From 89c737f4564479e31bb1b7c2b816085e1f07fe28 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Sat, 20 Jun 2020 12:25:07 -0700 Subject: [PATCH] Finish move to nu-table (#2025) --- Cargo.lock | 23 +--- crates/nu-cli/Cargo.toml | 1 - crates/nu-cli/src/commands/autoview.rs | 101 +++-------------- crates/nu-cli/src/commands/table.rs | 15 ++- crates/nu-table/src/table.rs | 128 +++++++++++++--------- crates/nu_plugin_textview/src/textview.rs | 4 - 6 files changed, 111 insertions(+), 161 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 95e3286337..5a44529ad8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1899,9 +1899,9 @@ dependencies = [ [[package]] name = "kstring" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6382df53100fd22e149030b6634720c94a151076db8d727b3274d7070975d609" +checksum = "fbbc30beb80d56ddf6346e935c7abcba96329ee5c5a4cde8984a4e6b6f18b58e" dependencies = [ "serde 1.0.110", ] @@ -2038,9 +2038,9 @@ dependencies = [ [[package]] name = "liquid-core" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea59709d9530bab4e9cc0ece12f20fe4999fdef90f7d89391b0fc9ff563b62b" +checksum = "4dc58422728185d54cd044bba4d45a2ef2a7111a421f84d344f65629949de4f1" dependencies = [ "anymap", "chrono", @@ -2481,7 +2481,6 @@ dependencies = [ "pin-utils", "pretty-hex", "pretty_env_logger", - "prettytable-rs", "ptree", "query_interface", "quickcheck", @@ -3235,20 +3234,6 @@ dependencies = [ "log", ] -[[package]] -name = "prettytable-rs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fd04b170004fa2daccf418a7f8253aaf033c27760b5f225889024cf66d7ac2e" -dependencies = [ - "atty", - "csv", - "encode_unicode", - "lazy_static 1.4.0", - "term", - "unicode-width", -] - [[package]] name = "proc-macro-error" version = "1.0.2" diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index d9c8c36383..070e8f04bb 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -62,7 +62,6 @@ parking_lot = "0.10.2" pin-utils = "0.1.0" pretty-hex = "0.1.1" pretty_env_logger = "0.4.0" -prettytable-rs = "0.8.0" ptree = {version = "0.2" } query_interface = "0.3.5" rand = "0.7" diff --git a/crates/nu-cli/src/commands/autoview.rs b/crates/nu-cli/src/commands/autoview.rs index c587d603b3..eac2317a67 100644 --- a/crates/nu-cli/src/commands/autoview.rs +++ b/crates/nu-cli/src/commands/autoview.rs @@ -6,10 +6,7 @@ use nu_errors::ShellError; use nu_protocol::{hir, hir::Expression, hir::Literal, hir::SpannedExpression}; use nu_protocol::{Primitive, Scope, Signature, UntaggedValue, Value}; use parking_lot::Mutex; -use prettytable::format::{FormatBuilder, LinePosition, LineSeparator}; -use prettytable::{color, Attr, Cell, Row, Table}; use std::sync::atomic::AtomicBool; -use textwrap::fill; pub struct Autoview; @@ -268,90 +265,28 @@ pub async fn autoview(context: RunnableContext) -> Result textwrap::termwidth()) => { - let termwidth = std::cmp::max(textwrap::termwidth(), 20); - - enum TableMode { - Light, - Normal, - } - - let mut table = Table::new(); - let table_mode = crate::data::config::config(Tag::unknown()); - - let table_mode = if let Some(s) = table_mode?.get("table_mode") { - match s.as_string() { - Ok(typ) if typ == "light" => TableMode::Light, - _ => TableMode::Normal, - } - } else { - TableMode::Normal - }; - - match table_mode { - TableMode::Light => { - table.set_format( - FormatBuilder::new() - .separator( - LinePosition::Title, - LineSeparator::new('─', '─', ' ', ' '), - ) - .separator( - LinePosition::Bottom, - LineSeparator::new(' ', ' ', ' ', ' '), - ) - .padding(1, 1) - .build(), - ); - } - _ => { - table.set_format( - FormatBuilder::new() - .column_separator('│') - .separator( - LinePosition::Top, - LineSeparator::new('─', '┬', ' ', ' '), - ) - .separator( - LinePosition::Title, - LineSeparator::new('─', '┼', ' ', ' '), - ) - .separator( - LinePosition::Bottom, - LineSeparator::new('─', '┴', ' ', ' '), - ) - .padding(1, 1) - .build(), - ); - } - } - - let mut max_key_len = 0; - for (key, _) in row.entries.iter() { - max_key_len = std::cmp::max(max_key_len, key.chars().count()); - } - - if max_key_len > (termwidth / 2 - 1) { - max_key_len = termwidth / 2 - 1; - } - - let max_val_len = termwidth - max_key_len - 5; - + let mut entries = vec![]; for (key, value) in row.entries.iter() { - table.add_row(Row::new(vec![ - Cell::new(&fill(&key, max_key_len)) - .with_style(Attr::ForegroundColor(color::GREEN)) - .with_style(Attr::Bold), - Cell::new(&fill( - &format_leaf(value).plain_string(100_000), - max_val_len, - )), - ])); + entries.push(vec![ + nu_table::StyledString::new( + key.to_string(), + nu_table::TextStyle { + alignment: nu_table::Alignment::Left, + color: Some(ansi_term::Color::Green), + is_bold: true, + }, + ), + nu_table::StyledString::new( + format_leaf(value).plain_string(100_000), + nu_table::TextStyle::basic(), + ), + ]); } - table.printstd(); + let table = + nu_table::Table::new(vec![], entries, nu_table::Theme::compact()); - // table.print_term(&mut *context.host.lock().out_terminal().ok_or_else(|| ShellError::untagged_runtime_error("Could not open terminal for output"))?) - // .map_err(|_| ShellError::untagged_runtime_error("Internal error: could not print to terminal (for unix systems check to make sure TERM is set)"))?; + nu_table::draw_table(&table, textwrap::termwidth()); } Value { diff --git a/crates/nu-cli/src/commands/table.rs b/crates/nu-cli/src/commands/table.rs index 9953dbda93..ea63864285 100644 --- a/crates/nu-cli/src/commands/table.rs +++ b/crates/nu-cli/src/commands/table.rs @@ -56,7 +56,7 @@ fn str_to_color(s: String) -> Option { pub fn from_list(values: &[Value], starting_idx: usize) -> nu_table::Table { let config = crate::data::config::config(Tag::unknown()); - let header_style = if let Ok(config) = config { + let header_style = if let Ok(config) = &config { let header_align = config.get("header_align").map_or(Alignment::Left, |a| { a.as_string() .map_or(Alignment::Center, |a| match a.to_lowercase().as_str() { @@ -97,6 +97,19 @@ pub fn from_list(values: &[Value], starting_idx: usize) -> nu_table::Table { .collect(); let entries = values_to_entries(values, &mut headers, starting_idx); + if let Ok(config) = config { + if let Some(style) = config.get("table_mode") { + if let Ok(table_mode) = style.as_string() { + if table_mode == "light" { + return nu_table::Table { + headers, + data: entries, + theme: Theme::light(), + }; + } + } + } + } nu_table::Table { headers, data: entries, diff --git a/crates/nu-table/src/table.rs b/crates/nu-table/src/table.rs index 7ad91e9085..5bd8877bdd 100644 --- a/crates/nu-table/src/table.rs +++ b/crates/nu-table/src/table.rs @@ -81,6 +81,8 @@ pub struct Theme { pub print_left_border: bool, pub print_right_border: bool, + pub print_top_border: bool, + pub print_bottom_border: bool, } impl Theme { @@ -108,6 +110,8 @@ impl Theme { print_left_border: true, print_right_border: true, + print_top_border: true, + print_bottom_border: true, } } #[allow(unused)] @@ -136,6 +140,8 @@ impl Theme { print_left_border: true, print_right_border: true, + print_top_border: true, + print_bottom_border: true, } } #[allow(unused)] @@ -160,10 +166,12 @@ impl Theme { right_vertical: ' ', separate_header: true, - separate_rows: true, + separate_rows: false, print_left_border: true, print_right_border: true, + print_top_border: false, + print_bottom_border: true, } } #[allow(unused)] @@ -191,6 +199,8 @@ impl Theme { print_left_border: false, print_right_border: false, + print_top_border: true, + print_bottom_border: true, } } } @@ -227,84 +237,77 @@ pub struct WrappedTable { } impl WrappedTable { - //TODO: optimize this fn print_separator(&self, separator_position: SeparatorPosition) { let column_count = self.column_widths.len(); + let mut output = String::new(); match separator_position { SeparatorPosition::Top => { for column in self.column_widths.iter().enumerate() { if column.0 == 0 && self.theme.print_left_border { - print!("{}", self.theme.top_left); + output.push(self.theme.top_left); } - print!( - "{}", - std::iter::repeat(self.theme.top_horizontal) - .take(*column.1) - .collect::() - ); - print!("{}{}", self.theme.top_horizontal, self.theme.top_horizontal); + for _ in 0..*column.1 { + output.push(self.theme.top_horizontal); + } + + output.push(self.theme.top_horizontal); + output.push(self.theme.top_horizontal); if column.0 == column_count - 1 { if self.theme.print_right_border { - print!("{}", self.theme.top_right); + output.push(self.theme.top_right); } } else { - print!("{}", self.theme.top_center); + output.push(self.theme.top_center); } } } SeparatorPosition::Middle => { for column in self.column_widths.iter().enumerate() { if column.0 == 0 && self.theme.print_left_border { - print!("{}", self.theme.middle_left); + output.push(self.theme.middle_left); } - print!( - "{}", - std::iter::repeat(self.theme.middle_horizontal) - .take(*column.1) - .collect::() - ); - print!( - "{}{}", - self.theme.middle_horizontal, self.theme.middle_horizontal - ); + for _ in 0..*column.1 { + output.push(self.theme.middle_horizontal); + } + + output.push(self.theme.middle_horizontal); + output.push(self.theme.middle_horizontal); + if column.0 == column_count - 1 { if self.theme.print_right_border { - print!("{}", self.theme.middle_right); + output.push(self.theme.middle_right); } } else { - print!("{}", self.theme.center); + output.push(self.theme.center); } } } SeparatorPosition::Bottom => { for column in self.column_widths.iter().enumerate() { if column.0 == 0 && self.theme.print_left_border { - print!("{}", self.theme.bottom_left); + output.push(self.theme.bottom_left); } - print!( - "{}", - std::iter::repeat(self.theme.bottom_horizontal) - .take(*column.1) - .collect::() - ); + for _ in 0..*column.1 { + output.push(self.theme.bottom_horizontal); + } + output.push(self.theme.bottom_horizontal); + output.push(self.theme.bottom_horizontal); - print!( - "{}{}", - self.theme.bottom_horizontal, self.theme.bottom_horizontal - ); if column.0 == column_count - 1 { if self.theme.print_right_border { - print!("{}", self.theme.bottom_right); + output.push(self.theme.bottom_right); } } else { - print!("{}", self.theme.bottom_center); + output.push(self.theme.bottom_center); } } } } + + println!("{}", output); } fn print_cell_contents(&self, cells: &[WrappedCell]) { @@ -399,10 +402,13 @@ impl WrappedTable { return; } - self.print_separator(SeparatorPosition::Top); - println!(); + if self.theme.print_top_border { + self.print_separator(SeparatorPosition::Top); + } - self.print_cell_contents(&self.headers); + if !self.headers.is_empty() { + self.print_cell_contents(&self.headers); + } let mut first_row = true; @@ -410,21 +416,21 @@ impl WrappedTable { if !first_row { if self.theme.separate_rows { self.print_separator(SeparatorPosition::Middle); - println!(); } } else { first_row = false; - if self.theme.separate_header { + if self.theme.separate_header && !self.headers.is_empty() { self.print_separator(SeparatorPosition::Middle); - println!(); } } self.print_cell_contents(row); } - self.print_separator(SeparatorPosition::Bottom); - println!(); + + if self.theme.print_bottom_border { + self.print_separator(SeparatorPosition::Bottom); + } } } @@ -499,6 +505,17 @@ pub fn draw_table(table: &Table, termwidth: usize) { // maybe_truncate_columns(&mut headers, &mut entries, termwidth); let headers_len = table.headers.len(); + // fix the length of the table if there are no headers: + let headers_len = if headers_len == 0 { + if !table.data.is_empty() && !table.data[0].is_empty() { + table.data[0].len() + } else { + return; + } + } else { + headers_len + }; + // Measure how big our columns need to be (accounting for separators also) let max_naive_column_width = (termwidth - 3 * (headers_len - 1)) / headers_len; @@ -518,18 +535,23 @@ pub fn draw_table(table: &Table, termwidth: usize) { // This should give us the final max column width let max_column_width = column_space.max_width(termwidth); - let wrapped_table = wrap_cells( - processed_table, - // max_per_column, - // max_naive_column_width, - max_column_width, - ); + let wrapped_table = wrap_cells(processed_table, max_column_width); wrapped_table.new_print_table(); } fn wrap_cells(processed_table: ProcessedTable, max_column_width: usize) -> WrappedTable { - let mut column_widths = vec![0; processed_table.headers.len()]; + let mut column_widths = vec![ + 0; + std::cmp::max( + processed_table.headers.len(), + if !processed_table.data.is_empty() { + processed_table.data[0].len() + } else { + 0 + } + ) + ]; let mut output_headers = vec![]; for header in processed_table.headers.into_iter().enumerate() { let wrapped = wrap( diff --git a/crates/nu_plugin_textview/src/textview.rs b/crates/nu_plugin_textview/src/textview.rs index c050ff189c..a1a5dedd0f 100644 --- a/crates/nu_plugin_textview/src/textview.rs +++ b/crates/nu_plugin_textview/src/textview.rs @@ -134,11 +134,7 @@ pub fn view_text_value(value: &Value) { _ => (), } } - } else { - println!("Couldn't find bat section in config"); } - } else { - println!("Error reading config!"); } let value_anchor = value.anchor();