chiark / gitweb /
FileStatusLine priority-sensitive rendering.
authorSimon Tatham <anakin@pobox.com>
Tue, 26 Dec 2023 12:13:07 +0000 (12:13 +0000)
committerSimon Tatham <anakin@pobox.com>
Tue, 26 Dec 2023 12:34:58 +0000 (12:34 +0000)
src/text.rs

index ce803a77f59519d849fde994a7b91c0849b5d9d1..00c99b67c03c2a0ef0540ddcbec3589d1c58d0a6 100644 (file)
@@ -1203,12 +1203,149 @@ fn test_filestatus_build() {
 }
 
 impl TextFragment for FileStatusLineFinal {
-    fn render(&self, _width: usize) -> Vec<ColouredString> {
-        vec! {
-            ColouredString::plain("FIXME"),
+    fn render(&self, width: usize) -> Vec<ColouredString> {
+        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