summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/format.rs99
-rw-r--r--src/lib.rs75
-rw-r--r--src/main.rs6
-rw-r--r--src/row.rs7
4 files changed, 146 insertions, 41 deletions
diff --git a/src/format.rs b/src/format.rs
new file mode 100644
index 0000000..c9ac29a
--- /dev/null
+++ b/src/format.rs
@@ -0,0 +1,99 @@
+//! Define table formatting utilities
+
+use std::io::{Write, Error};
+
+use super::utils::LINEFEED;
+
+/// Contains the character used for printing a line separator
+#[derive(Clone, Debug)]
+pub struct LineSeparator {
+ line: [u8; 1],
+ cross: [u8; 1],
+}
+
+impl LineSeparator {
+
+ /// Create a new line separator instance where `line` is the character used to separate 2 lines
+ /// and `cross` is the one used when column separaors and line separators cross
+ pub fn new(line: char, cross: char) -> LineSeparator {
+ return LineSeparator{line: [line as u8], cross: [cross as u8]};
+ }
+
+ /// Print a full line separator to `out`. `col_width` is a slice containing the width of each column
+ pub fn print<T: Write>(&self, out: &mut T, col_width: &[usize]) -> Result<(), Error> {
+ try!(out.write_all(&self.cross));
+ for width in col_width {
+ for _ in 0..(width + 2) {
+ try!(out.write_all(&self.line));
+ }
+ try!(out.write_all(&self.cross));
+ }
+ return out.write_all(LINEFEED);
+ }
+}
+
+/// Contains the table formatting rules
+#[derive(Clone, Debug)]
+pub struct TableFormat {
+ col_sep: [u8; 1],
+ line_sep: Option<LineSeparator>,
+ title_sep: Option<LineSeparator>
+}
+
+impl TableFormat {
+
+ /// Create a new TableFormat.
+ ///
+ /// `col_sep` is the character used for separating columns.
+ /// `line_sep` is an optional `LineSeparator` defining how to separate lines.
+ /// `title_sep` is an optional `LineSeparator` defining the format of the separator after the title line (if set).
+ /// If `title_sep` is set to `None`, then `line_sep` will be used, f it's set.
+ pub fn new(col_sep: char, line_sep: Option<LineSeparator>, title_sep: Option<LineSeparator>) -> TableFormat {
+ return TableFormat{col_sep: [col_sep as u8], line_sep: line_sep, title_sep: title_sep};
+ }
+
+ /// Print a full line separator to `out`. `col_width` is a slice containing the width of each column
+ pub fn print_line_separator<T: Write>(&self, out: &mut T, col_width: &[usize]) -> Result<(), Error> {
+ if let Some(ref l) = self.line_sep {
+ return l.print(out, col_width);
+ }
+ return Ok(());
+ }
+
+ /// Print a full title separator to `out`. `col_width` is a slice containing the width of each column
+ pub fn print_title_separator<T: Write>(&self, out: &mut T, col_width: &[usize]) -> Result<(), Error> {
+ if let Some(ref l) = self.title_sep {
+ return l.print(out, col_width);
+ }
+ return self.print_line_separator(out, col_width);
+ }
+
+ /// Print a column separator to `out`
+ pub fn print_column_separator<T: Write>(&self, out: &mut T) -> Result<(), Error> {
+ return out.write_all(&self.col_sep);
+ }
+}
+
+/// A line separator mad of `-` and `+`
+pub const MINUS_PLUS_SEP: LineSeparator = LineSeparator{line: ['-' as u8], cross: ['+' as u8]};
+/// A line separator mad of `=` and `+`
+pub const EQU_PLUS_SEP: LineSeparator = LineSeparator{line: ['=' as u8], cross: ['+' as u8]};
+
+/// Default table format, printing a table like this :
+///
+/// ```text
+/// +----+----+
+/// | T1 | T2 |
+/// +====+====+
+/// | | |
+/// +----+----+
+/// | | |
+/// +----+----+
+/// ```
+pub const FORMAT_DEFAULT: TableFormat = TableFormat{col_sep: ['|' as u8], line_sep: Some(MINUS_PLUS_SEP), title_sep: Some(EQU_PLUS_SEP)};
+
+/// Similar to `FORMAT_DEFAULT` but without special separator after title line
+pub const FORMAT_NO_LINESEP: TableFormat = TableFormat{col_sep: ['|' as u8], line_sep: None, title_sep: Some(MINUS_PLUS_SEP)};
+
+/// Format for printing a table without any separators (only alignment)
+pub const FORMAT_BLANK: TableFormat = TableFormat{col_sep: [' ' as u8], line_sep: None, title_sep: None}; \ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index d7a7806..f45ad55 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,19 +5,20 @@ use std::iter::{FromIterator, IntoIterator};
pub mod cell;
pub mod row;
+pub mod format;
mod utils;
use row::Row;
use cell::Cell;
-use utils::{StringWriter, LINEFEED};
+use format::{TableFormat, FORMAT_DEFAULT};
+use utils::StringWriter;
/// A Struct representing a printable table
#[derive(Clone, Debug)]
pub struct Table {
- rows: Vec<Row>,
- col_sep: char,
- line_sep: char,
- sep_cross: char
+ format: TableFormat,
+ titles: Option<Row>,
+ rows: Vec<Row>
}
impl Table {
@@ -30,22 +31,14 @@ impl Table {
pub fn init(rows: Vec<Row>) -> Table {
return Table {
rows: rows,
- col_sep: '|',
- line_sep: '-',
- sep_cross: '+'
+ titles: None,
+ format: FORMAT_DEFAULT
};
}
- /// Change separators
- ///
- /// `col` is the column separator
- /// `line` is the line separator
- /// `cross` is a special separator used when line and collumn separators meet
- /// Default separators used are '|', '-' and '+'
- pub fn separators(&mut self, col: char, line: char, cross: char) {
- self.col_sep = col;
- self.line_sep = line;
- self.sep_cross = cross;
+ /// Change separators the table format
+ pub fn set_format(&mut self, format: TableFormat) {
+ self.format = format;
}
/// Compute and return the number of column
@@ -65,6 +58,16 @@ impl Table {
return self.rows.len();
}
+ /// Set the optional title lines
+ pub fn set_titles(&mut self, titles: Row) {
+ self.titles = Some(titles);
+ }
+
+ /// Unset the title line
+ pub fn unset_titles(&mut self) {
+ self.titles = None;
+ }
+
/// Get a mutable reference to a row
pub fn get_mut_row(&mut self, row: usize) -> Option<&mut Row> {
return self.rows.get_mut(row);
@@ -112,8 +115,13 @@ impl Table {
}
}
- fn get_column_width(&self, col_idx: usize) -> usize {
- let mut width = 0;
+ /// Get the width of the column at position `col_idx`.
+ /// Return 0 if the column does not exists;
+ pub fn get_column_width(&self, col_idx: usize) -> usize {
+ let mut width = match self.titles {
+ Some(ref t) => t.get_cell_width(col_idx),
+ None => 0
+ };
for r in &self.rows {
let l = r.get_cell_width(col_idx);
if l > width {
@@ -123,7 +131,9 @@ impl Table {
return width;
}
- fn get_all_column_width(&self) -> Vec<usize> {
+ /// Get the width of all columns, and return a slice
+ /// with the result for each column
+ pub fn get_all_column_width(&self) -> Vec<usize> {
let colnum = self.get_column_num();
let mut col_width = vec![0usize; colnum];
for i in 0..colnum {
@@ -132,26 +142,19 @@ impl Table {
return col_width;
}
- fn print_line_separator<T: Write>(&self, out: &mut T, col_width: &[usize]) -> Result<(), Error> {
- try!(out.write_all(self.sep_cross.to_string().as_bytes()));
- for width in col_width {
- for _ in 0..(width + 2) {
- try!(out.write_all(self.line_sep.to_string().as_bytes()));
- }
- try!(out.write_all(self.sep_cross.to_string().as_bytes()));
- }
- return out.write_all(LINEFEED);
- }
-
/// Print the table to `out`
pub fn print<T: Write>(&self, out: &mut T) -> Result<(), Error> {
// Compute columns width
let col_width = self.get_all_column_width();
- try!(self.print_line_separator(out, &col_width));
+ try!(self.format.print_line_separator(out, &col_width));
+ if let Some(ref t) = self.titles {
+ try!(t.print(out, &self.format, &col_width));
+ try!(self.format.print_title_separator(out, &col_width));
+ }
// Print rows
for r in &self.rows {
- try!(r.print(out, self.col_sep, &col_width));
- try!(self.print_line_separator(out, &col_width));
+ try!(r.print(out, &self.format, &col_width));
+ try!(self.format.print_line_separator(out, &col_width));
}
return out.flush();
}
@@ -168,7 +171,7 @@ impl Table {
impl fmt::Display for Table {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- let mut writer = StringWriter::new();
+ let mut writer = StringWriter::new();
if let Err(_) = self.print(&mut writer) {
return Err(fmt::Error)
}
diff --git a/src/main.rs b/src/main.rs
index 2c968f7..6f48ae1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,6 +2,7 @@
use prettytable::Table;
use prettytable::row::Row;
use prettytable::cell::Cell;
+use prettytable::format::*;
#[allow(dead_code)]
fn main() {
@@ -15,11 +16,12 @@ fn main() {
);
table.printstd();
println!("Modified : ");
- table.separators('|', '=', '+');
table.set_element(&"new_foo".to_string(), 2, 1).unwrap();
table.printstd();
- let table = table!(["A", "B", "C"], [1, 2, 3, 4], ["A\nBCCZZZ\nDDD", 2, table]);
+ let mut table = table!(["A", "B", "C"], [1, 2, 3, 4], ["A\nBCCZZZ\nDDD", 2, table]);
+ table.set_titles(row!["Title 1", "Title 2"]);
+ table.set_format(FORMAT_DEFAULT);
table.printstd();
println!("{:?}", table);
}
diff --git a/src/row.rs b/src/row.rs
index cbf1e91..ffdf890 100644
--- a/src/row.rs
+++ b/src/row.rs
@@ -4,6 +4,7 @@ use std::iter::FromIterator;
use super::utils::LINEFEED;
use super::cell::Cell;
+use super::format::TableFormat;
/// Represent a table row made of cells
#[derive(Clone, Debug)]
@@ -88,15 +89,15 @@ impl Row {
/// Print the row to `out`, with `separator` as column separator, and `col_width`
/// specifying the width of each columns
- pub fn print<T: Write>(&self, out: &mut T, separator: char, col_width: &[usize]) -> Result<(), Error> {
+ pub fn print<T: Write>(&self, out: &mut T, format: &TableFormat, col_width: &[usize]) -> Result<(), Error> {
for i in 0..self.get_height() {
- try!(out.write_all(separator.to_string().as_bytes()));
+ try!(format.print_column_separator(out));
for j in 0..col_width.len() {
match self.get_cell(j) {
Some(ref c) => try!(c.print(out, i, col_width[j])),
None => try!(Cell::default().print(out, i, col_width[j]))
};
- try!(out.write_all(separator.to_string().as_bytes()));
+ try!(format.print_column_separator(out));
}
try!(out.write_all(LINEFEED));
}