nu-table: Fix expand table unnessary color in trail head config when wrap is used (#10367)

So it must address it,
But please check.

PS: I don't like the patch... but it is what it is

fix: #10359
cc: @amtoine
This commit is contained in:
Maxim Zhiburt 2023-09-15 16:44:53 +00:00 committed by GitHub
parent 5ee74b6ab5
commit 2b77544e58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 101 additions and 100 deletions

View File

@ -2,7 +2,9 @@ use nu_color_config::{Alignment, StyleComputer, TextStyle};
use nu_protocol::TrimStrategy; use nu_protocol::TrimStrategy;
use nu_protocol::{Config, FooterMode, ShellError, Span, Value}; use nu_protocol::{Config, FooterMode, ShellError, Span, Value};
use crate::{clean_charset, string_wrap, NuTableConfig, TableOutput, TableTheme}; use crate::{
clean_charset, colorize_space_str, string_wrap, NuTableConfig, TableOutput, TableTheme,
};
pub type NuText = (String, TextStyle); pub type NuText = (String, TextStyle);
pub type TableResult = Result<Option<TableOutput>, ShellError>; pub type TableResult = Result<Option<TableOutput>, ShellError>;
@ -34,9 +36,11 @@ pub fn nu_value_to_string(val: &Value, cfg: &Config, style: &StyleComputer) -> N
make_styled_string(style, text, Some(val), float_precision) make_styled_string(style, text, Some(val), float_precision)
} }
pub fn nu_value_to_string_clean(val: &Value, cfg: &Config, style: &StyleComputer) -> NuText { pub fn nu_value_to_string_clean(val: &Value, cfg: &Config, style_comp: &StyleComputer) -> NuText {
let (text, style) = nu_value_to_string(val, cfg, style); let (text, style) = nu_value_to_string(val, cfg, style_comp);
let text = clean_charset(&text); let mut text = clean_charset(&text);
colorize_space_str(&mut text, style_comp);
(text, style) (text, style)
} }

View File

