瀏覽代碼

Hacky port for i3bar

Thomas Dy 9 年之前
父節點
當前提交
71c211459c
共有 8 個文件被更改,包括 53 次插入158 次删除
  1. 1 0
      Cargo.toml
  2. 0 79
      src/bar.rs
  3. 38 0
      src/events.rs
  4. 0 64
      src/external.rs
  5. 10 11
      src/main.rs
  6. 1 1
      src/music.rs
  7. 2 2
      src/sensors/mod.rs
  8. 1 1
      src/store.rs

+ 1 - 0
Cargo.toml

@@ -7,3 +7,4 @@ authors = ["Thomas Dy <thatsmydoing@gmail.com>"]
 time = "0.1"
 toml = "0.1"
 mpd = "0.0.11"
+rustc-serialize = "0.3"

+ 0 - 79
src/bar.rs

@@ -1,79 +0,0 @@
-use config::Config;
-use std::io::prelude::*;
-use std::io::BufReader;
-use std::process::{ChildStdin, ChildStdout, Command, Stdio};
-use std::thread;
-
-pub struct Bar {
-    stdin: ChildStdin
-}
-
-impl Bar {
-    pub fn new(top: bool, cfg: &Config) -> Bar {
-        let val = cfg.lookup("bar.fonts").unwrap();
-        let fonts = val.as_slice().unwrap();
-        let fonts = fonts.iter().flat_map(|elem| elem.as_str());
-
-        let mut bar = Command::new("lemonbar");
-        bar.stdin(Stdio::piped());
-        bar.stdout(Stdio::piped());
-
-        if !top {
-            bar.arg("-b");
-        }
-
-        for font in fonts {
-            bar.arg("-f");
-            bar.arg(font);
-        }
-
-        let child = bar.spawn()
-            .ok()
-            .expect("Failed to start lemonbar");
-
-        let stdout = child.stdout.unwrap();
-        Bar::read_loop(stdout);
-
-        Bar { stdin: child.stdin.unwrap() }
-    }
-
-    fn read_loop(stdout: ChildStdout) {
-        thread::spawn(move || {
-            let mut s = String::new();
-            let mut reader = BufReader::new(stdout);
-            loop {
-                s.clear();
-                reader.read_line(&mut s).ok().expect("Failed to read from lemonbar");
-
-                let mut chars = s.trim().chars();
-                let kind = chars.next().unwrap();
-                let name = chars.collect::<String>();
-
-                match kind {
-                    'w' => Command::new("bspc")
-                        .arg("desktop")
-                        .arg("-f")
-                        .arg(&name)
-                        .output()
-                        .ok(),
-
-                    'c' => Command::new("cmus-remote")
-                        .arg("--pause")
-                        .output()
-                        .ok(),
-
-                    'm' => Command::new("mpc")
-                        .arg("toggle")
-                        .output()
-                        .ok(),
-
-                    _ => None
-                };
-            }
-        });
-    }
-
-    pub fn send(&mut self, text: &str) {
-        writeln!(&mut self.stdin, "{}", text).ok();
-    }
-}

+ 38 - 0
src/events.rs

@@ -0,0 +1,38 @@
+use comm::Channel;
+use config::Config;
+use rustc_serialize::json;
+use std::io;
+use std::process::Command;
+
+#[allow(dead_code)]
+#[derive(RustcDecodable)]
+struct I3Event {
+    name: Option<String>,
+    instance: Option<String>,
+    button: u32,
+    x: u32,
+    y: u32
+}
+
+pub fn handle(_tx: &Channel, _cfg: &Config) {
+    let mut line = String::new();
+
+    // read opening [
+    io::stdin().read_line(&mut line).ok().expect("Failed to read line");
+    loop {
+        line.clear();
+        io::stdin().read_line(&mut line).ok().expect("Failed to read line");
+
+        // the input has commas because it's supposed to be an endless array
+        // of click events but we don't really care about it
+        let event: I3Event = json::decode(line.trim_matches(',')).unwrap();
+
+        match event.name.as_ref().map(String::as_ref) {
+            Some("mpd") => Command::new("mpc")
+                .arg("toggle")
+                .output()
+                .ok(),
+            _ => None
+        };
+    }
+}

+ 0 - 64
src/external.rs

