From 7db23d0a701b10cdebe3311ee00e93c5a11421e2 Mon Sep 17 00:00:00 2001 From: Artemis Tosini Date: Thu, 4 Jun 2020 03:05:45 +0000 Subject: [PATCH] Add basic support for config files --- Cargo.lock | 155 ++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 7 ++ config.toml.example | 12 ++++ src/config.rs | 92 ++++++++++++++++++++++++++ src/main.rs | 20 +++--- src/output.rs | 7 +- src/tiles/time.rs | 8 +++ 7 files changed, 292 insertions(+), 9 deletions(-) create mode 100644 config.toml.example create mode 100644 src/config.rs diff --git a/Cargo.lock b/Cargo.lock index 4f2ef07..5009b62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi 0.3.8", +] + [[package]] name = "arc-swap" version = "0.4.6" @@ -17,6 +26,17 @@ dependencies = [ "syn", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.8", +] + [[package]] name = "autocfg" version = "1.0.0" @@ -52,6 +72,21 @@ dependencies = [ "time", ] +[[package]] +name = "clap" +version = "2.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "dbus" version = "0.8.3" @@ -202,6 +237,15 @@ dependencies = [ "wasi", ] +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.1.13" @@ -426,6 +470,32 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" +[[package]] +name = "proc-macro-error" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "syn-mid", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.16" @@ -514,7 +584,9 @@ dependencies = [ "serde", "serde_json", "smart-default", + "structopt", "tokio", + "toml", "uuid", ] @@ -594,6 +666,36 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "structopt" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "syn" version = "1.0.28" @@ -605,6 +707,26 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "syn-mid" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "time" version = "0.1.43" @@ -650,6 +772,27 @@ dependencies = [ "syn", ] +[[package]] +name = "toml" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-segmentation" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" + [[package]] name = "unicode-xid" version = "0.2.0" @@ -665,6 +808,18 @@ dependencies = [ "rand", ] +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index a03e466..006f0dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,12 @@ dbus-tokio = "0.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" smart-default = "0.6" +structopt = "0.3" tokio = { version = "0.2", features = ["full"] } +toml = "0.5" uuid = { version = "0.8", features = [ "v4" ] } + +[profile.release] +incremental = false +codegen-units = 1 +lto = true diff --git a/config.toml.example b/config.toml.example new file mode 100644 index 0000000..873a12e --- /dev/null +++ b/config.toml.example @@ -0,0 +1,12 @@ +[[tile]] +type = "load" + +[[tile]] +type = "memory" + +[[tile]] +type = "hostname" + +[[tile]] +type = "time" +format = "%Y-%m-%dT%H:%M:%S" diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..943fe71 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,92 @@ +use crate::tile::TileModule; +use crate::tiles; +use serde::Deserialize; +use smart_default::SmartDefault; +use std::env::var; +use std::io; +use std::path::PathBuf; +use structopt::StructOpt; +use tokio::fs::File; +use tokio::prelude::*; + +#[derive(Deserialize, Clone, Debug, Default)] +#[serde(default)] +pub struct Config { + pub default: DefaultSection, + pub tile: Box<[TileConfig]>, +} + +#[derive(Deserialize, Clone, Debug, Default)] +pub struct DefaultSection { + pub spacing: Option, +} + +#[derive(Deserialize, Clone, Debug)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum TileConfig { + Memory, + Load, + Hostname, + Time(TimeConfig), +} + +#[derive(SmartDefault, Deserialize, Clone, Debug)] +#[serde(default)] +pub struct TimeConfig { + #[default("%Y-%m-%d %H:%M:%S")] + pub format: Box, + #[default("%H:%M:%S")] + pub short_format: Box, +} + +#[derive(Debug, StructOpt)] +#[structopt( + name = "rustybar", + about = "Something to exec for your swaybar or i3bar" +)] +struct Args { + /// Configuration file, default is $XDG_CONFIG_HOME/rustybar/config.toml + #[structopt(short, long, parse(from_os_str))] + pub config: Option, +} + +pub async fn read_config() -> Result> { + let args = Args::from_args(); + let config_path = match args.config { + Some(config) => config, + None => { + if let Ok(rustybar_config_env) = var("RUSTYBAR_CONFIG") { + rustybar_config_env.into() + } else if let Ok(xdg_config_home) = var("XDG_CONFIG_HOME") { + [&xdg_config_home, "rustybar", "config.toml"] + .iter() + .collect() + } else if let Ok(home) = var("HOME") { + [&home, ".config", "rustybar", "config.toml"] + .iter() + .collect() + } else { + return Err(Box::new(io::Error::new( + io::ErrorKind::NotFound, + "Could not find RUSTYBAR_CONFIG, XDG_CONFIG_HOME, or HOME environment variables" + ))); + } + } + }; + + let mut config_contents = vec![]; + File::open(config_path) + .await? + .read_to_end(&mut config_contents) + .await?; + Ok(toml::from_slice(&config_contents)?) +} + +pub fn process_tile(tile: &TileConfig) -> Box { + match tile { + TileConfig::Load => Box::new(tiles::Hostname::new()), + TileConfig::Memory => Box::new(tiles::Memory::new()), + TileConfig::Hostname => Box::new(tiles::Hostname::new()), + TileConfig::Time(c) => Box::new(tiles::Time::from_config(c)), + } +} diff --git a/src/main.rs b/src/main.rs index 2cba43f..e92eced 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +pub mod config; pub mod output; pub mod tile; pub mod tiles; @@ -8,6 +9,8 @@ use uuid::Uuid; #[tokio::main] async fn main() -> Result<(), Box> { + let config = config::read_config().await?; + // We can't do much until we have a D-Bus connection so just do it synchronously let (resource, _conn) = new_session_sync()?; @@ -20,7 +23,7 @@ async fn main() -> Result<(), Box> { let (sender, receiver) = channel(1024); let mut index = 0usize; - let mut wrap = |module| { + let wrap = |module| { let tile = tile::Tile::new( index, sender.clone(), @@ -30,17 +33,18 @@ async fn main() -> Result<(), Box> { index += 1; tile }; - let tiles = vec![ - wrap(Box::new(tiles::Load::new())), - wrap(Box::new(tiles::Memory::new())), - wrap(Box::new(tiles::Hostname::new())), - wrap(Box::new(tiles::Time::new())), - ]; + + let tiles: Vec = config + .tile + .iter() + .map(config::process_tile) + .map(wrap) + .collect(); let num_tiles = tiles.len(); for tile in tiles.into_iter() { tile.spawn(); } - match output::launch(num_tiles, receiver).await? {} + match output::launch(num_tiles, receiver, config.default).await? {} } diff --git a/src/output.rs b/src/output.rs index 9bf8e14..0145896 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,9 +1,14 @@ +use crate::config::DefaultSection; use crate::tile::TileData; use std::convert::Infallible; use tokio::io::{self, AsyncWriteExt}; use tokio::sync::mpsc::Receiver; -pub async fn launch(num_tiles: usize, mut receiver: Receiver) -> io::Result { +pub async fn launch( + num_tiles: usize, + mut receiver: Receiver, + _default: DefaultSection, +) -> io::Result { let mut stdout = io::stdout(); stdout.write_all(b"{ \"version\": 1 }\n[").await?; diff --git a/src/tiles/time.rs b/src/tiles/time.rs index 5f42d70..773ffd1 100644 --- a/src/tiles/time.rs +++ b/src/tiles/time.rs @@ -1,3 +1,4 @@ +use crate::config::TimeConfig; use crate::tile::{Block, BlockSender, TileModule}; use async_trait::async_trait; use chrono::prelude::*; @@ -16,6 +17,13 @@ impl Time { Default::default() } + pub fn from_config(config: &TimeConfig) -> Time { + Time { + format: config.format.clone(), + short_format: config.short_format.clone(), + } + } + fn send_time(&mut self, time: DateTime) -> Block { Block { full_text: time.format(&self.format).to_string().into(),