Add support for placeholders with truncation

timeout_old
Jakub Jirutka 3 years ago committed by Tassilo Horn
parent 6269feb654
commit cae756bab8
  1. 9
      NEWS.md
  2. 5
      README.md
  3. 68
      src/tree.rs

@ -1,3 +1,12 @@
swayr v0.13.0
=============
- The placeholders `{app_name}`, `{name}`, `{output_name}`, and
`{workspace_name}` allow to specify the maximum string length using format
`{<name>:<len>}` (e.g. `{app_name:10}`). If the string is longer than the
specified length, it will be truncated and an ellipsis ("…") will be inserted
at the end.
swayr v0.12.0 swayr v0.12.0
============= =============

@ -324,6 +324,11 @@ right now.
* `fallback_icon` is a path to some PNG/SVG icon which will be used as * `fallback_icon` is a path to some PNG/SVG icon which will be used as
`{app_icon}` if no application-specific icon can be determined. `{app_icon}` if no application-specific icon can be determined.
The placeholders `{app_name}`, `{name}`, `{output_name}`, and `{workspace_name}`
allow to specify the maximum string length using format `{<name>:<len>}` (e.g.
`{app_name:10}`). If the string is longer than the specified length, it will
be truncated and an ellipsis ("…") will be inserted at the end.
It is crucial that during selection (using wofi or some other menu program) It is crucial that during selection (using wofi or some other menu program)
each window has a different display string. Therefore, it is highly each window has a different display string. Therefore, it is highly
recommended to include the `{id}` placeholder at least in `container_format` recommended to include the `{id}` placeholder at least in `container_format`

@ -429,6 +429,11 @@ lazy_static! {
regex::Regex::new("(.+)(-[0-9.]+)").unwrap(); regex::Regex::new("(.+)(-[0-9.]+)").unwrap();
} }
lazy_static! {
static ref PLACEHOLDER_RX: regex::Regex =
regex::Regex::new(r"\{(?P<name>[^}:]+)(?::(?P<width>\d+))?\}").unwrap();
}
fn maybe_html_escape(do_it: bool, text: &str) -> String { fn maybe_html_escape(do_it: bool, text: &str) -> String {
if do_it { if do_it {
text.replace("<", "&lt;") text.replace("<", "&lt;")
@ -470,8 +475,8 @@ impl DisplayFormat for DisplayNode<'_> {
Type::Container => cfg.get_format_container_format(), Type::Container => cfg.get_format_container_format(),
Type::Window => cfg.get_format_window_format(), Type::Window => cfg.get_format_window_format(),
}; };
fmt.replace("{indent}", &indent.repeat(self.get_indent_level())) let fmt = fmt
.replace("{layout}", format!("{:?}", self.node.layout).as_str()) .replace("{indent}", &indent.repeat(self.get_indent_level()))
.replace("{id}", format!("{}", self.node.id).as_str()) .replace("{id}", format!("{}", self.node.id).as_str())
.replace( .replace(
"{marks}", "{marks}",
@ -496,28 +501,6 @@ impl DisplayFormat for DisplayNode<'_> {
"" ""
}, },
) )
.replace(
"{app_name}",
&maybe_html_escape(html_escape, self.node.get_app_name()),
)
.replace(
"{output_name}",
&maybe_html_escape(
html_escape,
self.tree
.get_parent_node_of_type(self.node.id, Type::Output)
.map_or("<no_output>", |w| w.get_name()),
),
)
.replace(
"{workspace_name}",
&maybe_html_escape(
html_escape,
self.tree
.get_parent_node_of_type(self.node.id, Type::Workspace)
.map_or("<no_workspace>", |w| w.get_name()),
),
)
.replace( .replace(
"{app_icon}", "{app_icon}",
util::get_icon(self.node.get_app_name(), &icon_dirs) util::get_icon(self.node.get_app_name(), &icon_dirs)
@ -534,15 +517,34 @@ impl DisplayFormat for DisplayNode<'_> {
.map(|i| i.to_string_lossy().into_owned()) .map(|i| i.to_string_lossy().into_owned())
.unwrap_or_else(String::new) .unwrap_or_else(String::new)
.as_str(), .as_str(),
) );
.replace( PLACEHOLDER_RX.replace_all(&fmt, |caps: &regex::Captures| {
"{title}", let value = match &caps["name"] {
&maybe_html_escape(html_escape, self.node.get_name()), "app_name" => self.node.get_app_name(),
) "name" | "title" => self.node.get_name(),
.replace( "output_name" => {
"{name}", self.tree
&maybe_html_escape(html_escape, self.node.get_name()), .get_parent_node_of_type(self.node.id, Type::Output)
) .map_or("<no_output>", |w| w.get_name())
},
"workspace_name" => {
self.tree
.get_parent_node_of_type(self.node.id, Type::Workspace)
.map_or("<no_workspace>", |w| w.get_name())
},
_ => &caps[0],
};
let width = caps.name("width")
.map_or("0", |m| m.as_str())
.parse::<usize>()
.unwrap();
if width > 0 && value.len() > width {
maybe_html_escape(html_escape, &format!("{}…", &value[..width - 1]))
} else {
maybe_html_escape(html_escape, &value)
}
}).into()
} }
fn get_indent_level(&self) -> usize { fn get_indent_level(&self) -> usize {

Loading…
Cancel
Save