Patch restore lead trail space bg color (#10351)

```nu
 $env.config.color_config.leading_trailing_space_bg = { bg: 'white' }; [[a b, 'c   ']; ['  1  ' '    2' '3    '] ['  4  ' "hello   \n  world  " ['  1  ' 2 [1 '  2  ' 3]]]] | table --expand
```


![image](https://github.com/nushell/nushell/assets/20165848/01a35042-0e36-4c51-99a9-3011fabb551b)

ref: #2794
close: #10317

note: test are not actually make scenes cause `nu!` strips colors.
(Ideally it would need a flag to not do so)
note: It does does does ... slower down quite a bit rendering... (

PS: Maybe it's better being a flag to `table` rather then a
configuration option?
PS: I am not sure why the logic was removed in a first place
This commit is contained in:
Maxim Zhiburt 2023-09-13 12:47:53 +00:00 committed by GitHub
parent bbea7da669
commit 73d3708006
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 124 additions and 4 deletions

2
Cargo.lock generated
View file

@ -3078,11 +3078,13 @@ dependencies = [
name = "nu-table"
version = "0.84.1"
dependencies = [
"fancy-regex",
"nu-ansi-term",
"nu-color-config",
"nu-engine",
"nu-protocol",
"nu-utils",
"once_cell",
"tabled",
]

View file

@ -2664,3 +2664,25 @@ fn table_collapse_padding_zero() {
"
);
}
#[test]
fn table_leading_trailing_space_bg() {
let actual = nu!(
r#"$env.config.color_config.leading_trailing_space_bg = { bg: 'white' }; [[a b, 'c ']; [' 1 ' ' 2' '3 '] [' 4 ' "hello\nworld" [' 1 ' 2 [1 ' 2 ' 3]]]] | table"#
);
assert_eq!(
actual.out,
"╭───┬───────┬───────┬────────────────╮│ # │ a │ b │ c │├───┼───────┼───────┼────────────────┤│ 0 │ 1 │ 2 │ 3 ││ 1 │ 4 │ hello │ [list 3 items] ││ │ │ world │ │╰───┴───────┴───────┴────────────────╯"
);
}
#[test]
fn table_leading_trailing_space_bg_expand() {
let actual = nu!(
r#"$env.config.color_config.leading_trailing_space_bg = { bg: 'white' }; [[a b, 'c ']; [' 1 ' ' 2' '3 '] [' 4 ' "hello\nworld" [' 1 ' 2 [1 ' 2 ' 3]]]] | table --expand"#
);
assert_eq!(
actual.out,
"╭───┬───────┬───────┬───────────────────────╮│ # │ a │ b │ c │├───┼───────┼───────┼───────────────────────┤│ 0 │ 1 │ 2 │ 3 ││ 1 │ 4 │ hello │ ╭───┬───────────────╮ ││ │ │ world │ │ 0 │ 1 │ ││ │ │ │ │ 1 │ 2 │ ││ │ │ │ │ 2 │ ╭───┬───────╮ │ ││ │ │ │ │ │ │ 0 │ 1 │ │ ││ │ │ │ │ │ │ 1 │ 2 │ │ ││ │ │ │ │ │ │ 2 │ 3 │ │ ││ │ │ │ │ │ ╰───┴───────╯ │ ││ │ │ │ ╰───┴───────────────╯ │╰───┴───────┴───────┴───────────────────────╯"
);
}

View file

@ -16,6 +16,8 @@ nu-utils = { path = "../nu-utils", version = "0.84.1" }
nu-engine = { path = "../nu-engine", version = "0.84.1" }
nu-color-config = { path = "../nu-color-config", version = "0.84.1" }
nu-ansi-term = "0.49.0"
once_cell = "1.18"
fancy-regex = "0.11"
tabled = { version = "0.14.0", features = ["color"], default-features = false }
[dev-dependencies]

View file

@ -62,6 +62,16 @@ pub fn get_index_style(style_computer: &StyleComputer) -> TextStyle {
)
}
pub fn get_leading_trailing_space_style(style_computer: &StyleComputer) -> TextStyle {
TextStyle::with_style(
Alignment::Right,
style_computer.compute(
"leading_trailing_space_bg",
&Value::string("", Span::unknown()),
),
)
}
pub fn get_value_style(value: &Value, config: &Config, style_computer: &StyleComputer) -> NuText {
match value {
// Float precision is required here.

View file

@ -40,6 +40,8 @@ struct Styles {
index: AnsiColor<'static>,
header: AnsiColor<'static>,
data: EntityMap<AnsiColor<'static>>,
space_lead: Option<AnsiColor<'static>>,
space_trail: Option<AnsiColor<'static>>,
data_is_set: bool,
}
@ -137,6 +139,13 @@ impl NuTable {
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) {
self.indent = (left, right);
}
@ -225,7 +234,7 @@ fn build_table(
}
fn draw_table(
data: NuRecords,
mut data: NuRecords,
alignments: Alignments,
styles: Styles,
widths: Vec<usize>,
@ -239,6 +248,12 @@ fn draw_table(
let sep_color = cfg.split_color;
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 mut table = Builder::from(data).build();
@ -908,3 +923,48 @@ fn remove_row(recs: &mut NuRecords, row: usize) -> Vec<String> {
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);
}
}
}

View file

@ -9,8 +9,8 @@ use tabled::grid::config::Position;
use crate::{
common::{
create_nu_table_config, error_sign, get_header_style, get_index_style,
load_theme_from_config, nu_value_to_string, nu_value_to_string_clean, wrap_text, NuText,
StringResult, TableResult, INDEX_COLUMN_NAME,
get_leading_trailing_space_style, load_theme_from_config, nu_value_to_string,
nu_value_to_string_clean, wrap_text, NuText, StringResult, TableResult, INDEX_COLUMN_NAME,
},
string_width, NuTable, NuTableCell, TableOpts, TableOutput,
};
@ -178,6 +178,10 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
table.set_index_style(get_index_style(cfg.opts.style_computer));
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)));
}
@ -337,6 +341,10 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
table.set_indent(cfg.opts.indent.0, cfg.opts.indent.1);
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)))
}
@ -387,6 +395,10 @@ fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> StringResult {
table.set_index_style(get_key_style(&cfg));
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);
maybe_expand_table(out, cfg.opts.width, &cfg.opts)

View file

@ -6,7 +6,7 @@ use crate::{
clean_charset,
common::{
create_nu_table_config, get_empty_style, get_header_style, get_index_style,
get_value_style, NuText, INDEX_COLUMN_NAME,
get_leading_trailing_space_style, get_value_style, NuText, INDEX_COLUMN_NAME,
},
NuTable, NuTableCell, StringResult, TableOpts, TableOutput, TableResult,
};
@ -60,6 +60,10 @@ fn kv_table(record: &Record, opts: TableOpts<'_>) -> StringResult {
let mut table = NuTable::from(data);
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 left = opts.config.table_indent.left;
@ -121,6 +125,10 @@ fn to_table_with_header(
table.set_header_style(get_header_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() {
table.insert((0, i), text.to_owned());
}
@ -160,6 +168,10 @@ fn to_table_with_no_header(
let mut table = NuTable::new(input.len(), with_index as usize + 1);
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() {
if nu_utils::ctrl_c::was_pressed(&opts.ctrlc) {
return Ok(None);