diff --git a/src/format/table.rs b/src/format/table.rs index c01d24ca4e..db126b9d1b 100644 --- a/src/format/table.rs +++ b/src/format/table.rs @@ -1,7 +1,6 @@ use crate::format::{RenderView, consts}; use crate::object::Value; use crate::prelude::*; -use ansi_term::Color; use derive_new::new; use textwrap::fill; @@ -9,8 +8,11 @@ use prettytable::{color, Attr, Cell, Row, Table}; #[derive(Debug, new)] pub struct TableView { + // List of header cell values: headers: Vec, - entries: Vec>, + + // List of rows of cells, each containing value and prettytable style-string: + entries: Vec>, } impl TableView { @@ -40,21 +42,26 @@ impl TableView { let mut entries = vec![]; for (idx, value) in values.iter().enumerate() { - let mut row: Vec = match value { + let mut row: Vec<(String, &'static str)> = match value { Tagged { item: Value::Object(..), .. } => headers .iter() .enumerate() - .map(|(i, d)| value.get_data(d).borrow().format_leaf(Some(&headers[i]))) + .map(|(i, d)| { + let data = value.get_data(d); + return (data.borrow().format_leaf(Some(&headers[i])), data.borrow().style_leaf()); + }) .collect(), - x => vec![x.format_leaf(None)], + x => vec![(x.format_leaf(None), x.style_leaf())], }; if values.len() > 1 { - row.insert(0, format!("{}", idx.to_string())); + // Indices are black, bold, right-aligned: + row.insert(0, (format!("{}", idx.to_string()), "Fdbr")); } + entries.push(row); } @@ -65,13 +72,15 @@ impl TableView { } for head in 0..headers.len() { - let mut current_row_max = 0; + let mut current_col_max = 0; for row in 0..values.len() { - if entries[row][head].len() > current_row_max { - current_row_max = entries[row][head].len(); + let value_length = entries[row][head].0.len(); + if value_length > current_col_max { + current_col_max = value_length; } } - max_per_column.push(std::cmp::max(current_row_max, headers[head].len())); + + max_per_column.push(std::cmp::max(current_col_max, headers[head].len())); } // Different platforms want different amounts of buffer, not sure why @@ -89,7 +98,7 @@ impl TableView { headers.push("...".to_string()); for row in 0..entries.len() { - entries[row].push("...".to_string()); + entries[row].push(("...".to_string(), "c")); // ellipsis is centred } } @@ -166,19 +175,11 @@ impl TableView { if max_per_column[head] > max_naive_column_width { headers[head] = fill(&headers[head], max_column_width); for row in 0..entries.len() { - entries[row][head] = fill(&entries[row][head], max_column_width); + entries[row][head].0 = fill(&entries[row][head].0, max_column_width); } } } - // Paint the number column, if it exists - if entries.len() > 1 { - for row in 0..entries.len() { - entries[row][0] = - format!("{}", Color::Black.bold().paint(entries[row][0].to_string())); - } - } - Some(TableView { headers, entries }) } } @@ -205,7 +206,7 @@ impl RenderView for TableView { table.set_titles(Row::new(header)); for row in &self.entries { - table.add_row(Row::new(row.iter().map(|h| Cell::new(h)).collect())); + table.add_row(Row::new(row.iter().map(|(v, s)| Cell::new(v).style_spec(s)).collect())); } table.print_term(&mut *host.out_terminal()).unwrap(); diff --git a/src/object/base.rs b/src/object/base.rs index ea86386c6c..56c63d257b 100644 --- a/src/object/base.rs +++ b/src/object/base.rs @@ -94,13 +94,13 @@ impl Primitive { let byte = byte_unit::Byte::from_bytes(*b as u128); if byte.get_bytes() == 0u128 { - return "".to_string(); + return "—".to_string(); } let byte = byte.get_appropriate_unit(false); match byte.get_unit() { - byte_unit::ByteUnit::B => format!("{}", byte.format(0)), + byte_unit::ByteUnit::B => format!("{} B ", byte.get_value()), _ => format!("{}", byte.format(1)), } } @@ -118,6 +118,16 @@ impl Primitive { Primitive::Date(d) => format!("{}", d.humanize()), } } + + pub fn style(&self) -> &'static str { + match self { + Primitive::Bytes(0) => "c", // centre 'missing' indicator + Primitive::Int(_) | + Primitive::Bytes(_) | + Primitive::Float(_) => "r", + _ => "" + } + } } #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new, Serialize)] @@ -459,6 +469,13 @@ impl Value { } } + crate fn style_leaf(&self) -> &'static str { + match self { + Value::Primitive(p) => p.style(), + _ => "" + } + } + #[allow(unused)] crate fn compare(&self, operator: &Operator, other: &Value) -> Result { match operator {