use std::io::{Write, Error};
use super::utils::NEWLINE;
#[derive(Clone, Debug, PartialEq, Copy)]
pub enum Alignment {
LEFT,
CENTER,
RIGHT
}
#[derive(Clone, Debug, PartialEq, Copy)]
pub enum LinePosition {
Top,
Title,
Intern,
Bottom
}
#[derive(Clone, Debug, PartialEq, Copy)]
pub enum ColumnPosition {
Left,
Intern,
Right
}
#[derive(Clone, Debug, Copy)]
pub struct LineSeparator {
line: char,
junc: char,
ljunc: char,
rjunc: char
}
impl LineSeparator {
pub fn new(line: char, junc: char, ljunc: char, rjunc: char) -> LineSeparator {
return LineSeparator{line: line, junc: junc, ljunc: ljunc, rjunc: rjunc};
}
pub fn print<T: Write+?Sized>(&self, out: &mut T, col_width: &[usize], colsep: bool, lborder: bool, rborder: bool) -> Result<(), Error> {
if lborder {
try!(out.write_all(&[self.ljunc as u8]));
}
let mut iter = col_width.into_iter().peekable();
while let Some(width) = iter.next() {
try!(out.write_all(&vec![self.line as u8; width+2]));
if colsep && iter.peek().is_some() {
try!(out.write_all(&[self.junc as u8]));
}
}
if rborder {
try!(out.write_all(&[self.rjunc as u8]));
}
return out.write_all(NEWLINE);
}
}
impl Default for LineSeparator {
fn default() -> Self {
return LineSeparator::new('-', '+', '+', '+');
}
}
#[derive(Clone, Debug, Copy)]
pub struct TableFormat {
csep: Option<char>,
lborder: Option<char>,
rborder: Option<char>,
lsep: Option<LineSeparator>,
tsep: Option<LineSeparator>,
top_sep: Option<LineSeparator>,
bottom_sep: Option<LineSeparator>,
pad_left: usize,
pad_right: usize
}
impl TableFormat {
pub fn new() -> TableFormat {
return TableFormat{
csep: None,
lborder: None,
rborder: None,
lsep: None,
tsep: None,
top_sep: None,
bottom_sep: None,
pad_left: 0,
pad_right: 0
};
}
pub fn get_padding(&self) -> (usize, usize) {
return (self.pad_left, self.pad_right);
}
pub fn padding(&mut self, left: usize, right: usize) {
self.pad_left = left;
self.pad_right = right;
}
pub fn column_separator(&mut self, separator: char) {
self.csep = Some(separator);
}
pub fn borders(&mut self, border: char) {
self.lborder = Some(border);
self.rborder = Some(border);
}
pub fn separator(&mut self, what: LinePosition, separator: LineSeparator) {
*match what {
LinePosition::Top => &mut self.top_sep,
LinePosition::Bottom => &mut self.bottom_sep,
LinePosition::Title => &mut self.tsep,
LinePosition::Intern => &mut self.lsep
} = Some(separator);
}
pub fn separators(&mut self, what: &[LinePosition], separator: LineSeparator) {
for pos in what {
self.separator(*pos, separator);
}
}
fn get_sep_for_line(&self, pos: LinePosition) -> &Option<LineSeparator> {
return match pos {
LinePosition::Intern => return &self.lsep,
LinePosition::Top => return &self.top_sep,
LinePosition::Bottom => return &self.bottom_sep,
LinePosition::Title => match &self.tsep {
s @ &Some(_) => s,
&None => &self.lsep
}
};
}
pub fn print_line_separator<T: Write+?Sized>(&self, out: &mut T, col_width: &[usize], pos: LinePosition) -> Result<(), Error> {
return match *self.get_sep_for_line(pos) {
Some(ref l) => l.print(out, col_width, self.csep.is_some(), self.lborder.is_some(), self.rborder.is_some()),
None => Ok(())
};
}
fn get_column_separator(&self, pos: ColumnPosition) -> Option<char> {
return match pos {
ColumnPosition::Left => self.lborder,
ColumnPosition::Intern => self.csep,
ColumnPosition::Right => self.rborder
};
}
pub fn print_column_separator<T: Write+?Sized>(&self, out: &mut T, pos: ColumnPosition) -> Result<(), Error> {
return match self.get_column_separator(pos) {
Some(s) => out.write_all(&[s as u8]),
None => Ok(())
};
}
}
impl Default for TableFormat {
fn default() -> Self {
return TableFormat::new();
}
}
pub struct FormatBuilder {
format: Box<TableFormat>
}
impl FormatBuilder {
pub fn new() -> FormatBuilder {
return FormatBuilder {
format: Box::new(TableFormat::new())
};
}
pub fn padding(mut self, left: usize, right: usize) -> Self {
self.format.padding(left, right);
return self;
}
pub fn column_separator(mut self, separator: char) -> Self {
self.format.column_separator(separator);
return self;
}
pub fn borders(mut self, border: char) -> Self {
self.format.borders(border);
return self;
}
pub fn separator(mut self, what: LinePosition, separator: LineSeparator) -> Self {
self.format.separator(what, separator);
return self;
}
pub fn separators(mut self, what: &[LinePosition], separator: LineSeparator) -> Self {
self.format.separators(what, separator);
return self;
}
pub fn build(self) -> TableFormat {
return *self.format;
}
}
pub mod consts {
use super::{TableFormat, LineSeparator, FormatBuilder, LinePosition};
lazy_static! {
static ref MINUS_PLUS_SEP: LineSeparator = LineSeparator::new('-', '+', '+', '+');
static ref EQU_PLUS_SEP: LineSeparator = LineSeparator::new('=', '+', '+', '+');
pub static ref FORMAT_DEFAULT: TableFormat = FormatBuilder::new()
.column_separator('|')
.borders('|')
.separator(LinePosition::Intern, *MINUS_PLUS_SEP)
.separator(LinePosition::Title, *EQU_PLUS_SEP)
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.padding(1, 1)
.build();
pub static ref FORMAT_NO_TITLE: TableFormat = FormatBuilder::new()
.column_separator('|')
.borders('|')
.separator(LinePosition::Intern, *MINUS_PLUS_SEP)
.separator(LinePosition::Title, *MINUS_PLUS_SEP)
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.padding(1, 1)
.build();
pub static ref FORMAT_NO_LINESEP_WITH_TITLE: TableFormat = FormatBuilder::new()
.column_separator('|')
.borders('|')
.separator(LinePosition::Title, *MINUS_PLUS_SEP)
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.padding(1, 1)
.build();
pub static ref FORMAT_NO_LINESEP: TableFormat = FormatBuilder::new()
.column_separator('|')
.borders('|')
.padding(1, 1)
.build();
pub static ref FORMAT_NO_COLSEP: TableFormat = FormatBuilder::new()
.separator(LinePosition::Intern, *MINUS_PLUS_SEP)
.separator(LinePosition::Title, *EQU_PLUS_SEP)
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.padding(1, 1)
.build();
pub static ref FORMAT_CLEAN: TableFormat = FormatBuilder::new()
.padding(1, 1)
.build();
pub static ref FORMAT_BORDERS_ONLY: TableFormat = FormatBuilder::new()
.padding(1, 1)
.separator(LinePosition::Intern, *MINUS_PLUS_SEP)
.separator(LinePosition::Title, *EQU_PLUS_SEP)
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.borders('|')
.build();
pub static ref FORMAT_NO_BORDER: TableFormat = FormatBuilder::new()
.padding(1, 1)
.separator(LinePosition::Intern, *MINUS_PLUS_SEP)
.separator(LinePosition::Title, *EQU_PLUS_SEP)
.column_separator('|')
.build();
pub static ref FORMAT_NO_BORDER_LINE_SEPARATOR: TableFormat = FormatBuilder::new()
.padding(1, 1)
.separator(LinePosition::Title, *MINUS_PLUS_SEP)
.column_separator('|')
.build();
}
}