use std::io::{self, Write};
use std::ops::Range;
use termcolor::WriteColor;
pub use termcolor::Color as Color;
pub use termcolor::ColorSpec as Spec;
pub type Colors = Vec<(Spec, Range<usize>)>;
pub struct ColorlessString(pub String);
impl Write for ColorlessString {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
use std::str;
let string = str::from_utf8(buf).unwrap();
self.0 += string;
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl WriteColor for ColorlessString {
fn supports_color(&self) -> bool {
false
}
fn set_color(&mut self, _spec: &Spec) -> io::Result<()> {
Ok(())
}
fn reset (&mut self) -> io::Result<()> {
Ok(())
}
}
pub struct ColorRange<'a> {
colors: &'a Colors,
offset: usize,
}
impl<'a> Clone for ColorRange<'a> {
fn clone(&self) -> Self {
ColorRange {
colors: self.colors,
offset: self.offset,
}
}
}
impl<'a> ColorRange<'a> {
pub fn new(colors: &'a Colors) -> Self {
ColorRange {
colors: colors,
offset: 0,
}
}
pub fn update_offset(&mut self, offset: usize) {
self.offset = offset;
}
pub fn get(&self, idx: usize) -> Option<&Spec> {
let mut i = 0;
let offset = self.offset + idx;
while i < self.colors.len() {
let (ref rgb, ref range) = self.colors[i];
if offset >= range.start && offset < range.end {
return Some(rgb);
} else {
i += 1;
}
}
None
}
}
macro_rules! make_color {
($name:ident, $name_bold:ident, $color:ident) => {
pub fn $name() -> Spec {
Spec::new().set_bold(false).set_fg(Some(Color::$color)).clone()
}
pub fn $name_bold () -> Spec {
Spec::new().set_bold(true).set_fg(Some(Color::$color)).clone()
}
}
}
make_color!(red, red_bold, Red);
make_color!(blue, blue_bold, Blue);
make_color!(green, green_bold, Green);
make_color!(yellow, yellow_bold, Yellow);
make_color!(magenta, magenta_bold, Magenta);
make_color!(black, black_bold, Black);
make_color!(cyan, cyan_bold, Cyan);
make_color!(white, white_bold, White);