diff --git a/src/con.rs b/src/con.rs index 66dc632..b34f5dd 100644 --- a/src/con.rs +++ b/src/con.rs @@ -210,42 +210,21 @@ fn maybe_html_escape(do_it: bool, text: &str) -> String { impl<'a> DisplayFormat for Window<'a> { fn format_for_display(&self, cfg: &cfg::Config) -> String { - let default_format = cfg::Format::default(); - let fmt = cfg - .format - .as_ref() - .and_then(|f| f.window_format.as_ref()) - .unwrap_or_else(|| default_format.window_format.as_ref().unwrap()); - let urgency_start = cfg - .format - .as_ref() - .and_then(|f| f.urgency_start.as_ref()) - .unwrap_or_else(|| default_format.urgency_start.as_ref().unwrap()); - let urgency_end = cfg - .format - .as_ref() - .and_then(|f| f.urgency_end.as_ref()) - .unwrap_or_else(|| default_format.urgency_end.as_ref().unwrap()); - let html_escape = cfg - .format - .as_ref() - .and_then(|f| f.html_escape) - .unwrap_or_else(|| default_format.html_escape.unwrap()); - let icon_dirs = cfg - .format - .as_ref() - .and_then(|f| f.icon_dirs.as_ref()) - .unwrap_or_else(|| default_format.icon_dirs.as_ref().unwrap()); + let window_format = cfg.get_format_window_format(); + let urgency_start = cfg.get_format_urgency_start(); + let urgency_end = cfg.get_format_urgency_end(); + let html_escape = cfg.get_format_html_escape(); + let icon_dirs = cfg.get_format_icon_dirs(); // fallback_icon has no default value. - let fallback_icon: Option<&String> = - cfg.format.as_ref().and_then(|f| f.fallback_icon.as_ref()); + let fallback_icon = cfg.get_format_fallback_icon(); // Some apps report, e.g., Gimp-2.10 but the icon is still named // gimp.png. let app_name_no_version = APP_NAME_AND_VERSION_RX.replace(self.get_app_name(), "$1"); - fmt.replace("{id}", format!("{}", self.get_id()).as_str()) + window_format + .replace("{id}", format!("{}", self.get_id()).as_str()) .replace( "{urgency_start}", if self.is_urgent() { @@ -279,15 +258,17 @@ impl<'a> DisplayFormat for Window<'a> { ) .replace( "{app_icon}", - util::get_icon(self.get_app_name(), icon_dirs) - .or_else(|| util::get_icon(&app_name_no_version, icon_dirs)) + util::get_icon(self.get_app_name(), &icon_dirs) + .or_else(|| { + util::get_icon(&app_name_no_version, &icon_dirs) + }) .or_else(|| { util::get_icon( &app_name_no_version.to_lowercase(), - icon_dirs, + &icon_dirs, ) }) - .or_else(|| fallback_icon.map(|f| f.to_string())) + .or(fallback_icon) .unwrap_or_else(String::new) .as_str(), ) @@ -482,19 +463,8 @@ impl PartialOrd for Workspace<'_> { impl<'a> DisplayFormat for Workspace<'a> { fn format_for_display(&self, cfg: &cfg::Config) -> String { - let default_format = cfg::Format::default(); - let fmt = cfg - .format - .as_ref() - .and_then(|f| f.workspace_format.as_ref()) - .unwrap_or_else(|| { - default_format.workspace_format.as_ref().unwrap() - }); - let html_escape = cfg - .format - .as_ref() - .and_then(|f| f.html_escape) - .unwrap_or_else(|| default_format.html_escape.unwrap()); + let fmt = cfg.get_format_workspace_format(); + let html_escape = cfg.get_format_html_escape(); fmt.replace("{id}", format!("{}", self.get_id()).as_str()) .replace("{name}", &maybe_html_escape(html_escape, self.get_name())) diff --git a/src/config.rs b/src/config.rs index f33d521..de7d04b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -25,32 +25,122 @@ use std::path::Path; #[derive(Debug, Serialize, Deserialize)] pub struct Config { - pub menu: Option, - pub format: Option, - pub layout: Option, + menu: Option, + format: Option, + layout: Option, +} + +impl Config { + pub fn get_menu_executable(&self) -> String { + self.menu + .as_ref() + .and_then(|m| m.executable.clone()) + .or_else(|| Menu::default().executable) + .expect("No menu.executable defined!") + } + + pub fn get_menu_args(&self) -> Vec { + self.menu + .as_ref() + .and_then(|m| m.args.clone()) + .or_else(|| Menu::default().args) + .expect("No menu.args defined.") + } + + pub fn get_format_window_format(&self) -> String { + self.format + .as_ref() + .and_then(|f| f.window_format.clone()) + .or_else(|| Format::default().window_format) + .expect("No format.window_format defined.") + } + + pub fn get_format_workspace_format(&self) -> String { + self.format + .as_ref() + .and_then(|f| f.workspace_format.clone()) + .or_else(|| Format::default().workspace_format) + .expect("No format.workspace_format defined.") + } + + pub fn get_format_urgency_start(&self) -> String { + self.format + .as_ref() + .and_then(|f| f.urgency_start.clone()) + .or_else(|| Format::default().urgency_start) + .expect("No format.urgency_start defined.") + } + + pub fn get_format_urgency_end(&self) -> String { + self.format + .as_ref() + .and_then(|f| f.urgency_end.clone()) + .or_else(|| Format::default().urgency_end) + .expect("No format.urgency_end defined.") + } + + pub fn get_format_html_escape(&self) -> bool { + self.format + .as_ref() + .and_then(|f| f.html_escape) + .or_else(|| Format::default().html_escape) + .expect("No format.html_escape defined.") + } + + pub fn get_format_icon_dirs(&self) -> Vec { + self.format + .as_ref() + .and_then(|f| f.icon_dirs.clone()) + .or_else(|| Format::default().icon_dirs) + .expect("No format.icon_dirs defined.") + } + + pub fn get_format_fallback_icon(&self) -> Option { + self.format + .as_ref() + .and_then(|f| f.fallback_icon.clone()) + .or_else(|| Format::default().fallback_icon) + } + + pub fn is_layout_auto_tile(&self) -> bool { + self.layout + .as_ref() + .and_then(|l| l.auto_tile) + .or_else(|| Layout::default().auto_tile) + .expect("No layout.auto_tile defined.") + } + + pub fn get_layout_auto_tile_min_window_width_per_output_width_as_map( + &self, + ) -> HashMap { + self.layout.as_ref() + .and_then(|l|l.auto_tile_min_window_width_per_output_width_as_map()) + .or_else(|| Layout::default().auto_tile_min_window_width_per_output_width_as_map()) + .expect("No layout.auto_tile_min_window_width_per_output_width defined.") + } } #[derive(Debug, Serialize, Deserialize)] pub struct Menu { - pub executable: Option, - pub args: Option>, + executable: Option, + args: Option>, } #[derive(Debug, Serialize, Deserialize)] pub struct Format { - pub window_format: Option, - pub workspace_format: Option, - pub urgency_start: Option, - pub urgency_end: Option, - pub html_escape: Option, - pub icon_dirs: Option>, - pub fallback_icon: Option, + window_format: Option, + workspace_format: Option, + urgency_start: Option, + urgency_end: Option, + html_escape: Option, + icon_dirs: Option>, + fallback_icon: Option, } #[derive(Debug, Serialize, Deserialize)] pub struct Layout { - pub auto_tile: Option, - pub auto_tile_min_window_width_per_output_width: Option>, + auto_tile: Option, + auto_tile_min_window_width_per_output_width: Option>, } impl Layout { diff --git a/src/demon.rs b/src/demon.rs index 064a837..bb198ab 100644 --- a/src/demon.rs +++ b/src/demon.rs @@ -50,7 +50,6 @@ pub fn monitor_sway_events( extra_props: Arc>>, ) { let config = config::load_config(); - let layout = config.layout.unwrap_or_else(config::Layout::default); 'reset: loop { println!("Connecting to sway for subscribing to events..."); @@ -70,7 +69,7 @@ pub fn monitor_sway_events( handled = handle_window_event( win_ev, extra_props_clone, - &layout, + &config, ); } s::Event::Workspace(ws_ev) => { @@ -103,43 +102,35 @@ pub fn monitor_sway_events( } } -fn maybe_auto_tile(layout: &config::Layout) { - if layout.auto_tile == Some(true) { - println!("\nauto_tile: start"); - layout::auto_tile(layout); - println!("auto_tile: end\n"); - } -} - fn handle_window_event( ev: Box, extra_props: Arc>>, - layout: &config::Layout, + config: &config::Config, ) -> bool { let s::WindowEvent { change, container, .. } = *ev; match change { s::WindowChange::Focus => { - maybe_auto_tile(layout); + layout::maybe_auto_tile(config); update_last_focus_time(container.id, extra_props); println!("Handled window event type {:?}", change); true } s::WindowChange::New => { - maybe_auto_tile(layout); + layout::maybe_auto_tile(config); update_last_focus_time(container.id, extra_props); println!("Handled window event type {:?}", change); true } s::WindowChange::Close => { remove_extra_props(container.id, extra_props); - maybe_auto_tile(layout); + layout::maybe_auto_tile(config); println!("Handled window event type {:?}", change); true } s::WindowChange::Move | s::WindowChange::Floating => { - maybe_auto_tile(layout); + layout::maybe_auto_tile(config); println!("Handled window event type {:?}", change); false // We don't affect the extra_props state here. } diff --git a/src/layout.rs b/src/layout.rs index 6c34153..6c83ff7 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -20,14 +20,12 @@ use crate::con::NodeMethods; use crate::config; use swayipc as s; -pub fn auto_tile(layout: &config::Layout) { +pub fn auto_tile(cfg: &config::Config) { if let Ok(mut con) = s::Connection::new() { if let Ok(tree) = con.get_tree() { - let config_map = - layout.auto_tile_min_window_width_per_output_width_as_map(); - let default_map = config::Layout::default() - .auto_tile_min_window_width_per_output_width_as_map() - .unwrap(); + let config_map = cfg + .get_layout_auto_tile_min_window_width_per_output_width_as_map( + ); for output in &tree.nodes { println!("output: {:?}", output.name); @@ -41,10 +39,7 @@ pub fn auto_tile(layout: &config::Layout) { } let output_width = output.rect.width; - let min_window_width = &config_map - .as_ref() - .unwrap_or(&default_map) - .get(&output_width); + let min_window_width = &config_map.get(&output_width); if let Some(min_window_width) = min_window_width { for container in @@ -115,3 +110,11 @@ pub fn auto_tile(layout: &config::Layout) { eprintln!("Couldn't get connection for auto_tile"); } } + +pub fn maybe_auto_tile(config: &config::Config) { + if config.is_layout_auto_tile() { + println!("\nauto_tile: start"); + auto_tile(config); + println!("auto_tile: end\n"); + } +} diff --git a/src/util.rs b/src/util.rs index 2a766ee..6bf059f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -212,27 +212,19 @@ where map.insert(s, c); } - let menu_default = cfg::Menu::default(); - let menu_exec = cfg - .menu - .as_ref() - .and_then(|l| l.executable.as_ref()) - .unwrap_or_else(|| menu_default.executable.as_ref().unwrap()); + let menu_exec = cfg.get_menu_executable(); let args: Vec = cfg - .menu - .as_ref() - .and_then(|l| l.args.as_ref()) - .unwrap_or_else(|| menu_default.args.as_ref().unwrap()) + .get_menu_args() .iter() .map(|a| a.replace("{prompt}", prompt)) .collect(); - let mut menu = proc::Command::new(menu_exec) + let mut menu = proc::Command::new(&menu_exec) .args(args) .stdin(proc::Stdio::piped()) .stdout(proc::Stdio::piped()) .spawn() - .expect(&("Error running ".to_owned() + menu_exec)); + .expect(&("Error running ".to_owned() + &menu_exec)); { let stdin = menu