Bring back support for truncation with ellipsis

timeout_old
Jakub Jirutka 3 years ago
parent 053becd176
commit befb2aa7d3
  1. 12
      NEWS.md
  2. 12
      README.md
  3. 22
      src/rtfmt.rs
  4. 32
      src/tree.rs

@ -4,10 +4,14 @@ swayr v0.13.0
- The placeholders `{id}`, `{app_name}`, `{name}`/`{title}`, `{output_name}`, - The placeholders `{id}`, `{app_name}`, `{name}`/`{title}`, `{output_name}`,
`{workspace_name}`, and `{marks}` may optionally provide a format string as `{workspace_name}`, and `{marks}` may optionally provide a format string as
specified by [Rust's std::fmt](https://doc.rust-lang.org/std/fmt/). The specified by [Rust's std::fmt](https://doc.rust-lang.org/std/fmt/). The
syntax is `{<placeholder>:<fmt_str>}`. For example, `{app_name:{:>10.10}}` syntax is `{<placeholder>:<fmt_str>}` or `{<placeholder>:<fmt_str>…}`. For
would mean that the application name is printed with exactly 10 characters. example, `{app_name:{:>10.10}}` would mean that the application name is
If it's shorter, it will be right-aligned (the `>`) and padded with spaces, printed with exactly 10 characters. If it's shorter, it will be
if it's longer, it'll be cut after the 10th character. right-aligned (the `>`) and padded with spaces, if it's longer, it'll be cut
after the 10th character. Another example, `{app_name:{:.10}…}` would mean
that the application name is truncated at 10 characters. If it's shorter, it
will be printed as-is (no padding), if it's longer, it'll be cut after the
9th character and the ellipsis (…) character will be added after it.
swayr v0.12.0 swayr v0.12.0
============= =============

@ -327,10 +327,14 @@ right now.
The placeholders `{id}`, `{app_name}`, `{name}`/`{title}`, `{output_name}`, The placeholders `{id}`, `{app_name}`, `{name}`/`{title}`, `{output_name}`,
`{workspace_name}`, and `{marks}` may optionally provide a format string as `{workspace_name}`, and `{marks}` may optionally provide a format string as
specified by [Rust's std::fmt](https://doc.rust-lang.org/std/fmt/). The syntax specified by [Rust's std::fmt](https://doc.rust-lang.org/std/fmt/). The syntax
is `{<placeholder>:<fmt_str>}`. For example, `{app_name:{:>10.10}}` would mean is `{<placeholder>:<fmt_str>}` or `{<placeholder>:<fmt_str>…}`. For example,
that the application name is printed with exactly 10 characters. If it's `{app_name:{:>10.10}}` would mean that the application name is printed with
shorter, it will be right-aligned (the `>`) and padded with spaces, if it's exactly 10 characters. If it's shorter, it will be right-aligned (the `>`) and
longer, it'll be cut after the 10th character. padded with spaces, if it's longer, it'll be cut after the 10th character.
Another example, `{app_name:{:.10}…}` would mean that the application name is
truncated at 10 characters. If it's shorter, it will be printed as-is (no
padding), if it's longer, it'll be cut after the 9th character and the ellipsis
(…) character will be added after it.
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

@ -73,11 +73,29 @@ impl<'a> std::convert::TryInto<usize> for &FmtArg<'a> {
} }
} }
pub fn format(fmt: &str, arg: &str) -> String { pub fn format(fmt: &str, arg: &str, ellipsis: bool) -> String {
let args = &[FmtArg::Str(arg)]; let args = &[FmtArg::Str(arg)];
if let Ok(pf) = ParsedFormat::parse(fmt, args, &NoNamedArguments) { if let Ok(pf) = ParsedFormat::parse(fmt, args, &NoNamedArguments) {
format!("{}", pf) let mut s = format!("{}", pf);
if ellipsis && !s.contains(arg) {
s.pop();
s.push('…');
}
s
} else { } else {
format!("Invalid format string: {}", fmt) format!("Invalid format string: {}", fmt)
} }
} }
#[test]
fn test_format() {
assert_eq!(format("{:.10}", "sway", false), "sway");
assert_eq!(format("{:.10}", "sway", true), "sway");
assert_eq!(format("{:.4}", "𝔰𝔴𝔞𝔶", true), "𝔰𝔴𝔞𝔶");
assert_eq!(format("{:.3}", "sway", false), "swa");
assert_eq!(format("{:.3}", "sway", true), "sw…");
assert_eq!(format("{:.3}", "𝔰𝔴𝔞𝔶", true), "𝔰𝔴…");
}

@ -428,9 +428,10 @@ pub fn get_tree<'a>(
lazy_static! { lazy_static! {
static ref APP_NAME_AND_VERSION_RX: regex::Regex = static ref APP_NAME_AND_VERSION_RX: regex::Regex =
regex::Regex::new("(.+)(-[0-9.]+)").unwrap(); regex::Regex::new("(.+)(-[0-9.]+)").unwrap();
static ref PLACEHOLDER_RX: regex::Regex = static ref PLACEHOLDER_RX: regex::Regex = regex::Regex::new(
regex::Regex::new(r"\{(?P<name>[^}:]+)(?::(?P<fmtstr>\{[^}]*\}))?\}") r"\{(?P<name>[^}:]+)(?::(?P<fmtstr>\{[^}]*\})(?P<ellipsis>…)?)?\}"
.unwrap(); )
.unwrap();
} }
fn maybe_html_escape(do_it: bool, text: String) -> String { fn maybe_html_escape(do_it: bool, text: String) -> String {
@ -530,7 +531,12 @@ impl DisplayFormat for DisplayNode<'_> {
_ => caps[0].to_string(), _ => caps[0].to_string(),
}; };
let fmt_str = caps.name("fmtstr").map_or("{}", |m| m.as_str()); let fmt_str = caps.name("fmtstr").map_or("{}", |m| m.as_str());
maybe_html_escape(html_escape, rtfmt::format(fmt_str, &value)) let ellipsis = caps.name("ellipsis").is_some();
maybe_html_escape(
html_escape,
rtfmt::format(fmt_str, &value, ellipsis),
)
}) })
.into() .into()
} }
@ -561,3 +567,21 @@ impl DisplayFormat for DisplayNode<'_> {
} }
} }
} }
#[test]
fn test_placeholder_rx() {
let caps = PLACEHOLDER_RX.captures("Hello, {place}!").unwrap();
assert_eq!(caps.name("name").unwrap().as_str(), "place");
assert_eq!(caps.name("fmtstr"), None);
assert_eq!(caps.name("ellipsis"), None);
let caps = PLACEHOLDER_RX.captures("Hi, {place:{:>10.10}}!").unwrap();
assert_eq!(caps.name("name").unwrap().as_str(), "place");
assert_eq!(caps.name("fmtstr").unwrap().as_str(), "{:>10.10}");
assert_eq!(caps.name("ellipsis"), None);
let caps = PLACEHOLDER_RX.captures("Hello, {place:{:.5}…}!").unwrap();
assert_eq!(caps.name("name").unwrap().as_str(), "place");
assert_eq!(caps.name("fmtstr").unwrap().as_str(), "{:.5}");
assert_eq!(caps.name("ellipsis").unwrap().as_str(), "…");
}

Loading…
Cancel
Save