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(),