From 1b6c9e46be4733f2a8a5f47e98a84a4433731178 Mon Sep 17 00:00:00 2001 From: redxef Date: Sun, 15 Oct 2023 01:18:00 +0200 Subject: [PATCH] Add argument parsing and default config file. --- Cargo.toml | 1 + src/main.rs | 46 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7c18d2a..b034ae7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,4 @@ serde = { version = "1.0.188", features = ["std", "derive", "serde_derive"] } serde_json = "1.0.107" serde_yaml = "0.9.25" tokio = { version = "1.33.0", features = ["full"] } +xdg = "2.5.2" diff --git a/src/main.rs b/src/main.rs index f633986..11b83c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,8 @@ use tokio::time::{timeout, Duration}; use tokio::io::AsyncReadExt; use clap::Parser; use log::{info, debug, warn}; +use std::path::PathBuf; +use std::str::FromStr; mod config; mod i3ipc; @@ -16,6 +18,17 @@ use i3ipc::{Connection, MessageType}; #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Args { + #[arg(short, long, value_name = "FILE")] + config: Option, +} + +impl Args { + fn finish(&mut self) { + // TODO maybe return separate type + if self.config.is_none() { + self.config = Some(xdg::BaseDirectories::with_prefix("i3toolwait").unwrap().get_config_file("config.yaml")); + } + } } fn new_window_cb( @@ -45,13 +58,24 @@ fn new_window_cb( } async fn run<'a>(connection: &mut Connection<'a>, config: &Config) -> Result<(), anyhow::Error> { - let resp = connection.communicate(&MessageType::Version, b"").await?; - println!("{:?}", resp); + let (_, resp) = connection.communicate(&MessageType::Version, b"").await?; + info!("i3 version is {}", resp.get("human_readable").unwrap()); for p in config.programs.iter() { if let Some(r) = &p.run { - let (message_type, response) = connection.communicate(&MessageType::Command, r.as_bytes()).await?; - println!("{:?}", (message_type, response)); + let (_, responses) = connection.communicate(&MessageType::Command, r.as_bytes()).await?; + match responses { + serde_json::Value::Array(responses) => { + for response in responses { + if let serde_json::Value::Bool(v) = response.get("success").unwrap() { + if !v { + warn!("Failed to run command {}: {}", r, response); + } + } + } + }, + _ => panic!("invalid response"), + }; } } Ok(()) @@ -59,16 +83,22 @@ async fn run<'a>(connection: &mut Connection<'a>, config: &Config) -> Result<(), #[tokio::main] async fn main() -> Result<()> { - let args = std::sync::Arc::new(Args::parse()); env_logger::init_from_env(env_logger::Env::new().filter("I3TOOLWAIT_LOG").write_style("I3TOOLWAIT_LOG_STYLE")); - let mut connection = Connection::connect((i3ipc::get_socket_path().await?).as_ref())?; - let mut sub_connection = connection.clone(); + let mut args = Args::parse(); + args.finish(); + let args = std::sync::Arc::new(args); let mut config = String::new(); - tokio::fs::File::open("/home/redxef/CODE/i3toolwait/i3_autostart.yaml").await?.read_to_string(&mut config).await?; + if args.config.as_ref().unwrap() == &PathBuf::from_str("-").unwrap() { + tokio::io::stdin().read_to_string(&mut config).await?; + } else { + tokio::fs::File::open(args.config.as_ref().unwrap()).await?.read_to_string(&mut config).await?; + } let config: Config = serde_yaml::from_str(&config)?; let config = std::sync::Arc::new(config); + let mut connection = Connection::connect((i3ipc::get_socket_path().await?).as_ref())?; + let mut sub_connection = connection.clone(); let cb_config = config.clone(); let cb_args = args.clone(); let cb = move |a, b| {new_window_cb(a, b, &cb_config, &cb_args)};