@ -1,4 +1,4 @@
use crate::table_theme::TableTheme; use crate::{convert_style, table_theme::TableTheme};
use nu_ansi_term::Style; use nu_ansi_term::Style;
use nu_color_config::TextStyle; use nu_color_config::TextStyle;
use nu_protocol::TrimStrategy; use nu_protocol::TrimStrategy;
@ -41,8 +41,6 @@ struct Styles {
index: AnsiColor<'static>, index: AnsiColor<'static>,
header: AnsiColor<'static>, header: AnsiColor<'static>,
data: EntityMap<AnsiColor<'static>>, data: EntityMap<AnsiColor<'static>>,
space_lead: Option<AnsiColor<'static>>,
space_trail: Option<AnsiColor<'static>>,
data_is_set: bool, data_is_set: bool,
} }
@ -140,17 +138,14 @@ impl NuTable {
self.alignments.data = convert_alignment(style.alignment); self.alignments.data = convert_alignment(style.alignment);
} }
pub fn set_trail_lead_style(&mut self, head: Style, tail: Style) {
let style_head = AnsiColor::from(convert_style(head));
let style_tail = AnsiColor::from(convert_style(tail));
self.styles.space_trail = Some(style_tail);
self.styles.space_lead = Some(style_head);
}
pub fn set_indent(&mut self, left: usize, right: usize) { pub fn set_indent(&mut self, left: usize, right: usize) {
self.indent = (left, right); self.indent = (left, right);
} }
pub fn get_records_mut(&mut self) -> &mut NuRecords {
&mut self.data
}
/// Converts a table to a String. /// Converts a table to a String.
/// ///
/// It returns None in case where table cannot be fit to a terminal width. /// It returns None in case where table cannot be fit to a terminal width.
@ -235,7 +230,7 @@ fn build_table(
} }
fn draw_table( fn draw_table(
mut data: NuRecords, data: NuRecords,
alignments: Alignments, alignments: Alignments,
styles: Styles, styles: Styles,
widths: Vec<usize>, widths: Vec<usize>,
@ -249,12 +244,6 @@ fn draw_table(
let sep_color = cfg.split_color; let sep_color = cfg.split_color;
let border_header = cfg.header_on_border; let border_header = cfg.header_on_border;
colorize_lead_trail_space(
&mut data,
styles.space_lead.clone(),
styles.space_trail.clone(),
);
let data: Vec<Vec<_>> = data.into(); let data: Vec<Vec<_>> = data.into();
let mut table = Builder::from(data).build(); let mut table = Builder::from(data).build();
@ -727,10 +716,6 @@ impl<R, D> TableOption<R, D, ColoredConfig> for SetAlignment {
} }
} }
fn convert_style(style: Style) -> Color {
Color::new(style.prefix().to_string(), style.suffix().to_string())
}
struct SetDimensions(Vec<usize>); struct SetDimensions(Vec<usize>);
impl<R> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for SetDimensions { impl<R> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for SetDimensions {
@ -928,51 +913,6 @@ fn remove_row(recs: &mut NuRecords, row: usize) -> Vec<String> {
columns columns
} }
fn colorize_lead_trail_space(
data: &mut NuRecords,
lead: Option<AnsiColor<'_>>,
trail: Option<AnsiColor<'_>>,
) {
use fancy_regex::Captures;
use fancy_regex::Regex;
use once_cell::sync::Lazy;
static RE_LEADING: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(?m)(?P<beginsp>^\s+)").expect("error with leading space regex"));
static RE_TRAILING: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(?m)(?P<endsp>\s+$)").expect("error with trailing space regex"));
if lead.is_none() && trail.is_none() {
return;
}
for row in data.iter_mut() {
for cell in row {
let mut buf = cell.as_ref().to_owned();
if let Some(color) = &lead {
buf = RE_LEADING
.replace_all(cell.as_ref(), |cap: &Captures| {
let spaces = cap.get(1).expect("valid").as_str();
format!("{}{}{}", color.get_prefix(), spaces, color.get_suffix())
})
.into_owned();
}
if let Some(color) = &trail {
buf = RE_TRAILING
.replace_all(buf.as_ref(), |cap: &Captures| {
let spaces = cap.get(1).expect("valid").as_str();
format!("{}{}{}", color.get_prefix(), spaces, color.get_suffix())
})
.into_owned();
}
*cell = CellInfo::new(buf);
}
}
}
struct StripColorFromRow(usize); struct StripColorFromRow(usize);
impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for StripColorFromRow { impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for StripColorFromRow {

View File

@ -9,8 +9,8 @@ use tabled::grid::config::Position;
use crate::{ use crate::{
common::{ common::{
create_nu_table_config, error_sign, get_header_style, get_index_style, create_nu_table_config, error_sign, get_header_style, get_index_style,
get_leading_trailing_space_style, load_theme_from_config, nu_value_to_string, load_theme_from_config, nu_value_to_string, nu_value_to_string_clean, wrap_text, NuText,
nu_value_to_string_clean, wrap_text, NuText, StringResult, TableResult, INDEX_COLUMN_NAME, StringResult, TableResult, INDEX_COLUMN_NAME,
}, },
string_width, NuTable, NuTableCell, TableOpts, TableOutput, string_width, NuTable, NuTableCell, TableOpts, TableOutput,
}; };
@ -178,10 +178,6 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
table.set_index_style(get_index_style(cfg.opts.style_computer)); table.set_index_style(get_index_style(cfg.opts.style_computer));
set_data_styles(&mut table, data_styles); set_data_styles(&mut table, data_styles);
if let Some(style) = get_leading_trailing_space_style(cfg.opts.style_computer).color_style {
table.set_trail_lead_style(style, style);
}
return Ok(Some(TableOutput::new(table, false, with_index))); return Ok(Some(TableOutput::new(table, false, with_index)));
} }
@ -341,10 +337,6 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
table.set_indent(cfg.opts.indent.0, cfg.opts.indent.1); table.set_indent(cfg.opts.indent.0, cfg.opts.indent.1);
set_data_styles(&mut table, data_styles); set_data_styles(&mut table, data_styles);
if let Some(style) = get_leading_trailing_space_style(cfg.opts.style_computer).color_style {
table.set_trail_lead_style(style, style);
}
Ok(Some(TableOutput::new(table, true, with_index))) Ok(Some(TableOutput::new(table, true, with_index)))
} }
@ -395,10 +387,6 @@ fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> StringResult {
table.set_index_style(get_key_style(&cfg)); table.set_index_style(get_key_style(&cfg));
table.set_indent(cfg.opts.indent.0, cfg.opts.indent.1); table.set_indent(cfg.opts.indent.0, cfg.opts.indent.1);
if let Some(style) = get_leading_trailing_space_style(cfg.opts.style_computer).color_style {
table.set_trail_lead_style(style, style);
}
let out = TableOutput::new(table, false, true); let out = TableOutput::new(table, false, true);
maybe_expand_table(out, cfg.opts.width, &cfg.opts) maybe_expand_table(out, cfg.opts.width, &cfg.opts)

View File

@ -3,10 +3,10 @@ use nu_engine::column::get_columns;
use nu_protocol::{ast::PathMember, Config, Record, ShellError, Span, TableIndexMode, Value}; use nu_protocol::{ast::PathMember, Config, Record, ShellError, Span, TableIndexMode, Value};
use crate::{ use crate::{
clean_charset, clean_charset, colorize_space,
common::{ common::{
create_nu_table_config, get_empty_style, get_header_style, get_index_style, create_nu_table_config, get_empty_style, get_header_style, get_index_style,
get_leading_trailing_space_style, get_value_style, NuText, INDEX_COLUMN_NAME, get_value_style, NuText, INDEX_COLUMN_NAME,
}, },
NuTable, NuTableCell, StringResult, TableOpts, TableOutput, TableResult, NuTable, NuTableCell, StringResult, TableOpts, TableOutput, TableResult,
}; };
@ -30,6 +30,8 @@ fn create_table(input: &[Value], opts: TableOpts<'_>) -> Result<Option<String>,
let right = opts.config.table_indent.right; let right = opts.config.table_indent.right;
out.table.set_indent(left, right); out.table.set_indent(left, right);
colorize_space(out.table.get_records_mut(), opts.style_computer);
let table_config = let table_config =
create_nu_table_config(opts.config, opts.style_computer, &out, false); create_nu_table_config(opts.config, opts.style_computer, &out, false);
Ok(out.table.draw(table_config, opts.width)) Ok(out.table.draw(table_config, opts.width))
@ -57,13 +59,11 @@ fn kv_table(record: &Record, opts: TableOpts<'_>) -> StringResult {
row.push(value); row.push(value);
} }
colorize_space(&mut data, opts.style_computer);
let mut table = NuTable::from(data); let mut table = NuTable::from(data);
table.set_index_style(TextStyle::default_field()); table.set_index_style(TextStyle::default_field());
if let Some(style) = get_leading_trailing_space_style(opts.style_computer).color_style {
table.set_trail_lead_style(style, style);
}
let mut out = TableOutput::new(table, false, true); let mut out = TableOutput::new(table, false, true);
let left = opts.config.table_indent.left; let left = opts.config.table_indent.left;
@ -125,10 +125,6 @@ fn to_table_with_header(
table.set_header_style(get_header_style(opts.style_computer)); table.set_header_style(get_header_style(opts.style_computer));
table.set_index_style(get_index_style(opts.style_computer)); table.set_index_style(get_index_style(opts.style_computer));
if let Some(style) = get_leading_trailing_space_style(opts.style_computer).color_style {
table.set_trail_lead_style(style, style);
}
for (i, text) in headers.iter().enumerate() { for (i, text) in headers.iter().enumerate() {
table.insert((0, i), text.to_owned()); table.insert((0, i), text.to_owned());
} }
@ -168,10 +164,6 @@ fn to_table_with_no_header(
let mut table = NuTable::new(input.len(), with_index as usize + 1); let mut table = NuTable::new(input.len(), with_index as usize + 1);
table.set_index_style(get_index_style(opts.style_computer)); table.set_index_style(get_index_style(opts.style_computer));
if let Some(style) = get_leading_trailing_space_style(opts.style_computer).color_style {
table.set_trail_lead_style(style, style);
}
for (row, item) in input.iter().enumerate() { for (row, item) in input.iter().enumerate() {
if nu_utils::ctrl_c::was_pressed(&opts.ctrlc) { if nu_utils::ctrl_c::was_pressed(&opts.ctrlc) {
return Ok(None); return Ok(None);

View File

@ -1,9 +1,14 @@
use nu_color_config::StyleComputer;
use tabled::{ use tabled::{
builder::Builder, builder::Builder,
grid::util::string::string_width_multiline, grid::{
settings::{width::Truncate, Modify, Padding, Style, Width}, color::AnsiColor, records::vec_records::CellInfo, util::string::string_width_multiline,
},
settings::{width::Truncate, Color, Modify, Padding, Style, Width},
}; };
use crate::common::get_leading_trailing_space_style;
pub fn string_width(text: &str) -> usize { pub fn string_width(text: &str) -> usize {
string_width_multiline(text) string_width_multiline(text)
} }
@ -47,3 +52,75 @@ pub fn clean_charset(text: &str) -> String {
// todo: optimize, I bet it can be done in 1 path // todo: optimize, I bet it can be done in 1 path
text.replace('\t', " ").replace('\r', "") text.replace('\t', " ").replace('\r', "")
} }
pub fn colorize_space(data: &mut [Vec<CellInfo<String>>], style_computer: &StyleComputer<'_>) {
if let Some(style) = get_leading_trailing_space_style(style_computer).color_style {
let style = convert_style(style).into();
colorize_lead_trail_space(data, Some(&style), Some(&style));
}
}
pub fn colorize_space_str(text: &mut String, style_computer: &StyleComputer<'_>) {
if let Some(style) = get_leading_trailing_space_style(style_computer).color_style {
let style = convert_style(style).into();
*text = colorize_space_one(text, Some(&style), Some(&style));
}
}
fn colorize_lead_trail_space(
data: &mut [Vec<CellInfo<String>>],
lead: Option<&AnsiColor<'_>>,
trail: Option<&AnsiColor<'_>>,
) {
if lead.is_none() && trail.is_none() {
return;
}
for row in data.iter_mut() {
for cell in row {
let buf = colorize_space_one(cell.as_ref(), lead, trail);
*cell = CellInfo::new(buf);
}
}
}
fn colorize_space_one(
text: &str,
lead: Option<&AnsiColor<'_>>,
trail: Option<&AnsiColor<'_>>,
) -> String {
use fancy_regex::Captures;
use fancy_regex::Regex;
use once_cell::sync::Lazy;
static RE_LEADING: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(?m)(?P<beginsp>^\s+)").expect("error with leading space regex"));
static RE_TRAILING: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(?m)(?P<endsp>\s+$)").expect("error with trailing space regex"));
let mut buf = text.to_owned();
if let Some(color) = &lead {
buf = RE_LEADING
.replace_all(&buf, |cap: &Captures| {
let spaces = cap.get(1).expect("valid").as_str();
format!("{}{}{}", color.get_prefix(), spaces, color.get_suffix())
})
.into_owned();
}
if let Some(color) = &trail {
buf = RE_TRAILING
.replace_all(&buf, |cap: &Captures| {
let spaces = cap.get(1).expect("valid").as_str();
format!("{}{}{}", color.get_prefix(), spaces, color.get_suffix())
})
.into_owned();
}
buf
}
pub fn convert_style(style: nu_ansi_term::Style) -> Color {
Color::new(style.prefix().to_string(), style.suffix().to_string())
}