chiark / gitweb /
Successful frags iterator!
authorSimon Tatham <anakin@pobox.com>
Sun, 24 Dec 2023 15:41:55 +0000 (15:41 +0000)
committerSimon Tatham <anakin@pobox.com>
Sun, 24 Dec 2023 15:41:55 +0000 (15:41 +0000)
src/coloured_string.rs

index 25bc8dc67448f93ce1f3ad45dda059c3e5d88a1e..6c6a8b7f623c42acce1ee54ebfd931ad1a813d1e 100644 (file)
@@ -79,6 +79,53 @@ impl std::ops::Add<ColouredString> for &str {
     }
 }
 
+pub struct ColouredStringFragIterator<'a> {
+    cs: &'a ColouredString,
+    textpos: usize,
+    colourpos: usize,
+}
+
+impl<'a> ColouredString {
+    pub fn frags(&'a self) -> ColouredStringFragIterator<'a> {
+        ColouredStringFragIterator {
+            cs: self,
+            textpos: 0,
+            colourpos: 0,
+        }
+    }
+}
+
+impl<'a> Iterator for ColouredStringFragIterator<'a> {
+    type Item = (&'a str, char);
+    fn next(&mut self) -> Option<Self::Item> {
+        let textslice = &self.cs.text[self.textpos..];
+        let mut textit = textslice.char_indices();
+        let colourslice = &self.cs.colour[self.colourpos..];
+        let mut colourit = colourslice.char_indices();
+        if let Some((_, colour)) = colourit.next() {
+            // Expect this not to run out, because colour didn't
+            textit.next().unwrap();
+
+            let (textend, colourend) = loop {
+                match colourit.next() {
+                    None => break (textslice.len(), colourslice.len()),
+                    Some((colourpos_here, colour_here)) => {
+                        let (textpos_here, _) = textit.next().unwrap();
+                        if colour_here != colour {
+                            break (textpos_here, colourpos_here);
+                        }
+                    }
+                }
+            };
+            self.textpos += textend;
+            self.colourpos += colourend;
+            Some((&textslice[..textend], colour))
+        } else {
+            None
+        }
+    }
+}
+
 #[test]
 fn test_constructors() {
     assert_eq!(ColouredString::plain("hello"),
@@ -112,3 +159,13 @@ fn test_lengths() {
     assert_eq!(ColouredString::general("xy\u{302}z", "pqqr").nchars(), 4);
     assert_eq!(ColouredString::general("xy\u{302}z", "pqqr").width(), 3);
 }
+
+#[test]
+fn test_frags() {
+    let cs = ColouredString::general("stóat wèasël", "uuuuu vvvvvv");
+    let mut frags = cs.frags();
+    assert_eq!(frags.next(), Some(("stóat", 'u')));
+    assert_eq!(frags.next(), Some((" ", ' ')));
+    assert_eq!(frags.next(), Some(("wèasël", 'v')));
+    assert_eq!(frags.next(), None);
+}