Add basic support for config files

This commit is contained in:
Artemis Tosini 2020-06-04 03:05:45 +00:00
parent f08d1bdc7d
commit 7db23d0a70
Signed by: artemist
GPG key ID: EE5227935FE3FF18
7 changed files with 292 additions and 9 deletions

155
Cargo.lock generated
View file

@ -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"

View file

@ -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

12
config.toml.example Normal file
View file

@ -0,0 +1,12 @@
[[tile]]
type = "load"
[[tile]]
type = "memory"
[[tile]]
type = "hostname"
[[tile]]
type = "time"
format = "%Y-%m-%dT%H:%M:%S"

92
src/config.rs Normal file
View file

@ -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<u32>,
}
#[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<str>,
#[default("%H:%M:%S")]
pub short_format: Box<str>,
}
#[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<PathBuf>,
}
pub async fn read_config() -> Result<Config, Box<dyn std::error::Error>> {
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<dyn TileModule> {
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)),
}
}

View file

@ -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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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<tile::Tile> = 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? {}
}

View file

@ -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<TileData>) -> io::Result<Infallible> {
pub async fn launch(
num_tiles: usize,
mut receiver: Receiver<TileData>,
_default: DefaultSection,
) -> io::Result<Infallible> {
let mut stdout = io::stdout();
stdout.write_all(b"{ \"version\": 1 }\n[").await?;

View file

@ -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<Local>) -> Block {
Block {
full_text: time.format(&self.format).to_string().into(),