From 621ac2771c2d503adf5f10ef57c4180b390baacb Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 26 Dec 2023 12:13:07 +0000 Subject: [PATCH] FileStatusLine priority-sensitive rendering. --- src/text.rs | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 3 deletions(-) diff --git a/src/text.rs b/src/text.rs index ce803a7..00c99b6 100644 --- a/src/text.rs +++ b/src/text.rs @@ -1203,12 +1203,149 @@ fn test_filestatus_build() { } impl TextFragment for FileStatusLineFinal { - fn render(&self, _width: usize) -> Vec { - vec! { - ColouredString::plain("FIXME"), + fn render(&self, width: usize) -> Vec { + let mut line = ColouredString::plain(""); + let space = ColouredString::plain(" ").repeat(FileStatusLine::SPACING); + let push = |line: &mut ColouredString, s: ColouredStringSlice<'_>| { + if !line.is_empty() { + line.push_str(&space.slice()); + } + line.push_str(&s); + }; + + if let Some(msg) = &self.fs.message { + let cmsg = ColouredString::plain(&msg); + push(&mut line, cmsg.slice()); + } + + let cprop = if let Some(prop) = &self.fs.proportion { + Some(ColouredString::plain(&format!("({}%)", prop))) + } else { + None + }; + let cpropwidth = if let Some(cprop) = &cprop { cprop.width() } else {0}; + let extraspace = if !line.is_empty() && cpropwidth > 0 { + FileStatusLine::SPACING + } else {0}; + + let avail = width - min( + width, line.width() + cpropwidth + extraspace + 1); + let minindex = self.priwidth.partition_point(|(_, w)| *w <= avail); + dbg!(avail, &self.priwidth, minindex); + if minindex > 0 { + let minpri = self.priwidth[minindex - 1].0; + + for (kp, pri) in &self.fs.keypresses { + if *pri >= minpri { + let mut ckey = ColouredString::plain("["); + let ckp = ColouredString::uniform(&kp.key, 'k'); + ckey.push_str(&ckp.slice()); + ckey.push_str(&ColouredString::plain("]:").slice()); + ckey.push_str(&kp.description.slice()); + push(&mut line, ckey.slice()); + } + + } + } + + if let Some(cprop) = cprop { + push(&mut line, cprop.slice()); } + + // Done. Now centre it in the available space. + let line = line.truncate(width - 1); + let space = width - min(line.width() + 1, width); + let left = space / 2; + let linepad = ColouredString::plain(" ").repeat(left) + line; + vec! { linepad } } } +#[test] +fn test_filestatus_render() { + let fs = FileStatusLine::new() + .message("stoat") + .set_proportion(34, 55) + .add("A".to_owned(), "Annoy", 10) + .add("B".to_owned(), "Badger", 10) + .add("C".to_owned(), "Critical", 1000) + .add("D".to_owned(), "Dull", 1) + .into_box(); + + assert_eq!(fs.render(80), vec! { + ColouredString::general( + " stoat [A]:Annoy [B]:Badger [C]:Critical [D]:Dull (61%)", + " k k k k "), + }); + + assert_eq!(fs.render(60), vec! { + ColouredString::general( + "stoat [A]:Annoy [B]:Badger [C]:Critical [D]:Dull (61%)", + " k k k k "), + }); + + assert_eq!(fs.render(59), vec! { + ColouredString::general( + " stoat [A]:Annoy [B]:Badger [C]:Critical (61%)", + " k k k "), + }); + + assert_eq!(fs.render(50), vec! { + ColouredString::general( + "stoat [A]:Annoy [B]:Badger [C]:Critical (61%)", + " k k k "), + }); + + assert_eq!(fs.render(49), vec! { + ColouredString::general( + " stoat [C]:Critical (61%)", + " k "), + }); + + assert_eq!(fs.render(27), vec! { + ColouredString::general( + "stoat [C]:Critical (61%)", + " k "), + }); + + assert_eq!(fs.render(26), vec! { + ColouredString::plain(" stoat (61%)"), + }); + + let fs = FileStatusLine::new() + .set_proportion(1, 11) + .add("K".to_owned(), "Keypress", 10) + .into_box(); + + assert_eq!(fs.render(19), vec! { + ColouredString::general( + "[K]:Keypress (9%)", + " k "), + }); + + assert_eq!(fs.render(18), vec! { + ColouredString::general( + " (9%)", + " "), + }); + + let fs = FileStatusLine::new() + .message("weasel") + .add("K".to_owned(), "Keypress", 10) + .into_box(); + + assert_eq!(fs.render(21), vec! { + ColouredString::general( + "weasel [K]:Keypress", + " k "), + }); + + assert_eq!(fs.render(20), vec! { + ColouredString::general( + " weasel", + " "), + }); +} + // TODO: // MenuKeypressLine -- 2.30.2