diff --git a/swayr/src/shared/cfg.rs b/swayr/src/shared/cfg.rs index 428c644..5985710 100644 --- a/swayr/src/shared/cfg.rs +++ b/swayr/src/shared/cfg.rs @@ -87,6 +87,9 @@ where .arg("Thanks!") .spawn() .ok(); + log::debug!("Created new config in {}.", path.to_string_lossy()); + } else { + log::debug!("Loaded config from {}.", path.to_string_lossy()); } let mut file = OpenOptions::new() .read(true) @@ -96,5 +99,12 @@ where .unwrap(); let mut buf: String = String::new(); file.read_to_string(&mut buf).unwrap(); - toml::from_str::(&buf).expect("Invalid config.") + match toml::from_str::(&buf) { + Ok(cfg) => cfg, + Err(err) => { + log::error!("Invalid config: {}", err); + log::error!("Using default configuration."); + T::default() + } + } } diff --git a/swayr/src/shared/fmt.rs b/swayr/src/shared/fmt.rs index 4616aa1..f317069 100644 --- a/swayr/src/shared/fmt.rs +++ b/swayr/src/shared/fmt.rs @@ -22,6 +22,7 @@ use std::fmt; pub enum FmtArg { I64(i64), + I32(i32), F64(f64), F32(f32), String(String), @@ -33,6 +34,12 @@ impl From for FmtArg { } } +impl From for FmtArg { + fn from(x: i32) -> FmtArg { + FmtArg::I32(x) + } +} + impl From for FmtArg { fn from(x: f64) -> FmtArg { FmtArg::F64(x) @@ -62,6 +69,7 @@ impl ToString for FmtArg { match self { FmtArg::String(x) => x.clone(), FmtArg::I64(x) => x.to_string(), + FmtArg::I32(x) => x.to_string(), FmtArg::F64(x) => x.to_string(), FmtArg::F32(x) => x.to_string(), } @@ -77,6 +85,7 @@ impl FormatArgument for FmtArg { match self { Self::String(val) => fmt::Display::fmt(&val, f), Self::I64(val) => fmt::Display::fmt(&val, f), + Self::I32(val) => fmt::Display::fmt(&val, f), Self::F64(val) => fmt::Display::fmt(&val, f), Self::F32(val) => fmt::Display::fmt(&val, f), } diff --git a/swayrbar/src/bar.rs b/swayrbar/src/bar.rs index 1d4da55..ffcbc7c 100644 --- a/swayrbar/src/bar.rs +++ b/swayrbar/src/bar.rs @@ -101,7 +101,10 @@ fn handle_click( for m in mods.iter() { if let Some(on_click) = m.get_on_click_map(&name, &instance) { if let Some(cmd) = on_click.get(&button_str) { - execute_command(cmd); + match m.subst_args(cmd) { + Some(cmd) => execute_command(&cmd), + None => execute_command(cmd), + } return Some(()); } } @@ -111,6 +114,7 @@ fn handle_click( } fn execute_command(cmd: &[String]) { + log::debug!("Executing cmd: {:?}", cmd); match p::Command::new(&cmd[0]).args(&cmd[1..]).spawn() { Ok(_child) => (), Err(err) => { diff --git a/swayrbar/src/module.rs b/swayrbar/src/module.rs index 0324ea4..7fba67b 100644 --- a/swayrbar/src/module.rs +++ b/swayrbar/src/module.rs @@ -44,4 +44,8 @@ pub trait BarModuleFn: Sync + Send { } } fn build(&self) -> s::Block; + fn subst_args<'a>(&'a self, _cmd: &'a [String]) -> Option> { + // None means, no substitution are to be made. + None + } } diff --git a/swayrbar/src/module/window.rs b/swayrbar/src/module/window.rs index e2696a7..2da3c39 100644 --- a/swayrbar/src/module/window.rs +++ b/swayrbar/src/module/window.rs @@ -16,6 +16,7 @@ //! The window `swayrbar` module. use std::collections::HashMap; +use std::sync::Mutex; use crate::config; use crate::module::BarModuleFn; @@ -28,11 +29,15 @@ const NAME: &str = "window"; pub struct BarModuleWindow { config: config::ModuleConfig, + pid: Mutex, } impl BarModuleFn for BarModuleWindow { fn create(config: config::ModuleConfig) -> Box { - Box::new(BarModuleWindow { config }) + Box::new(BarModuleWindow { + config, + pid: Mutex::new(0), + }) } fn default_config(instance: String) -> config::ModuleConfig { @@ -41,13 +46,19 @@ impl BarModuleFn for BarModuleWindow { instance, format: "🪟 {title} — {app_name}".to_owned(), html_escape: Some(false), - on_click: Some(HashMap::from([( - "Left".to_owned(), - vec![ - "swayr".to_owned(), - "switch-to-urgent-or-lru-window".to_owned(), - ], - )])), + on_click: Some(HashMap::from([ + ( + "Left".to_owned(), + vec![ + "swayr".to_owned(), + "switch-to-urgent-or-lru-window".to_owned(), + ], + ), + ( + "Right".to_owned(), + vec!["kill".to_owned(), "{pid}".to_owned()], + ), + ])), } } @@ -62,10 +73,14 @@ impl BarModuleFn for BarModuleWindow { .find(|n| n.focused && n.get_type() == ipc::Type::Window); let text = match focused_win { Some(win) => { - format_placeholders!(&self.config.format, - self.config.is_html_escape(), { - "title" | "name" => win.get_name(), - "app_name" => win.get_app_name(), + let mut pid = self.pid.lock().expect("Couldn't lock pid!"); + *pid = win.pid.unwrap_or(-1); + format_placeholders!( + &self.config.format, + self.config.is_html_escape(), { + "title" | "name" => win.get_name(), + "app_name" => win.get_app_name(), + "pid" => *pid, }) } None => String::new(), @@ -90,4 +105,29 @@ impl BarModuleFn for BarModuleWindow { separator_block_width: None, } } + + fn get_on_click_map( + &self, + name: &str, + instance: &str, + ) -> Option<&HashMap>> { + let cfg = self.get_config(); + if name == cfg.name && instance == cfg.instance { + cfg.on_click.as_ref() + } else { + None + } + } + + fn subst_args<'a>(&'a self, cmd: &'a [String]) -> Option> { + let cmd = cmd + .iter() + .map(|arg| { + format_placeholders!(arg, false, { + "pid" => *self.pid.lock().expect("Could not lock pid."), + }) + }) + .collect(); + Some(cmd) + } }