From 4f812a7f34fb962c3e4eae74db02e81d320eb010 Mon Sep 17 00:00:00 2001 From: Maxim Zhiburt Date: Tue, 27 Dec 2022 16:44:34 +0300 Subject: [PATCH] Fix table expand wrap in case no header is there (#7605) ref #7598 To be honest I was not able to obtain such results in basic mode as you @rgwood. But I've got it in `table -e`. So this must fix the `table -e` wrapping. Could you verify if it got fixed? Signed-off-by: Maxim Zhiburt --- crates/nu-command/src/viewers/table.rs | 59 ++++++++++++++++++------ crates/nu-explore/src/nu_common/table.rs | 56 ++++++++++++++++------ crates/nu-table/src/util.rs | 27 ++++------- 3 files changed, 96 insertions(+), 46 deletions(-) diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs index 092cf46b85..676e04946a 100644 --- a/crates/nu-command/src/viewers/table.rs +++ b/crates/nu-command/src/viewers/table.rs @@ -2,6 +2,7 @@ use lscolors::{LsColors, Style}; use nu_color_config::color_from_hex; use nu_color_config::{Alignment, StyleComputer, TextStyle}; use nu_engine::{column::get_columns, env_to_string, CallExt}; +use nu_protocol::TrimStrategy; use nu_protocol::{ ast::{Call, PathMember}, engine::{Command, EngineState, Stack, StateWorkingSet}, @@ -550,13 +551,13 @@ fn build_expanded_table( style_computer, ); - wrap_text(failed_value.0, remaining_width) + wrap_text(failed_value.0, remaining_width, config) } } } val => { let text = value_to_styled_string(&val, config, style_computer).0; - wrap_text(text, remaining_width) + wrap_text(text, remaining_width, config) } } }; @@ -1041,6 +1042,10 @@ fn convert_to_table2<'a>( } if !with_header { + if available_width >= ADDITIONAL_CELL_SPACE { + available_width -= PADDING_SPACE; + } + for (row, item) in input.into_iter().enumerate() { if nu_utils::ctrl_c::was_pressed(&ctrlc) { return Ok(None); @@ -1145,7 +1150,7 @@ fn convert_to_table2<'a>( } let value = create_table2_entry_basic(item, &header, head, config, style_computer); - let value = wrap_nu_text(value, available_width); + let value = wrap_nu_text(value, available_width, config); let value_width = string_width(&value.0); column_width = max(column_width, value_width); @@ -1170,7 +1175,7 @@ fn convert_to_table2<'a>( } let value = create_table2_entry_basic(item, &header, head, config, style_computer); - let value = wrap_nu_text(value, OK_CELL_CONTENT_WIDTH); + let value = wrap_nu_text(value, OK_CELL_CONTENT_WIDTH, config); let value = NuTable::create_cell(value.0, value.1); @@ -1300,7 +1305,7 @@ fn create_table2_entry( flatten_sep, width, ), - Err(_) => wrap_nu_text(error_sign(style_computer), width), + Err(_) => wrap_nu_text(error_sign(style_computer), width, config), } } _ => convert_to_table2_entry( @@ -1320,21 +1325,21 @@ fn error_sign(style_computer: &StyleComputer) -> (String, TextStyle) { make_styled_string(style_computer, String::from("❎"), None, 0) } -fn wrap_nu_text(mut text: NuText, width: usize) -> NuText { +fn wrap_nu_text(mut text: NuText, width: usize, config: &Config) -> NuText { if string_width(&text.0) <= width { return text; } - text.0 = nu_table::wrap_string(&text.0, width); + text.0 = nu_table::string_wrap(&text.0, width, is_cfg_trim_keep_words(config)); text } -fn wrap_text(text: String, width: usize) -> String { +fn wrap_text(text: String, width: usize, config: &Config) -> String { if string_width(&text) <= width { return text; } - nu_table::wrap_string(&text, width) + nu_table::string_wrap(&text, width, is_cfg_trim_keep_words(config)) } #[allow(clippy::too_many_arguments)] @@ -1352,13 +1357,21 @@ fn convert_to_table2_entry( ) -> NuText { let is_limit_reached = matches!(deep, Some(0)); if is_limit_reached { - return wrap_nu_text(value_to_styled_string(item, config, style_computer), width); + return wrap_nu_text( + value_to_styled_string(item, config, style_computer), + width, + config, + ); } match &item { Value::Record { span, cols, vals } => { if cols.is_empty() && vals.is_empty() { - wrap_nu_text(value_to_styled_string(item, config, style_computer), width) + wrap_nu_text( + value_to_styled_string(item, config, style_computer), + width, + config, + ) } else { let table = convert_to_table2( 0, @@ -1392,7 +1405,11 @@ fn convert_to_table2_entry( (table, TextStyle::default()) } else { // error so back down to the default - wrap_nu_text(value_to_styled_string(item, config, style_computer), width) + wrap_nu_text( + value_to_styled_string(item, config, style_computer), + width, + config, + ) } } } @@ -1405,6 +1422,7 @@ fn convert_to_table2_entry( wrap_nu_text( convert_value_list_to_string(vals, config, style_computer, flatten_sep), width, + config, ) } else { let table = convert_to_table2( @@ -1440,13 +1458,17 @@ fn convert_to_table2_entry( } else { // error so back down to the default - wrap_nu_text(value_to_styled_string(item, config, style_computer), width) + wrap_nu_text( + value_to_styled_string(item, config, style_computer), + width, + config, + ) } } } _ => { let text = value_to_styled_string(item, config, style_computer); - wrap_nu_text(text, width) + wrap_nu_text(text, width, config) } // unknown type. } } @@ -1540,6 +1562,15 @@ fn convert_with_precision(val: &str, precision: usize) -> Result bool { + matches!( + config.trim_strategy, + TrimStrategy::Wrap { + try_to_keep_words: true + } + ) +} + struct PagingTableCreator { head: Span, stream: ListStream, diff --git a/crates/nu-explore/src/nu_common/table.rs b/crates/nu-explore/src/nu_common/table.rs index 8ca77f6c2f..299a6b7c89 100644 --- a/crates/nu-explore/src/nu_common/table.rs +++ b/crates/nu-explore/src/nu_common/table.rs @@ -1,7 +1,7 @@ use nu_color_config::{Alignment, StyleComputer, TextStyle}; use nu_engine::column::get_columns; -use nu_protocol::FooterMode; use nu_protocol::{ast::PathMember, Config, ShellError, Span, TableIndexMode, Value}; +use nu_protocol::{FooterMode, TrimStrategy}; use nu_table::{string_width, Table as NuTable, TableConfig, TableTheme}; use std::sync::Arc; use std::{ @@ -225,13 +225,13 @@ fn build_expanded_table( style_computer, ); - nu_table::wrap_string(&failed_value.0, remaining_width) + wrap_nu_text(failed_value, remaining_width, config).0 } } } val => { let text = value_to_styled_string(&val, config, style_computer).0; - nu_table::wrap_string(&text, remaining_width) + wrap_nu_text((text, TextStyle::default()), remaining_width, config).0 } } }; @@ -489,7 +489,7 @@ fn convert_to_table2<'a>( } let value = create_table2_entry_basic(item, &header, head, config, style_computer); - let value = wrap_nu_text(value, available_width); + let value = wrap_nu_text(value, available_width, config); let value_width = string_width(&value.0); column_width = max(column_width, value_width); @@ -516,7 +516,7 @@ fn convert_to_table2<'a>( } let value = create_table2_entry_basic(item, &header, head, config, style_computer); - let value = wrap_nu_text(value, OK_CELL_CONTENT_WIDTH); + let value = wrap_nu_text(value, OK_CELL_CONTENT_WIDTH, config); let value = NuTable::create_cell(value.0, value.1); @@ -646,7 +646,7 @@ fn create_table2_entry( flatten_sep, width, ), - Err(_) => wrap_nu_text(error_sign(style_computer), width), + Err(_) => wrap_nu_text(error_sign(style_computer), width, config), } } _ => convert_to_table2_entry( @@ -666,8 +666,8 @@ fn error_sign(style_computer: &StyleComputer) -> (String, TextStyle) { make_styled_string(style_computer, String::from("❎"), None, 0) } -fn wrap_nu_text(mut text: NuText, width: usize) -> NuText { - text.0 = nu_table::wrap_string(&text.0, width); +fn wrap_nu_text(mut text: NuText, width: usize, config: &Config) -> NuText { + text.0 = nu_table::string_wrap(&text.0, width, is_cfg_trim_keep_words(config)); text } @@ -686,13 +686,21 @@ fn convert_to_table2_entry( ) -> NuText { let is_limit_reached = matches!(deep, Some(0)); if is_limit_reached { - return wrap_nu_text(value_to_styled_string(item, config, style_computer), width); + return wrap_nu_text( + value_to_styled_string(item, config, style_computer), + width, + config, + ); } match &item { Value::Record { span, cols, vals } => { if cols.is_empty() && vals.is_empty() { - wrap_nu_text(value_to_styled_string(item, config, style_computer), width) + wrap_nu_text( + value_to_styled_string(item, config, style_computer), + width, + config, + ) } else { let table = convert_to_table2( 0, @@ -726,7 +734,11 @@ fn convert_to_table2_entry( (table, TextStyle::default()) } else { // error so back down to the default - wrap_nu_text(value_to_styled_string(item, config, style_computer), width) + wrap_nu_text( + value_to_styled_string(item, config, style_computer), + width, + config, + ) } } } @@ -739,6 +751,7 @@ fn convert_to_table2_entry( wrap_nu_text( convert_value_list_to_string(vals, config, style_computer, flatten_sep), width, + config, ) } else { let table = convert_to_table2( @@ -774,11 +787,19 @@ fn convert_to_table2_entry( } else { // error so back down to the default - wrap_nu_text(value_to_styled_string(item, config, style_computer), width) + wrap_nu_text( + value_to_styled_string(item, config, style_computer), + width, + config, + ) } } } - _ => wrap_nu_text(value_to_styled_string(item, config, style_computer), width), // unknown type. + _ => wrap_nu_text( + value_to_styled_string(item, config, style_computer), + width, + config, + ), // unknown type. } } @@ -921,3 +942,12 @@ fn need_footer(config: &Config, count_records: u64) -> bool { matches!(config.footer_mode, FooterMode::RowCount(limit) if count_records > limit) || matches!(config.footer_mode, FooterMode::Always) } + +fn is_cfg_trim_keep_words(config: &Config) -> bool { + matches!( + config.trim_strategy, + TrimStrategy::Wrap { + try_to_keep_words: true + } + ) +} diff --git a/crates/nu-table/src/util.rs b/crates/nu-table/src/util.rs index 2439e52c55..258e479d45 100644 --- a/crates/nu-table/src/util.rs +++ b/crates/nu-table/src/util.rs @@ -4,7 +4,7 @@ pub fn string_width(text: &str) -> usize { tabled::papergrid::util::string_width_multiline_tab(text, 4) } -pub fn wrap_string(text: &str, width: usize) -> String { +pub fn string_wrap(text: &str, width: usize, keep_words: bool) -> String { // todo: change me... // // well... it's not effitient to build a table to wrap a string, @@ -14,13 +14,17 @@ pub fn wrap_string(text: &str, width: usize) -> String { return String::new(); } + let wrap = if keep_words { + Width::wrap(width).keep_words() + } else { + Width::wrap(width) + }; + Builder::from_iter([[text]]) .build() .with(Style::empty()) .with(Padding::zero()) - .with(Modify::new(Cell(0, 0)).with(Width::wrap(width))) - .to_string() - .trim_end() + .with(Modify::new(Cell(0, 0)).with(wrap)) .to_string() } @@ -39,18 +43,3 @@ pub fn string_truncate(text: &str, width: usize) -> String { .with(Width::truncate(width)) .to_string() } - -pub fn string_wrap(text: &str, width: usize) -> String { - // todo: change me... - - if text.is_empty() { - return String::new(); - } - - Builder::from_iter([[text]]) - .build() - .with(Style::empty()) - .with(Padding::zero()) - .with(Width::wrap(width)) - .to_string() -}