Skip to content

Commit 1ab549c

Browse files
committed
feature: Add Deref impl for ColoredStrings.
1 parent 60dfa95 commit 1ab549c

1 file changed

Lines changed: 75 additions & 2 deletions

File tree

src/lib.rs

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,71 @@ mod color;
3939
pub mod control;
4040
mod style;
4141

42+
// use std::str::pattern::Pattern;
4243
pub use self::customcolors::CustomColor;
4344

4445
/// Custom colors support.
4546
pub mod customcolors;
4647

4748
pub use color::*;
4849

49-
use std::{borrow::Cow, fmt, ops::Deref};
50+
use std::{borrow::Cow, fmt, ops::Deref, ops::DerefMut};
5051

5152
pub use style::{Style, Styles};
5253

5354
/// A string that may have color and/or style applied to it.
5455
#[derive(Clone, Debug, PartialEq, Eq)]
5556
pub 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

470534
impl 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)]
627700
mod tests {
628701
use super::*;

0 commit comments

Comments
 (0)