}
}
+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"),
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);
+}