From 81bafedf363e6fcf3b1517cb47947038808702c5 Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Fri, 9 Jul 2021 21:55:55 +0200 Subject: [PATCH] New {marks} placeholder in window_format; format.html_escape config option --- README.md | 20 ++++++++++++-------- src/con.rs | 39 +++++++++++++++++++++++++++++++++++---- src/config.rs | 2 ++ 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a26a488..fff52fb 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ args = [ [format] window_format = '{urgency_start}“{title}”{urgency_end} — {app_name} on workspace {workspace_name} ({id})' workspace_format = 'Workspace {name} ({id})' +html_escape = true urgency_start = '' urgency_end = '' icon_dirs = [ @@ -154,7 +155,7 @@ icon_dirs = [ '/usr/share/icons/hicolor/48x48/apps', '/usr/share/pixmaps', ] -fallback_icon = '/usr/share/icons/gnome/48x48/apps/kwin.png' +fallback_icon = '/usr/share/pixmaps/archlinux-logo.png' ``` In the `[menu]` section, you can specify the menu program using the @@ -169,16 +170,19 @@ to style the text using HTML and CSS. The following formats are supported right now. * `window_format` defines how windows are displayed. The placeholder `{title}` is replaced with the window's title, `{app_name}` with the application name, - `{app_icon}` with the application's icon (a path to a PNG or SVG file), - `{workspace_name}` with the name or number of the workspace the window is - shown, and `{id}` is the window's sway-internal con id. There are also the - placeholders `{urcency_start}` and `{urgency_end}` which get replaced by the - empty string if the window has no urgency flag, and with the values of the - same-named formats if the window has the urgency flag set. That makes it - possible to highlight urgent windows as shown in the default config. + `{marks}` with a comma-separated list of the window's marks, `{app_icon}` + with the application's icon (a path to a PNG or SVG file), `{workspace_name}` + with the name or number of the workspace the window is shown, and `{id}` is + the window's sway-internal con id. There are also the placeholders + `{urcency_start}` and `{urgency_end}` which get replaced by the empty string + if the window has no urgency flag, and with the values of the same-named + formats if the window has the urgency flag set. That makes it possible to + highlight urgent windows as shown in the default config. * `workspace_format` defines how workspaces are displayed. There are the placeholders `{name}` which gets replaced by the workspace's number or name, and `{id}` which gets replaced by the sway-internal con id of the workspace. +* `html_escape` defines if the strings replacing the placeholders above (except + for `{urgency_start}` and `{urgency_end}`) should be HTML-escaped. * `urgency_start` is a string which replaces the `{urgency_start}` placeholder in `window_format`. * `urgency_end` is a string which replaces the `{urgency_end}` placeholder in diff --git a/src/con.rs b/src/con.rs index 5651b06..5d9a8ae 100644 --- a/src/con.rs +++ b/src/con.rs @@ -198,6 +198,14 @@ lazy_static! { regex::Regex::new("(.+)(-[0-9.]+)").unwrap(); } +fn maybe_html_escape(do_it: bool, text: &str) -> String { + if do_it { + text.replace("<", "<").replace(">", ">") + } else { + text.to_string() + } +} + impl<'a> DisplayFormat for Window<'a> { fn format_for_display(&self, cfg: &cfg::Config) -> String { let default_format = cfg::Format::default(); @@ -216,6 +224,11 @@ impl<'a> DisplayFormat for Window<'a> { .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() @@ -247,10 +260,20 @@ impl<'a> DisplayFormat for Window<'a> { "" }, ) - .replace("{app_name}", self.get_app_name()) + .replace( + "{app_name}", + &maybe_html_escape(html_escape, self.get_app_name()), + ) .replace( "{workspace_name}", - self.workspace.name.as_ref().unwrap().as_str(), + &maybe_html_escape( + html_escape, + self.workspace.name.as_ref().unwrap().as_str(), + ), + ) + .replace( + "{marks}", + &maybe_html_escape(html_escape, &self.node.marks.join(", ")), ) .replace( "{app_icon}", @@ -266,7 +289,10 @@ impl<'a> DisplayFormat for Window<'a> { .unwrap_or_else(String::new) .as_str(), ) - .replace("{title}", self.get_title()) + .replace( + "{title}", + &maybe_html_escape(html_escape, self.get_title()), + ) } } @@ -462,8 +488,13 @@ impl<'a> DisplayFormat for Workspace<'a> { .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()); fmt.replace("{id}", format!("{}", self.get_id()).as_str()) - .replace("{name}", self.get_name()) + .replace("{name}", &maybe_html_escape(html_escape, self.get_name())) } } diff --git a/src/config.rs b/src/config.rs index e8c101a..f33d521 100644 --- a/src/config.rs +++ b/src/config.rs @@ -42,6 +42,7 @@ pub struct Format { pub workspace_format: Option, pub urgency_start: Option, pub urgency_end: Option, + pub html_escape: Option, pub icon_dirs: Option>, pub fallback_icon: Option, } @@ -99,6 +100,7 @@ impl Default for Format { ({id})" .to_string(), ), + html_escape: Some(true), urgency_start: Some( "" .to_string(),