summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--examples/basic.rs8
-rw-r--r--src/cell.rs80
-rw-r--r--src/format.rs12
-rw-r--r--src/lib.rs41
-rw-r--r--src/main.rs14
-rw-r--r--src/row.rs9
-rw-r--r--src/utils.rs6
8 files changed, 140 insertions, 32 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 8fe27f9..95f4ac4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "prettytable-rs"
-version = "0.1.2"
+version = "0.1.3"
description = "A small rust library that print aligned and formatted tables"
repository = "https://github.com/phsym/prettytable-rs"
documentation = "http://phsym.github.io/prettytable-rs"
diff --git a/examples/basic.rs b/examples/basic.rs
index 13cc661..a7def3a 100644
--- a/examples/basic.rs
+++ b/examples/basic.rs
@@ -26,13 +26,13 @@ fn main() {
table.add_row(row!["ABC", "DEFG", "HIJKLMN"]);
table.add_row(row!["foobar", "bar", "foo"]);
table.add_row(Row::new(vec![
- Cell::new(&"foobar2".to_string()),
- Cell::new(&"bar2".to_string()),
- Cell::new(&"foo2".to_string())])
+ Cell::new("foobar2"),
+ Cell::new("bar2"),
+ Cell::new("foo2")])
);
table.printstd();
println!("Modified : ");
- table.set_element(&"new_foo".to_string(), 2, 1).unwrap();
+ table.set_element("new_foo", 2, 1).unwrap();
table.printstd();
// The same table can be built the following way :
diff --git a/src/cell.rs b/src/cell.rs
index 5001538..d57908d 100644
--- a/src/cell.rs
+++ b/src/cell.rs
@@ -2,7 +2,9 @@
use std::io::{Write, Error};
use std::string::ToString;
+use std::str::FromStr;
use unicode_width::UnicodeWidthStr;
+use super::format::Align;
/// Represent a table cell containing a string.
///
@@ -11,12 +13,14 @@ use unicode_width::UnicodeWidthStr;
#[derive(Clone, Debug)]
pub struct Cell {
content: Vec<String>,
- width: usize
+ width: usize,
+ align: Align
}
impl Cell {
- /// Create a new `Cell` initialized with content from `string`
- pub fn new(string: &String) -> 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: Align) -> Cell {
let content: Vec<String> = string.lines_any().map(|ref x| x.to_string()).collect();
let mut width = 0;
for cont in &content {
@@ -27,10 +31,22 @@ impl Cell {
}
return Cell {
content: content,
- width: width
+ width: width,
+ align: align
};
}
+ /// Create a new `Cell` initialized with content from `string`.
+ /// By default, content is align to `LEFT`
+ pub fn new(string: &str) -> Cell {
+ return Cell::new_align(string, Align::LEFT);
+ }
+
+ /// Set text alignment in the cell
+ pub fn align(&mut self, align: Align) {
+ self.align = align;
+ }
+
/// Return the height of the cell
pub fn get_height(&self) -> usize {
return self.content.len();
@@ -51,14 +67,15 @@ impl Cell {
/// 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>(&self, out: &mut T, idx: usize, col_width: usize) -> Result<(), Error> {
- try!(out.write_all(b" "));
- let mut len = 0;
- if let Some(content) = self.content.get(idx) {
- try!(out.write_all(content.as_bytes()));
- len = UnicodeWidthStr::width(&content[..]);
+ let c = match self.content.get(idx) {
+ Some(s) => s.as_ref(),
+ None => ""
+ };
+ return match self.align {
+ Align::LEFT => write!(out, " {: <1$} ", c, col_width),
+ Align::CENTER => write!(out, " {: ^1$} ", c, col_width),
+ Align::RIGHT => write!(out, " {: >1$} ", c, col_width),
}
- try!(out.write_all(&vec![' ' as u8; col_width - len + 1]));
- return Ok(());
}
}
@@ -68,6 +85,13 @@ impl <'a, T: ToString> From<&'a T> for Cell {
}
}
+impl FromStr for Cell {
+ type Err = ();
+ fn from_str(s: &str) -> Result<Cell, Self::Err> {
+ return Ok(Cell::new(s));
+ }
+}
+
impl ToString for Cell {
fn to_string(&self) -> String {
return self.get_content();
@@ -75,11 +99,12 @@ impl ToString for Cell {
}
impl Default for Cell {
- /// Return a cell initialized with a single empty `String`
+ /// Return a cell initialized with a single empty `String`, with LEFT alignment
fn default() -> Cell {
return Cell {
content: vec!["".to_string(); 1],
- width: 0
+ width: 0,
+ align: Align::LEFT
};
}
}
@@ -88,10 +113,11 @@ impl Default for Cell {
mod tests {
use cell::Cell;
use utils::StringWriter;
+ use format::Align;
#[test]
fn ascii() {
- let ascii_cell = Cell::new(&String::from("hello"));
+ let ascii_cell = Cell::new("hello");
assert_eq!(ascii_cell.get_width(), 5);
let mut out = StringWriter::new();
@@ -101,12 +127,36 @@ mod tests {
#[test]
fn unicode() {
- let unicode_cell = Cell::new(&String::from("привет"));
+ 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);
assert_eq!(out.as_string(), " привет ");
}
+
+ #[test]
+ fn align_left() {
+ let cell = Cell::new_align("test", Align::LEFT);
+ let mut out = StringWriter::new();
+ let _ = cell.print(&mut out, 0, 10);
+ assert_eq!(out.as_string(), " test ");
+ }
+
+ #[test]
+ fn align_center() {
+ let cell = Cell::new_align("test", Align::CENTER);
+ let mut out = StringWriter::new();
+ let _ = cell.print(&mut out, 0, 10);
+ assert_eq!(out.as_string(), " test ");
+ }
+
+ #[test]
+ fn align_right() {
+ let cell = Cell::new_align("test", Align::RIGHT);
+ let mut out = StringWriter::new();
+ let _ = cell.print(&mut out, 0, 10);
+ assert_eq!(out.as_string(), " test ");
+ }
}
diff --git a/src/format.rs b/src/format.rs
index 2ccb02a..048d6d1 100644
--- a/src/format.rs
+++ b/src/format.rs
@@ -2,7 +2,15 @@
use std::io::{Write, Error};
-use super::utils::LINEFEED;
+use super::utils::NEWLINE;
+
+/// Alignment for cell's content
+#[derive(Clone, Debug)]
+pub enum Align {
+ LEFT,
+ CENTER,
+ RIGHT
+}
/// Contains the character used for printing a line separator
#[derive(Clone, Debug)]
@@ -26,7 +34,7 @@ impl LineSeparator {
try!(out.write_all(&vec![self.line[0]; width+2]));
try!(out.write_all(&self.cross));
}
- return out.write_all(LINEFEED);
+ return out.write_all(NEWLINE);
}
}
diff --git a/src/lib.rs b/src/lib.rs
index a255405..08db98a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -105,8 +105,9 @@ impl Table {
}
/// Modify a single element in the table
- pub fn set_element(&mut self, element: &String, column: usize, row: usize) -> Result<(), &str> {
+ pub fn set_element(&mut self, element: &str, column: usize, row: usize) -> Result<(), &str> {
let rowline = try!(self.get_mut_row(row).ok_or("Cannot find row"));
+ // TODO : If a cell already exist, copy it's alignment parameter
return rowline.set_cell(Cell::new(element), column);
}
@@ -144,6 +145,16 @@ impl Table {
return col_width;
}
+ /// Return an iterator over the immutable cells of the column specified by `column`
+ pub fn column_iter(&self, column: usize) -> ColumnIter {
+ return ColumnIter(self.rows.iter(), column);
+ }
+
+ /// Return an iterator over the mutable cells of the column specified by `column`
+ pub fn column_iter_mut(&mut self, column: usize) -> ColumnIterMut {
+ return ColumnIterMut(self.rows.iter_mut(), column);
+ }
+
/// Print the table to `out`
pub fn print<T: Write>(&self, out: &mut T) -> Result<(), Error> {
// Compute columns width
@@ -193,6 +204,34 @@ impl <T, A, B> From<T> for Table where B: ToString, A: IntoIterator<Item=B>, T :
}
}
+/// Iterator over immutable cells in a column
+pub struct ColumnIter<'a>(std::slice::Iter<'a, Row>, usize);
+
+impl <'a> std::iter::Iterator for ColumnIter<'a> {
+ type Item = &'a Cell;
+
+ fn next(&mut self) -> Option<&'a Cell> {
+ return match self.0.next() {
+ None => None,
+ Some(row) => row.get_cell(self.1)
+ }
+ }
+}
+
+/// Iterator over mutable cells in a column
+pub struct ColumnIterMut<'a>(std::slice::IterMut<'a, Row>, usize);
+
+impl <'a> std::iter::Iterator for ColumnIterMut<'a> {
+ type Item = &'a mut Cell;
+
+ fn next(&mut self) -> Option<&'a mut Cell> {
+ return match self.0.next() {
+ None => None,
+ Some(row) => row.get_mut_cell(self.1)
+ }
+ }
+}
+
/// Create a table filled with some values
///
/// All the arguments used for elements must implement the `std::string::ToString` trait
diff --git a/src/main.rs b/src/main.rs
index 3a0bdd2..59952de 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,13 +10,19 @@ fn main() {
table.add_row(row!["ABC", "DEFG", "HIJKLMN"]);
table.add_row(row!["foobar", "bar", "foo"]);
table.add_row(Row::new(vec![
- Cell::new(&"foobar2".to_string()),
- Cell::new(&"bar2".to_string()),
- Cell::new(&"foo2".to_string())])
+ Cell::new("foobar2"),
+ Cell::new("bar2"),
+ Cell::new("foo2")])
);
+ for cell in table.column_iter_mut(2) {
+ cell.align(Align::RIGHT);
+ }
+ for cell in table.column_iter_mut(1) {
+ cell.align(Align::CENTER);
+ }
table.printstd();
println!("Modified : ");
- table.set_element(&"new_foo".to_string(), 2, 1).unwrap();
+ table.set_element("new_foo", 2, 1).unwrap();
table.printstd();
ptable!(["A", "B", "C"], [1, 2, 3, 4]);
diff --git a/src/row.rs b/src/row.rs
index ffdf890..4265fe2 100644
--- a/src/row.rs
+++ b/src/row.rs
@@ -2,7 +2,7 @@
use std::io::{Write, Error};
use std::iter::FromIterator;
-use super::utils::LINEFEED;
+use super::utils::NEWLINE;
use super::cell::Cell;
use super::format::TableFormat;
@@ -56,6 +56,11 @@ impl Row {
return self.cells.get(idx);
}
+ /// Get the mutable cell at index `idx`
+ pub fn get_mut_cell(&mut self, idx: usize) -> Option<&mut Cell> {
+ return self.cells.get_mut(idx);
+ }
+
/// Set the `cell` in the row at the given `column`
pub fn set_cell(&mut self, cell: Cell, column: usize) -> Result<(), &str> {
if column >= self.len() {
@@ -99,7 +104,7 @@ impl Row {
};
try!(format.print_column_separator(out));
}
- try!(out.write_all(LINEFEED));
+ try!(out.write_all(NEWLINE));
}
return Ok(());
}
diff --git a/src/utils.rs b/src/utils.rs
index ab18d04..d460441 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -3,9 +3,9 @@ use std::io::{Error, ErrorKind, Write};
use std::str;
#[cfg(any(unix, macos))]
-pub static LINEFEED: &'static [u8] = b"\n";
+pub static NEWLINE: &'static [u8] = b"\n";
#[cfg(windows)]
-pub static LINEFEED: &'static [u8] = b"\r\n";
+pub static NEWLINE: &'static [u8] = b"\r\n";
/// Internal utility for writing data into a string
pub struct StringWriter {
@@ -19,7 +19,7 @@ impl StringWriter {
}
/// Return a reference to the internally written `String`
- pub fn as_string(&self) -> &String {
+ pub fn as_string(&self) -> &str {
return &self.string;
}
}