@@ -1,64 +0,0 @@
-use comm;
-use comm::Channel;
-use config::Config;
-use std::io;
-
-pub fn external(tx: &Channel, _cfg: &Config) {
-    let mut line = String::new();
-    loop {
-        line.clear();
-        io::stdin().read_line(&mut line).ok().expect("Failed to read line");
-        let kind = line.remove(0);
-        let line = line.trim();
-
-        match kind {
-            'T' => comm::send(tx, "title", line),
-            'M' => comm::send(tx, "cmus", &format!("%{{A:cmus:}}{}%{{A}}", line)),
-            'W' => comm::send(tx, "desktops", &parse_bspwm(line)),
-            _ => ()
-        }
-    }
-}
-
-fn parse_bspwm(line: &str) -> String {
-    let mut out = String::new();
-    let mut monitor_count = 0;
-    let mut monitor_selected = false;
-
-    let elems = line.split(':');
-    for elem in elems {
-        let mut chars = elem.chars();
-        let kind = chars.next().unwrap();
-        let name = chars.collect::<String>();
-
-        if kind == 'M' || kind == 'm' {
-            out = format!("{}%{{S{num}}}", out, num = monitor_count);
-            monitor_count += 1;
-            monitor_selected = kind.is_uppercase();
-        }
-        else if kind == 'L' {
-        }
-        else if kind == 'G' {
-        }
-        else if kind == 'T' {
-        }
-        else {
-            let desktop = format!("%{{A:w{name}:}} {name} %{{A}}", name = name);
-            if kind.is_uppercase() {
-                if monitor_selected {
-                    out = format!("{}%{{B#66CC66}}{}%{{B-}}", out, desktop);
-                }
-                else {
-                    out = format!("{}%{{B#666666}}{}%{{B-}}", out, desktop);
-                }
-            }
-            else if kind == 'U' || kind == 'u' {
-                out = format!("{}%{{B#CC0033}}{}%{{B-}}", out, desktop);
-            }
-            else if kind == 'O' || kind == 'o' {
-                out = format!("{}{}", out, desktop);
-            }
-        }
-    }
-    out
-}

+ 10 - 11
src/main.rs

@@ -1,8 +1,9 @@
+extern crate rustc_serialize;
+
 mod sensors;
 mod comm;
 mod config;
-mod external;
-mod bar;
+mod events;
 mod store;
 mod music;
 
@@ -17,27 +18,25 @@ fn main() {
     let config_path = env::args().nth(1).unwrap_or("./panel.toml".to_string());
     let cfg = config::load(&config_path);
 
-    let mut topbar = bar::Bar::new(true, &cfg);
-    let mut botbar = bar::Bar::new(false, &cfg);
-
     let cfg = Arc::new(cfg);
     let (tx, rx) = mpsc::channel::<Message>();
-    make_thread(&tx, &cfg, external::external);
+    make_thread(&tx, &cfg, events::handle);
     make_thread(&tx, &cfg, sensors::sensors);
     make_thread(&tx, &cfg, music::music);
 
     let mut data = store::Store::new();
 
+    // i3bar header
+    println!("{{\"version\": 1,\"click_events\":true}}");
+    println!("[");
     loop {
         let msg = rx.recv().unwrap();
         data.save(msg);
 
-        topbar.send(&format!("{}| {}%{{r}}{}",
-            data.get("desktops"),
-            data.get("title"),
+        println!("[{},{}],",
+            data.get("mpd"),
             data.get("sensors")
-        ));
-        botbar.send(&format!("{}", data.get("mpd")));
+        );
     }
 }
 

+ 1 - 1
src/music.rs

@@ -21,7 +21,7 @@ pub fn music(tx: &Channel, _cfg: &Config) {
         let song = conn.currentsong().unwrap();
         let stopped = "Stopped".to_string();
         let display = song.as_ref().map(get_display).unwrap_or(stopped);
-        comm::send(tx, "mpd", &format!("%{{A:mpd:}}{} {}%{{A}}", state, display));
+        comm::send(tx, "mpd", &format!("{{\"name\":\"mpd\",\"separator\":false,\"markup\":\"pango\",\"align\":\"left\",\"full_text\":\"<span face=\\\"Ionicons\\\">{}</span> {}\"}}", state, display));
         conn.wait(&[idle::Subsystem::Player]).ok();
     }
 }

+ 2 - 2
src/sensors/mod.rs

@@ -54,7 +54,7 @@ pub fn sensors(tx: &Channel, config: &Config) {
             .map(|sensor| {
                 sensor.process();
                 format!(
-                    "%{{B#666666}} {} %{{B-}} {}",
+                    "{{\"separator\":false,\"markup\":\"pango\",\"full_text\":\"<span bgcolor=\\\"#666666\\\"> <span face=\\\"Ionicons\\\">{}</span> </span> {}\"}}",
                     sensor.icon(),
                     sensor.status()
                 )
@@ -67,5 +67,5 @@ pub fn sensors(tx: &Channel, config: &Config) {
 }
 
 fn reduce(arr: Vec<String>) -> String {
-    arr.into_iter().fold("".to_string(), |acc, elem| format!("{} {}", acc, elem))
+    arr.join(",")
 }

+ 1 - 1
src/store.rs

@@ -17,7 +17,7 @@ impl Store {
     pub fn get(&self, kind: &str) -> &str {
         match self.data.get(kind) {
             Some(res) => res,
-            None => ""
+            None => "{\"full_text\":\"\"}"
         }
     }
 }