use colored::{Color, Colorize};
use super::super::table::column_break::ColumnBreak;
#[derive(Debug, Clone)]
#[derive(PartialEq)]
pub enum Alignment {
Left,
Center,
Right
}
impl Alignment {
fn from_token(token: char) -> Option<Alignment> {
match token {
'<' => Some(Alignment::Left),
'^' => Some(Alignment::Center),
'>' => Some(Alignment::Right),
_ => None
}
}
}
#[derive(Debug, Clone)]
pub enum Wrap {
Truncate,
Wrap
}
impl Wrap {
fn from_token(token: char) -> Option<Wrap> {
match token {
';' => Some(Wrap::Wrap),
'.' => Some(Wrap::Truncate),
_ => None
}
}
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! content_style {
( $style:literal ) => {
ContentStyle::from_format($style)
}
}
#[derive(Debug, Clone)]
pub struct ContentStyle {
pub fg_color: Option<Color>,
pub bg_color: Option<Color>,
pub alignment: Alignment,
pub wrap: Wrap,
pub width: ColumnBreak
}
impl ContentStyle {
pub fn default() -> ContentStyle {
ContentStyle {
fg_color: None,
bg_color: None,
alignment: Alignment::Left,
wrap: Wrap::Truncate,
width: ColumnBreak::Content,
}
}
pub fn new(
fg_color: Option<Color>,
bg_color: Option<Color>,
alignment: Alignment,
wrap: Wrap,
width: ColumnBreak
) -> ContentStyle {
ContentStyle {
fg_color,
bg_color,
alignment,
wrap,
width,
}
}
pub fn from_format(format: &str) -> ContentStyle {
let mut style = ContentStyle::default();
let tokens: Vec<char> = format[1..format.len() - 1].chars().collect();
let mut token_ix = 0;
while token_ix < tokens.len() {
let token = tokens[token_ix];
match ContentStyle::color_from_token(token) {
Some(color) => style.fg_color = Some(color),
None => {}
}
match Alignment::from_token(token) {
Some(alignment) => style.alignment = alignment,
None => {}
}
match Wrap::from_token(token) {
Some(wrap) => style.wrap = wrap,
None => {}
}
if token == '-' {
if tokens.len() > token_ix + 1 {
style.bg_color =
ContentStyle::color_from_token(tokens[token_ix + 1]);
token_ix += 1;
}
}
token_ix += 1;
if token == ':' {
match format[token_ix+1..tokens.len()+1].find(':') {
Some(ix) => {
let width = format[token_ix+1..token_ix+ix+1].parse::<usize>().unwrap();
style.width = ColumnBreak::Fixed(width);
token_ix += ix + 1;
}
None => { }
}
}
if token == '-' {
match format[token_ix+1..tokens.len()+1].find('-') {
Some(ix) => {
let width = format[token_ix+1..token_ix+ix+1].parse::<usize>().unwrap();
style.width = ColumnBreak::Fixed(width);
token_ix += ix + 1;
}
None => { }
}
}
}
style
}
fn color_from_token(
token: char
) -> Option<Color> {
match token {
'w' => Some(Color::White),
'l' => Some(Color::Black),
'r' => Some(Color::Red),
'g' => Some(Color::Green),
'y' => Some(Color::Yellow),
'b' => Some(Color::Blue),
'm' => Some(Color::Magenta),
'c' => Some(Color::Cyan),
'W' => Some(Color::BrightWhite),
'L' => Some(Color::BrightBlack),
'R' => Some(Color::BrightRed),
'G' => Some(Color::BrightGreen),
'Y' => Some(Color::BrightYellow),
'B' => Some(Color::BrightBlue),
'M' => Some(Color::BrightMagenta),
'C' => Some(Color::BrightCyan),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use colored::Color;
#[test]
fn test_from_format() {
let style = ContentStyle::from_format("{c^;:15:}");
let expected =
ContentStyle {
fg_color: Some(Color::Cyan),
bg_color: None,
alignment: Alignment::Center,
wrap: Wrap::Wrap,
width: ColumnBreak::Fixed(15)
};
assert_eq!(
format!("{:?}", style),
format!("{:?}", expected)
);
}
}