@@ -39,26 +39,71 @@ mod color;
3939pub mod control;
4040mod style;
4141
42+ // use std::str::pattern::Pattern;
4243pub use self :: customcolors:: CustomColor ;
4344
4445/// Custom colors support.
4546pub mod customcolors;
4647
4748pub use color:: * ;
4849
49- use std:: { borrow:: Cow , fmt, ops:: Deref } ;
50+ use std:: { borrow:: Cow , fmt, ops:: Deref , ops :: DerefMut } ;
5051
5152pub use style:: { Style , Styles } ;
5253
5354/// A string that may have color and/or style applied to it.
5455#[ derive( Clone , Debug , PartialEq , Eq ) ]
5556pub struct ColoredString < ' a > {
56- input : Cow < ' a , str > ,
57+ pub input : Cow < ' a , str > ,
5758 fgcolor : Option < Color > ,
5859 bgcolor : Option < Color > ,
5960 style : style:: Style ,
6061}
6162
63+ /// A collection of colored strings.
64+ #[ derive( Clone , Debug , PartialEq , Eq , Default ) ]
65+ pub struct ColoredStrings < ' a > ( pub Vec < ColoredString < ' a > > ) ;
66+
67+ impl < ' a > Deref for ColoredStrings < ' a > {
68+ type Target = Vec < ColoredString < ' a > > ;
69+ fn deref ( & self ) -> & Self :: Target {
70+ & self . 0
71+ }
72+ }
73+
74+ impl < ' a > DerefMut for ColoredStrings < ' a > {
75+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
76+ & mut self . 0
77+ }
78+ }
79+
80+ impl < ' a > ColoredStrings < ' a > {
81+ fn new ( ) -> Self {
82+ ColoredStrings :: default ( )
83+ }
84+
85+ pub fn split ( self , pat : char ) -> Vec < ColoredStrings < ' a > > {
86+ let mut accum: Vec < ColoredStrings > = Vec :: new ( ) ;
87+ accum. push ( ColoredStrings :: default ( ) ) ;
88+ for colored_string in self . 0 {
89+ let mut i = colored_string. split ( pat) ;
90+ if let Some ( mut first) = i. next ( ) {
91+ accum. last_mut ( ) . unwrap ( ) . push ( first) ;
92+ }
93+ accum. extend ( i. map ( |s| {
94+ ColoredStrings ( vec ! [ s] )
95+ } ) ) ;
96+ }
97+ accum
98+ }
99+ }
100+
101+ impl < ' a , T > From < T > for ColoredStrings < ' a > where T : Into < Cow < ' a , str > > {
102+ fn from ( item : T ) -> Self {
103+ Self ( vec ! [ item. into( ) . into( ) ] )
104+ }
105+ }
106+
62107/// The trait that enables something to be given color.
63108///
64109/// You can use `colored` effectively simply by importing this trait
@@ -465,6 +510,25 @@ impl<'a> ColoredString<'a> {
465510
466511 input_cow
467512 }
513+
514+ // We can use Pattern once it becomes stable.
515+ // fn split<P: Pattern<'a>>(&'a self, pat: P) -> impl Iterator<Item = ColoredString<'a>>{
516+ fn split ( self , pat : char ) -> impl Iterator < Item = ColoredString < ' a > > {
517+ let mut a = None ;
518+ let mut b = None ;
519+ if self . input . find ( pat) . is_none ( ) {
520+ a = Some ( self ) ;
521+ } else {
522+ b = Some ( self . input . split ( pat) . map ( move |s| ColoredString {
523+ input : s. to_owned ( ) . into ( ) ,
524+ fgcolor : self . fgcolor . clone ( ) ,
525+ bgcolor : self . bgcolor . clone ( ) ,
526+ style : self . style . clone ( )
527+ } ) . collect :: < Vec < _ > > ( ) ) ;
528+ }
529+ // Here's how you coalesce two iterators, only one of which has content.
530+ a. into_iter ( ) . chain ( b. into_iter ( ) . flatten ( ) )
531+ }
468532}
469533
470534impl Default for ColoredString < ' static > {
@@ -623,6 +687,15 @@ impl<'a> fmt::Display for ColoredString<'a> {
623687 }
624688}
625689
690+ impl < ' a > fmt:: Display for ColoredStrings < ' a > {
691+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
692+ for s in & self . 0 {
693+ s. fmt ( f) ?
694+ }
695+ Ok ( ( ) )
696+ }
697+ }
698+
626699#[ cfg( test) ]
627700mod tests {
628701 use super :: * ;
0 commit comments