diff options
author | Pierre-Henri Symoneaux <pierre-henri.symoneaux@nokia.com> | 2017-05-29 22:10:07 +0200 |
---|---|---|
committer | Pierre-Henri Symoneaux <pierre-henri.symoneaux@nokia.com> | 2017-05-29 22:10:07 +0200 |
commit | 0b633eb06f99a24f54070fe460068b2fa5ce1e13 (patch) | |
tree | dbc9095bb2ec623bee04382c74f356c327810a0b /src | |
parent | c771c45b69de6b1c432e070cf6ac4d58c885488c (diff) |
Applied rustfmt on code
Diffstat (limited to 'src')
-rw-r--r-- | src/cell.rs | 659 | ||||
-rw-r--r-- | src/format.rs | 514 | ||||
-rw-r--r-- | src/lib.rs | 1484 | ||||
-rw-r--r-- | src/main.rs | 91 | ||||
-rw-r--r-- | src/row.rs | 444 | ||||
-rw-r--r-- | src/utils.rs | 245 |
6 files changed, 1778 insertions, 1659 deletions
diff --git a/src/cell.rs b/src/cell.rs index 40a1141..18aadd0 100644 --- a/src/cell.rs +++ b/src/cell.rs @@ -1,114 +1,114 @@ -//! This module contains definition of table/row cells stuff
-
-use std::io::{Write, Error};
-use std::string::ToString;
-use unicode_width::UnicodeWidthStr;
-use term::{Attr, Terminal, color};
-use super::format::Alignment;
-use super::utils::print_align;
-
-/// Represent a table cell containing a string.
-///
-/// Once created, a cell's content cannot be modified.
-/// The cell would have to be replaced by another one
-#[derive(Clone, Debug)]
-pub struct Cell {
- content: Vec<String>,
- width: usize,
- align: Alignment,
- style: Vec<Attr>
-}
-
-impl Cell {
- /// Create a new `Cell` initialized with content from `string`.
- /// Text alignment in cell is configurable with the `align` argument
- pub fn new_align(string: &str, align: Alignment) -> Cell {
- let content: Vec<String> = string.lines().map(|ref x| x.to_string()).collect();
- let mut width = 0;
- for cont in &content {
- let l = UnicodeWidthStr::width(&cont[..]);
- if l > width {
- width = l;
- }
- }
- Cell {
- content: content,
- width: width,
- align: align,
- style: Vec::new()
- }
- }
-
- /// Create a new `Cell` initialized with content from `string`.
- /// By default, content is align to `LEFT`
- pub fn new(string: &str) -> Cell {
- Cell::new_align(string, Alignment::LEFT)
- }
-
- /// Set text alignment in the cell
- pub fn align(&mut self, align: Alignment) {
- self.align = align;
- }
-
- /// Add a style attribute to the cell
- pub fn style(&mut self, attr: Attr) {
- self.style.push(attr);
- }
-
- /// Add a style attribute to the cell. Can be chained
- pub fn with_style(mut self, attr: Attr) -> Cell {
- self.style(attr);
- self
- }
-
- /// Remove all style attributes and reset alignment to default (LEFT)
- pub fn reset_style(&mut self) {
- self.style.clear();
- self.align(Alignment::LEFT);
- }
-
- /// Set the cell's style by applying the given specifier string
- ///
- /// # Style spec syntax
- ///
- /// The syntax for the style specifier looks like this :
- /// **FrBybl** which means **F**oreground **r**ed **B**ackground **y**ellow **b**old **l**eft
- ///
- /// ### List of supported specifiers :
- ///
- /// * **F** : **F**oreground (must be followed by a color specifier)
- /// * **B** : **B**ackground (must be followed by a color specifier)
- /// * **b** : **b**old
- /// * **i** : **i**talic
- /// * **u** : **u**nderline
- /// * **c** : Align **c**enter
- /// * **l** : Align **l**eft
- /// * **r** : Align **r**ight
- /// * **d** : **d**efault style
- ///
- /// ### List of color specifiers :
- ///
- /// * **r** : Red
- /// * **b** : Blue
- /// * **g** : Green
- /// * **y** : Yellow
- /// * **c** : Cyan
- /// * **m** : Magenta
- /// * **w** : White
- /// * **d** : Black
- ///
- /// And capital letters are for **bright** colors.
- /// Eg :
- ///
- /// * **R** : Bright Red
- /// * **B** : Bright Blue
- /// * ... and so on ...
- pub fn style_spec(mut self, spec: &str) -> Cell {
- self.reset_style();
- let mut foreground = false;
- let mut background = false;
- for c in spec.chars() {
- if foreground || background {
+//! This module contains definition of table/row cells stuff + +use std::io::{Write, Error}; +use std::string::ToString; +use unicode_width::UnicodeWidthStr; +use term::{Attr, Terminal, color}; +use super::format::Alignment; +use super::utils::print_align; + +/// Represent a table cell containing a string. +/// +/// Once created, a cell's content cannot be modified. +/// The cell would have to be replaced by another one +#[derive(Clone, Debug)] +pub struct Cell { + content: Vec<String>, + width: usize, + align: Alignment, + style: Vec<Attr>, +} + +impl Cell { + /// Create a new `Cell` initialized with content from `string`. + /// Text alignment in cell is configurable with the `align` argument + pub fn new_align(string: &str, align: Alignment) -> Cell { + let content: Vec<String> = string.lines().map(|ref x| x.to_string()).collect(); + let mut width = 0; + for cont in &content { + let l = UnicodeWidthStr::width(&cont[..]); + if l > width { + width = l; + } + } + Cell { + content: content, + width: width, + align: align, + style: Vec::new(), + } + } + + /// Create a new `Cell` initialized with content from `string`. + /// By default, content is align to `LEFT` + pub fn new(string: &str) -> Cell { + Cell::new_align(string, Alignment::LEFT) + } + + /// Set text alignment in the cell + pub fn align(&mut self, align: Alignment) { + self.align = align; + } + + /// Add a style attribute to the cell + pub fn style(&mut self, attr: Attr) { + self.style.push(attr); + } + + /// Add a style attribute to the cell. Can be chained + pub fn with_style(mut self, attr: Attr) -> Cell { + self.style(attr); + self + } + + /// Remove all style attributes and reset alignment to default (LEFT) + pub fn reset_style(&mut self) { + self.style.clear(); + self.align(Alignment::LEFT); + } + + /// Set the cell's style by applying the given specifier string + /// + /// # Style spec syntax + /// + /// The syntax for the style specifier looks like this : + /// **FrBybl** which means **F**oreground **r**ed **B**ackground **y**ellow **b**old **l**eft + /// + /// ### List of supported specifiers : + /// + /// * **F** : **F**oreground (must be followed by a color specifier) + /// * **B** : **B**ackground (must be followed by a color specifier) + /// * **b** : **b**old + /// * **i** : **i**talic + /// * **u** : **u**nderline + /// * **c** : Align **c**enter + /// * **l** : Align **l**eft + /// * **r** : Align **r**ight + /// * **d** : **d**efault style + /// + /// ### List of color specifiers : + /// + /// * **r** : Red + /// * **b** : Blue + /// * **g** : Green + /// * **y** : Yellow + /// * **c** : Cyan + /// * **m** : Magenta + /// * **w** : White + /// * **d** : Black + /// + /// And capital letters are for **bright** colors. + /// Eg : + /// + /// * **R** : Bright Red + /// * **B** : Bright Blue + /// * ... and so on ... + pub fn style_spec(mut self, spec: &str) -> Cell { + self.reset_style(); + let mut foreground = false; + let mut background = false; + for c in spec.chars() { + if foreground || background { let color = match c {
'r' => color::RED,
'R' => color::BRIGHT_RED,
@@ -126,18 +126,21 @@ impl Cell { 'W' => color::BRIGHT_WHITE,
'd' => color::BLACK,
'D' => color::BRIGHT_BLACK,
- _ => { // Silently ignore unknown tags
- foreground = false;
- background = false;
- continue;
- }
- };
- if foreground { self.style(Attr::ForegroundColor(color)); }
- else if background { self.style(Attr::BackgroundColor(color)); }
- foreground = false;
- background = false;
- }
- else {
+ _ => { + // Silently ignore unknown tags + foreground = false; + background = false; + continue; + }
+ }; + if foreground { + self.style(Attr::ForegroundColor(color)); + } else if background { + self.style(Attr::BackgroundColor(color)); + } + foreground = false; + background = false; + } else { match c {
'F' => foreground = true,
'B' => background = true,
@@ -147,209 +150,225 @@ impl Cell { 'c' => self.align(Alignment::CENTER),
'l' => self.align(Alignment::LEFT),
'r' => self.align(Alignment::RIGHT),
- 'd' => {/* Default : do nothing */}
- _ => {/* Silently ignore unknown tags */}
- }
- }
- }
- return self;
- }
-
- /// Return the height of the cell
- pub fn get_height(&self) -> usize {
- self.content.len()
- }
-
- /// Return the width of the cell
- pub fn get_width(&self) -> usize {
- self.width
- }
-
- /// Return a copy of the full string contained in the cell
- pub fn get_content(&self) -> String {
- self.content.join("\n")
- }
-
- /// Print a partial cell to `out`. Since the cell may be multi-lined,
- /// `idx` is the line index to print. `col_width` is the column width used to
- /// fill the cells with blanks so it fits in the table.
- /// If `ìdx` is higher than this cell's height, it will print empty content
- pub fn print<T: Write+?Sized>(&self, out: &mut T, idx: usize, col_width: usize, skip_right_fill: bool) -> Result<(), Error> {
- let c = self.content.get(idx).map(|s| s.as_ref()).unwrap_or("");
- print_align(out, self.align, c, ' ', col_width, skip_right_fill)
- }
-
- /// Apply style then call `print` to print the cell into a terminal
- pub fn print_term<T: Terminal+?Sized>(&self, out: &mut T, idx: usize, col_width: usize, skip_right_fill: bool) -> Result<(), Error> {
- for a in &self.style {
+ 'd' => { /* Default : do nothing */ }
+ _ => { /* Silently ignore unknown tags */ }
+ } + } + } + return self; + } + + /// Return the height of the cell + pub fn get_height(&self) -> usize { + self.content.len() + } + + /// Return the width of the cell + pub fn get_width(&self) -> usize { + self.width + } + + /// Return a copy of the full string contained in the cell + pub fn get_content(&self) -> String { + self.content.join("\n") + } + + /// Print a partial cell to `out`. Since the cell may be multi-lined, + /// `idx` is the line index to print. `col_width` is the column width used to + /// fill the cells with blanks so it fits in the table. + /// If `ìdx` is higher than this cell's height, it will print empty content + pub fn print<T: Write + ?Sized>(&self, + out: &mut T, + idx: usize, + col_width: usize, + skip_right_fill: bool) + -> Result<(), Error> { + let c = self.content.get(idx).map(|s| s.as_ref()).unwrap_or(""); + print_align(out, self.align, c, ' ', col_width, skip_right_fill) + } + + /// Apply style then call `print` to print the cell into a terminal + pub fn print_term<T: Terminal + ?Sized>(&self, + out: &mut T, + idx: usize, + col_width: usize, + skip_right_fill: bool) + -> Result<(), Error> { + for a in &self.style { match out.attr(a.clone()) {
- Ok(..) | Err(::term::Error::NotSupported) | Err(::term::Error::ColorOutOfRange) => (), // Ignore unsupported atrributes
- Err(e) => return Err(term_error_to_io_error(e))
- };
- }
- try!(self.print(out, idx, col_width, skip_right_fill));
+ Ok(..) | + Err(::term::Error::NotSupported) | + Err(::term::Error::ColorOutOfRange) => (), // Ignore unsupported atrributes
+ Err(e) => return Err(term_error_to_io_error(e)),
+ }; + } + try!(self.print(out, idx, col_width, skip_right_fill)); match out.reset() {
- Ok(..) | Err(::term::Error::NotSupported) | Err(::term::Error::ColorOutOfRange) => Ok(()),
- Err(e) => Err(term_error_to_io_error(e))
- }
- }
-}
-
-fn term_error_to_io_error(te: ::term::Error) -> Error {
+ Ok(..) | + Err(::term::Error::NotSupported) | + Err(::term::Error::ColorOutOfRange) => Ok(()),
+ Err(e) => Err(term_error_to_io_error(e)),
+ } + } +} + +fn term_error_to_io_error(te: ::term::Error) -> Error { match te {
::term::Error::Io(why) => why,
_ => Error::new(::std::io::ErrorKind::Other, te),
- }
-}
-
-impl <'a, T: ToString> From<&'a T> for Cell {
- fn from(f: &T) -> Cell {
- Cell::new(&f.to_string())
- }
-}
-
-impl ToString for Cell {
- fn to_string(&self) -> String {
- self.get_content()
- }
-}
-
-impl Default for Cell {
- /// Return a cell initialized with a single empty `String`, with LEFT alignment
- fn default() -> Cell {
- Cell {
- content: vec!["".to_string(); 1],
- width: 0,
- align: Alignment::LEFT,
- style: Vec::new()
- }
- }
-}
-
-/// This macro simplifies `Cell` creation
-///
-/// Support 2 syntax : With and without style specification.
-/// # Syntax
-/// ```text
-/// cell!(value);
-/// ```
-/// or
-///
-/// ```text
-/// cell!(spec:value);
-/// ```
-/// Value must implement the `std::string::ToString` trait
-///
-/// For details about style specifier syntax, check doc for [Cell::style_spec](cell/struct.Cell.html#method.style_spec) method
-/// # Example
-/// ```
-/// # #[macro_use] extern crate prettytable;
-/// # fn main() {
-/// let cell = cell!("value");
-/// // Do something with the cell
-/// # drop(cell);
-/// // Create a cell with style (Red foreground, Bold, aligned to left);
-/// let styled = cell!(Frbl->"value");
-/// # drop(styled);
-/// # }
-/// ```
-#[macro_export]
+ } +} + +impl<'a, T: ToString> From<&'a T> for Cell { + fn from(f: &T) -> Cell { + Cell::new(&f.to_string()) + } +} + +impl ToString for Cell { + fn to_string(&self) -> String { + self.get_content() + } +} + +impl Default for Cell { + /// Return a cell initialized with a single empty `String`, with LEFT alignment + fn default() -> Cell { + Cell { + content: vec!["".to_string(); 1], + width: 0, + align: Alignment::LEFT, + style: Vec::new(), + } + } +} + +/// This macro simplifies `Cell` creation +/// +/// Support 2 syntax : With and without style specification. +/// # Syntax +/// ```text +/// cell!(value); +/// ``` +/// or +/// +/// ```text +/// cell!(spec:value); +/// ``` +/// Value must implement the `std::string::ToString` trait +/// +/// For details about style specifier syntax, check doc for [Cell::style_spec](cell/struct.Cell.html#method.style_spec) method +/// # Example +/// ``` +/// # #[macro_use] extern crate prettytable; +/// # fn main() { +/// let cell = cell!("value"); +/// // Do something with the cell +/// # drop(cell); +/// // Create a cell with style (Red foreground, Bold, aligned to left); +/// let styled = cell!(Frbl->"value"); +/// # drop(styled); +/// # } +/// ``` +#[macro_export] macro_rules! cell {
() => ($crate::cell::Cell::default());
($value:expr) => ($crate::cell::Cell::new(&$value.to_string()));
($style:ident -> $value:expr) => (cell!($value).style_spec(stringify!($style)));
-}
-
-#[cfg(test)]
-mod tests {
- use cell::Cell;
- use utils::StringWriter;
- use format::Alignment;
- use term::{Attr, color};
-
- #[test]
- fn get_content() {
- let cell = Cell::new("test");
- assert_eq!(cell.get_content(), "test");
- }
-
- #[test]
- fn print_ascii() {
- let ascii_cell = Cell::new("hello");
- assert_eq!(ascii_cell.get_width(), 5);
-
- let mut out = StringWriter::new();
- let _ = ascii_cell.print(&mut out, 0, 10, false);
- assert_eq!(out.as_string(), "hello ");
- }
-
- #[test]
- fn print_unicode() {
- let unicode_cell = Cell::new("привет");
- assert_eq!(unicode_cell.get_width(), 6);
-
- let mut out = StringWriter::new();
- let _ = unicode_cell.print(&mut out, 0, 10, false);
- assert_eq!(out.as_string(), "привет ");
- }
-
- #[test]
- fn print_cjk() {
- let unicode_cell = Cell::new("由系统自动更新");
- assert_eq!(unicode_cell.get_width(), 14);
- let mut out = StringWriter::new();
- let _ = unicode_cell.print(&mut out, 0, 20, false);
- assert_eq!(out.as_string(), "由系统自动更新 ");
- }
-
- #[test]
- fn align_left() {
- let cell = Cell::new_align("test", Alignment::LEFT);
- let mut out = StringWriter::new();
- let _ = cell.print(&mut out, 0, 10, false);
- assert_eq!(out.as_string(), "test ");
- }
-
- #[test]
- fn align_center() {
- let cell = Cell::new_align("test", Alignment::CENTER);
- let mut out = StringWriter::new();
- let _ = cell.print(&mut out, 0, 10, false);
- assert_eq!(out.as_string(), " test ");
- }
-
- #[test]
- fn align_right() {
- let cell = Cell::new_align("test", Alignment::RIGHT);
- let mut out = StringWriter::new();
- let _ = cell.print(&mut out, 0, 10, false);
- assert_eq!(out.as_string(), " test");
- }
-
- #[test]
- fn style_spec() {
- let mut cell = Cell::new("test").style_spec("FrBBbuic");
- assert_eq!(cell.style.len(), 5);
- assert!(cell.style.contains(&Attr::Underline(true)));
- assert!(cell.style.contains(&Attr::Italic(true)));
- assert!(cell.style.contains(&Attr::Bold));
- assert!(cell.style.contains(&Attr::ForegroundColor(color::RED)));
- assert!(cell.style.contains(&Attr::BackgroundColor(color::BRIGHT_BLUE)));
- assert_eq!(cell.align, Alignment::CENTER);
-
- cell = cell.style_spec("FDBwr");
- assert_eq!(cell.style.len(), 2);
- assert!(cell.style.contains(&Attr::ForegroundColor(color::BRIGHT_BLACK)));
- assert!(cell.style.contains(&Attr::BackgroundColor(color::WHITE)));
- assert_eq!(cell.align, Alignment::RIGHT)
- }
-
- #[test]
- fn reset_style() {
- let mut cell = Cell::new("test").style_spec("FDBwr");
- assert_eq!(cell.style.len(), 2);
- cell.reset_style();
- assert_eq!(cell.style.len(), 0);
- assert_eq!(cell.align, Alignment::LEFT);
- }
-}
+} + +#[cfg(test)] +mod tests { + use cell::Cell; + use utils::StringWriter; + use format::Alignment; + use term::{Attr, color}; + + #[test] + fn get_content() { + let cell = Cell::new("test"); + assert_eq!(cell.get_content(), "test"); + } + + #[test] + fn print_ascii() { + let ascii_cell = Cell::new("hello"); + assert_eq!(ascii_cell.get_width(), 5); + + let mut out = StringWriter::new(); + let _ = ascii_cell.print(&mut out, 0, 10, false); + assert_eq!(out.as_string(), "hello "); + } + + #[test] + fn print_unicode() { + let unicode_cell = Cell::new("привет"); + assert_eq!(unicode_cell.get_width(), 6); + + let mut out = StringWriter::new(); + let _ = unicode_cell.print(&mut out, 0, 10, false); + assert_eq!(out.as_string(), "привет "); + } + + #[test] + fn print_cjk() { + let unicode_cell = Cell::new("由系统自动更新"); + assert_eq!(unicode_cell.get_width(), 14); + let mut out = StringWriter::new(); + let _ = unicode_cell.print(&mut out, 0, 20, false); + assert_eq!(out.as_string(), "由系统自动更新 "); + } + + #[test] + fn align_left() { + let cell = Cell::new_align("test", Alignment::LEFT); + let mut out = StringWriter::new(); + let _ = cell.print(&mut out, 0, 10, false); + assert_eq!(out.as_string(), "test "); + } + + #[test] + fn align_center() { + let cell = Cell::new_align("test", Alignment::CENTER); + let mut out = StringWriter::new(); + let _ = cell.print(&mut out, 0, 10, false); + assert_eq!(out.as_string(), " test "); + } + + #[test] + fn align_right() { + let cell = Cell::new_align("test", Alignment::RIGHT); + let mut out = StringWriter::new(); + let _ = cell.print(&mut out, 0, 10, false); + assert_eq!(out.as_string(), " test"); + } + + #[test] + fn style_spec() { + let mut cell = Cell::new("test").style_spec("FrBBbuic"); + assert_eq!(cell.style.len(), 5); + assert!(cell.style.contains(&Attr::Underline(true))); + assert!(cell.style.contains(&Attr::Italic(true))); + assert!(cell.style.contains(&Attr::Bold)); + assert!(cell.style.contains(&Attr::ForegroundColor(color::RED))); + assert!(cell.style + .contains(&Attr::BackgroundColor(color::BRIGHT_BLUE))); + assert_eq!(cell.align, Alignment::CENTER); + + cell = cell.style_spec("FDBwr"); + assert_eq!(cell.style.len(), 2); + assert!(cell.style + .contains(&Attr::ForegroundColor(color::BRIGHT_BLACK))); + assert!(cell.style.contains(&Attr::BackgroundColor(color::WHITE))); + assert_eq!(cell.align, Alignment::RIGHT) + } + + #[test] + fn reset_style() { + let mut cell = Cell::new("test").style_spec("FDBwr"); + assert_eq!(cell.style.len(), 2); + cell.reset_style(); + assert_eq!(cell.style.len(), 0); + assert_eq!(cell.align, Alignment::LEFT); + } +} diff --git a/src/format.rs b/src/format.rs index 8ff16cc..0293b67 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,259 +1,281 @@ -//! Define table formatting utilities
-
-use std::io::{Write, Error};
-
-use encode_unicode::Utf8Char;
-
-use super::utils::NEWLINE;
-
-/// Alignment for cell's content
-#[derive(Clone, Debug, PartialEq, Copy)]
-pub enum Alignment {
- LEFT,
- CENTER,
- RIGHT
-}
-
-/// Position of a line separator in a table
-#[derive(Clone, Debug, PartialEq, Copy)]
-pub enum LinePosition {
- Top,
- Title,
- Intern,
- Bottom
-}
-
-/// Position of a column separator in a row
-#[derive(Clone, Debug, PartialEq, Copy)]
-pub enum ColumnPosition {
- Left,
- Intern,
- Right
-}
-
-/// Contains the character used for printing a line separator
-#[derive(Clone, Debug, Copy)]
-pub struct LineSeparator {
- /// Line separator
- line: char,
- /// Internal junction separator
- junc: char,
- /// Left junction separator
- ljunc: char,
- /// Right junction separator
- rjunc: char
-}
-
-impl LineSeparator {
-
- /// Create a new line separator instance where `line` is the character used to separate 2 lines
- /// and `junc` is the one used for junctions between columns and lines
- pub fn new(line: char, junc: char, ljunc: char, rjunc: char) -> LineSeparator {
- LineSeparator{line: line, junc: junc, ljunc: ljunc, rjunc: rjunc}
- }
-
- /// Print a full line separator to `out`. `col_width` is a slice containing the width of each column
- 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(Utf8Char::from(self.ljunc).as_bytes()));
- }
- let mut iter = col_width.into_iter().peekable();
- while let Some(width) = iter.next() {
- for _ in 0..width+2 {
- try!(out.write_all(Utf8Char::from(self.line).as_bytes()));
- }
- if colsep && iter.peek().is_some() {
- try!(out.write_all(Utf8Char::from(self.junc).as_bytes()));
- }
- }
- if rborder {
- try!(out.write_all(Utf8Char::from(self.rjunc).as_bytes()));
- }
- out.write_all(NEWLINE)
- }
-}
-
-impl Default for LineSeparator {
- fn default() -> Self {
- LineSeparator::new('-', '+', '+', '+')
- }
-}
-
-/// Contains the table formatting rules
-#[derive(Clone, Debug, Copy)]
-pub struct TableFormat {
- /// Optional column separator character
- csep: Option<char>,
- /// Optional left border character
- lborder: Option<char>,
- /// Optional right border character
- rborder: Option<char>,
- /// Optional internal line separator
- lsep: Option<LineSeparator>,
- /// Optional title line separator
- tsep: Option<LineSeparator>,
- /// Optional top line separator
- top_sep: Option<LineSeparator>,
- /// Optional bottom line separator
- bottom_sep: Option<LineSeparator>,
- /// Left padding
- pad_left: usize,
- /// Right padding
- pad_right: usize
-}
-
-impl TableFormat {
-
- /// Create a new empty TableFormat.
- pub fn new() -> TableFormat {
- TableFormat{
- csep: None,
- lborder: None,
- rborder: None,
- lsep: None,
- tsep: None,
- top_sep: None,
- bottom_sep: None,
- pad_left: 0,
- pad_right: 0
- }
- }
-
- /// Return a tuple with left and right padding
- pub fn get_padding(&self) -> (usize, usize) {
- (self.pad_left, self.pad_right)
- }
-
- /// Set left and right padding
- pub fn padding(&mut self, left: usize, right: usize) {
- self.pad_left = left;
- self.pad_right = right;
- }
-
- /// Set the character used for internal column separation
- pub fn column_separator(&mut self, separator: char) {
- self.csep = Some(separator);
- }
-
- /// Set the character used for table borders
- pub fn borders(&mut self, border: char) {
- self.lborder = Some(border);
- self.rborder = Some(border);
- }
-
- /// Set a line separator
- pub fn separator(&mut self, what: LinePosition, separator: LineSeparator) {
+//! Define table formatting utilities + +use std::io::{Write, Error}; + +use encode_unicode::Utf8Char; + +use super::utils::NEWLINE; + +/// Alignment for cell's content +#[derive(Clone, Debug, PartialEq, Copy)] +pub enum Alignment { + LEFT, + CENTER, + RIGHT, +} + +/// Position of a line separator in a table +#[derive(Clone, Debug, PartialEq, Copy)] +pub enum LinePosition { + Top, + Title, + Intern, + Bottom, +} + +/// Position of a column separator in a row +#[derive(Clone, Debug, PartialEq, Copy)] +pub enum ColumnPosition { + Left, + Intern, + Right, +} + +/// Contains the character used for printing a line separator +#[derive(Clone, Debug, Copy)] +pub struct LineSeparator { + /// Line separator + line: char, + /// Internal junction separator + junc: char, + /// Left junction separator + ljunc: char, + /// Right junction separator + rjunc: char, +} + +impl LineSeparator { + /// Create a new line separator instance where `line` is the character used to separate 2 lines + /// and `junc` is the one used for junctions between columns and lines + pub fn new(line: char, junc: char, ljunc: char, rjunc: char) -> LineSeparator { + LineSeparator { + line: line, + junc: junc, + ljunc: ljunc, + rjunc: rjunc, + } + } + + /// Print a full line separator to `out`. `col_width` is a slice containing the width of each column + 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(Utf8Char::from(self.ljunc).as_bytes())); + } + let mut iter = col_width.into_iter().peekable(); + while let Some(width) = iter.next() { + for _ in 0..width + 2 { + try!(out.write_all(Utf8Char::from(self.line).as_bytes())); + } + if colsep && iter.peek().is_some() { + try!(out.write_all(Utf8Char::from(self.junc).as_bytes())); + } + } + if rborder { + try!(out.write_all(Utf8Char::from(self.rjunc).as_bytes())); + } + out.write_all(NEWLINE) + } +} + +impl Default for LineSeparator { + fn default() -> Self { + LineSeparator::new('-', '+', '+', '+') + } +} + +/// Contains the table formatting rules +#[derive(Clone, Debug, Copy)] +pub struct TableFormat { + /// Optional column separator character + csep: Option<char>, + /// Optional left border character + lborder: Option<char>, + /// Optional right border character + rborder: Option<char>, + /// Optional internal line separator + lsep: Option<LineSeparator>, + /// Optional title line separator + tsep: Option<LineSeparator>, + /// Optional top line separator + top_sep: Option<LineSeparator>, + /// Optional bottom line separator + bottom_sep: Option<LineSeparator>, + /// Left padding + pad_left: usize, + /// Right padding + pad_right: usize, +} + +impl TableFormat { + /// Create a new empty TableFormat. + pub fn new() -> TableFormat { + TableFormat { + csep: None, + lborder: None, + rborder: None, + lsep: None, + tsep: None, + top_sep: None, + bottom_sep: None, + pad_left: 0, + pad_right: 0, + } + } + + /// Return a tuple with left and right padding + pub fn get_padding(&self) -> (usize, usize) { + (self.pad_left, self.pad_right) + } + + /// Set left and right padding + pub fn padding(&mut self, left: usize, right: usize) { + self.pad_left = left; + self.pad_right = right; + } + + /// Set the character used for internal column separation + pub fn column_separator(&mut self, separator: char) { + self.csep = Some(separator); + } + + /// Set the character used for table borders + pub fn borders(&mut self, border: char) { + self.lborder = Some(border); + self.rborder = Some(border); + } + + /// Set a line separator + 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);
- }
-
- /// Set format for multiple kind of line 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> {
+ LinePosition::Top => &mut self.top_sep,
+ LinePosition::Bottom => &mut self.bottom_sep,
+ LinePosition::Title => &mut self.tsep,
+ LinePosition::Intern => &mut self.lsep,
+ } = Some(separator); + } + + /// Set format for multiple kind of line 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> { 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
+ LinePosition::Title => { + match &self.tsep {
+ s @ &Some(_) => s,
+ &None => &self.lsep,
+ } |