Browse Source

Add the ability to use a TOML-based configuration file

Getty Ritter 4 years ago
parent
commit
9c7739678a
7 changed files with 110 additions and 85 deletions
  1. 16 0
      Cargo.lock
  2. 1 1
      Cargo.toml
  3. 10 0
      sample.toml
  4. 60 0
      src/config.rs
  5. 7 50
      src/main.rs
  6. 15 27
      src/widgets.rs
  7. 1 7
      src/window.rs

+ 16 - 0
Cargo.lock

@@ -139,6 +139,7 @@ dependencies = [
  "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "pango 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pangocairo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "x11 2.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -250,6 +251,11 @@ name = "rustc-demangle"
 version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "serde"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "syn"
 version = "0.15.29"
@@ -281,6 +287,14 @@ dependencies = [
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "toml"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "unicode-xid"
 version = "0.1.0"
@@ -342,9 +356,11 @@ dependencies = [
 "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
 "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
 "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
+"checksum serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "076a696fdea89c19d3baed462576b8f6d663064414b5c793642da8dfeb99475b"
 "checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2"
 "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
 "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
+"checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"

+ 1 - 1
Cargo.toml

@@ -8,10 +8,10 @@ edition = "2018"
 cairo-rs = "0.6"
 pango = "0.6"
 pangocairo = "0.7"
-# time = "0.1"
 chrono = "*"
 libc = "0.2"
 failure = "*"
+toml = "0.5"
 
 [dependencies.cairo-sys-rs]
 version = "0.8"

+ 10 - 0
sample.toml

@@ -0,0 +1,10 @@
+background = "ff0000"
+
+[[widgets]]
+name = "stdin"
+
+[[widgets]]
+name = "sep"
+
+[[widgets]]
+name = "time"

+ 60 - 0
src/config.rs

@@ -0,0 +1,60 @@
+use crate::widgets as w;
+
+pub struct Config {
+    left: Vec<Box<w::Widget>>,
+    right: Vec<Box<w::Widget>>,
+}
+
+impl Config {
+    pub fn from_toml(input: toml::Value) -> Result<Config, failure::Error> {
+        let mut conf = Config { left: Vec::new(), right: Vec::new() };
+        let widgets = &input.as_table().ok_or(format_err!("invalid config"))?["widgets"];
+        let mut target = &mut conf.left;
+        for section in widgets.as_array().ok_or(format_err!("invalid config"))? {
+            let section = section.as_table().ok_or(format_err!("invalid config"))?;
+            match section["name"].as_str().ok_or(format_err!(""))? {
+                "box" => target.push(Box::new(w::SmallBox)),
+                "battery" => target.push(Box::new(w::Battery::new()?)),
+                "sep" => target = &mut conf.right,
+                "stdin" => target.push(Box::new(w::Stdin::new())),
+                "time" => target.push(Box::new(w::Time::new())),
+                _ => (),
+            }
+        }
+        Ok(conf)
+    }
+
+    pub fn from_file(path: impl AsRef<std::path::Path>) -> Result<Config, failure::Error> {
+        let body = std::fs::read_to_string(path)?;
+        let val = body.parse::<toml::Value>()?;
+        Config::from_toml(val)
+    }
+
+    pub fn draw(&self, ctx: &cairo::Context, layout: &pango::Layout, stdin: &str, size: w::Size) -> Result<(), failure::Error>{
+        // the background is... gray-ish? this'll be configurable eventually
+        ctx.set_source_rgb(0.1, 0.1, 0.1);
+        ctx.paint();
+
+        // and the text is white
+        ctx.set_source_rgb(1.0, 1.0, 1.0);
+
+        // set up a struct with everything that widgets need to draw
+        let d = w::Drawing {
+            ctx: ctx,
+            lyt: &layout,
+            size,
+            stdin,
+        };
+
+        let mut offset = 10;
+        for w in self.left.iter() {
+            offset += 10 + w.draw(&d, w::Located::FromLeft(offset));
+        }
+        offset = 10;
+        for w in self.right.iter() {
+            offset += 10 + w.draw(&d, w::Located::FromRight(offset));
+        }
+
+        Ok(())
+    }
+}

+ 7 - 50
src/main.rs

@@ -1,17 +1,19 @@
 #[macro_use]
 extern crate failure;
 
+mod config;
 mod widgets;
 mod window;
 
 use std::os::unix::io::AsRawFd;
 use pango::LayoutExt;
 
-use widgets::Widget;
-use window::{Display,Event,Size,Window};
+use widgets::Size;
+use window::{Display,Event,Window};
 
 fn main() -> Result<(), failure::Error> {
     // set up the display and the window
+    let config = config::Config::from_file("sample.toml")?;
     let mut d = Display::create()?;
     let mut ws = Vec::new();
     for (x_off, wd) in d.get_widths()? {
@@ -77,7 +79,7 @@ fn main() -> Result<(), failure::Error> {
         layout.set_font_description(&font);
 
         // do an initial pass at drawing the bar!
-        draw(&ctx, &layout, &input, w.size())?;
+        config.draw(&ctx, &layout, &input, w.size())?;
 
         ctxs.push((ctx, layout, w.size()));
     }
@@ -116,7 +118,7 @@ fn main() -> Result<(), failure::Error> {
                 break;
             }
             for (ctx, layout, sz) in ctxs.iter() {
-                draw(&ctx, &layout, &input, *sz)?;
+                config.draw(&ctx, &layout, &input, *sz)?;
             }
         }
 
@@ -133,54 +135,9 @@ fn main() -> Result<(), failure::Error> {
 
         for (ctx, layout, sz) in ctxs.iter() {
             // otherwise, draw the thing!
-            draw(&ctx, &layout, &input, *sz)?;
+            config.draw(&ctx, &layout, &input, *sz)?;
         }
     }
 
     Ok(())
 }
-
-
-/// Do our Cairo drawing. This needs to be refactored to allow for
-/// more configurability in terms of what gets written!
-fn draw(
-    ctx: &cairo::Context,
-    layout: &pango::Layout,
-    left: &str,
-    size: Size)
-    -> Result<(), failure::Error>
-{
-    // the background is... gray-ish? this'll be configurable eventually
-    ctx.set_source_rgb(0.1, 0.1, 0.1);
-    ctx.paint();
-
-    // and the text is white
-    ctx.set_source_rgb(1.0, 1.0, 1.0);
-
-    // set up a struct with everything that widgets need to draw
-    let drawing = widgets::Drawing {
-        ctx: ctx,
-        lyt: &layout,
-        size,
-    };
-    // set up our widgets
-    let text = widgets::Text::new(left);
-    let time = widgets::Time::new();
-    // let bat = widgets::Battery::new()?;
-
-    // and create a 'config' which tells us which widgets to draw from
-    // the left, and which from the right
-    let config = widgets::Config {
-        left: vec![
-            &text as &Widget,
-        ],
-        right: vec![
-            // &bat as &Widget,
-            &time as &Widget,
-        ],
-    };
-    // and draw them!
-    config.draw(&drawing);
-
-    Ok(())
-}

+ 15 - 27
src/widgets.rs

@@ -1,30 +1,19 @@
-use crate::window::Size;
 use pango::LayoutExt;
 
+#[derive(Debug,Clone,Copy)]
+pub struct Size {
+    pub wd: i32,
+    pub ht: i32,
+    pub xo: i32,
+    pub yo: i32,
+}
+
 #[derive(Debug,Clone,Copy)]
 pub enum Located {
     FromLeft(i32),
     FromRight(i32),
 }
 
-pub struct Config<'r> {
-    pub left: Vec<&'r Widget>,
-    pub right: Vec<&'r Widget>,
-}
-
-impl<'r> Config<'r> {
-    pub fn draw(&self, d: &Drawing) {
-        let mut offset = 10;
-        for w in self.left.iter() {
-            offset += 10 + w.draw(d, Located::FromLeft(offset));
-        }
-        offset = 10;
-        for w in self.right.iter() {
-            offset += 10 + w.draw(d, Located::FromRight(offset));
-        }
-    }
-}
-
 impl Located {
     fn draw_text(&self, d: &Drawing, msg: &str) -> i32 {
         d.lyt.set_text(msg);
@@ -46,6 +35,7 @@ pub struct Drawing<'t> {
     pub ctx: &'t cairo::Context,
     pub lyt: &'t pango::Layout,
     pub size: Size,
+    pub stdin: &'t str,
 }
 
 pub trait Widget {
@@ -74,19 +64,17 @@ impl Widget for Time {
 
 
 #[derive(Debug)]
-pub struct Text<'t> {
-    text: &'t str,
-}
+pub struct Stdin;
 
-impl<'t> Text<'t> {
-    pub fn new(text: &str) -> Text {
-        Text { text }
+impl Stdin {
+    pub fn new() -> Stdin {
+        Stdin
     }
 }
 
-impl<'t> Widget for Text<'t> {
+impl Widget for Stdin {
     fn draw(&self, d: &Drawing, loc: Located) -> i32 {
-        loc.draw_text(d, &self.text)
+        loc.draw_text(d, &d.stdin)
     }
 }
 

+ 1 - 7
src/window.rs

@@ -4,13 +4,7 @@ use std::ffi::CString;
 use std::{mem,ptr};
 use std::os::raw::{c_int,c_uchar};
 
-#[derive(Debug,Clone,Copy)]
-pub struct Size {
-    pub wd: i32,
-    pub ht: i32,
-    pub xo: i32,
-    pub yo: i32,
-}
+use crate::widgets::Size;
 
 pub struct Display {
     pub display: *mut xlib::_XDisplay,