From ce49de11c3abab87cb3c9286ea38390070a192ec Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 24 Dec 2023 15:41:55 +0000 Subject: [PATCH] Successful frags iterator! --- src/coloured_string.rs | 57 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/coloured_string.rs b/src/coloured_string.rs index 25bc8dc..6c6a8b7 100644 --- a/src/coloured_string.rs +++ b/src/coloured_string.rs @@ -79,6 +79,53 @@ impl std::ops::Add 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 { + 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); +} -- 2.30.2