Merge 99fb49fc2c7716c709d42c55252c9f5d3865400b into a340511e95ad7e0efd3eb30792fccf947b9dd42f

This commit is contained in:
Maxim Zhiburt 2025-05-07 14:10:21 +03:00 committed by GitHub
commit 115507ffe2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 178 additions and 161 deletions

65
Cargo.lock generated
View File

@ -30,6 +30,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"const-random",
"getrandom 0.2.15", "getrandom 0.2.15",
"once_cell", "once_cell",
"version_check", "version_check",
@ -102,7 +103,16 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cf4578926a981ab0ca955dc023541d19de37112bc24c1a197bd806d3d86ad1d" checksum = "1cf4578926a981ab0ca955dc023541d19de37112bc24c1a197bd806d3d86ad1d"
dependencies = [ dependencies = [
"ansitok", "ansitok 0.2.0",
]
[[package]]
name = "ansi-str"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "060de1453b69f46304b28274f382132f4e72c55637cf362920926a70d090890d"
dependencies = [
"ansitok 0.3.0",
] ]
[[package]] [[package]]
@ -115,6 +125,16 @@ dependencies = [
"vte 0.10.1", "vte 0.10.1",
] ]
[[package]]
name = "ansitok"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0a8acea8c2f1c60f0a92a8cd26bf96ca97db56f10bbcab238bbe0cceba659ee"
dependencies = [
"nom 7.1.3",
"vte 0.14.1",
]
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.18" version = "0.6.18"
@ -3774,7 +3794,7 @@ dependencies = [
name = "nu-explore" name = "nu-explore"
version = "0.104.1" version = "0.104.1"
dependencies = [ dependencies = [
"ansi-str", "ansi-str 0.8.0",
"anyhow", "anyhow",
"crossterm", "crossterm",
"log", "log",
@ -4592,14 +4612,13 @@ checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56"
[[package]] [[package]]
name = "papergrid" name = "papergrid"
version = "0.13.0" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/zhiburt/tabled?rev=fd48cef72a3e87beada497689509f9ab7b5823dd#fd48cef72a3e87beada497689509f9ab7b5823dd"
checksum = "d2b0f8def1f117e13c895f3eda65a7b5650688da29d6ad04635f61bc7b92eebd"
dependencies = [ dependencies = [
"ansi-str", "ahash",
"ansitok", "ansi-str 0.9.0",
"ansitok 0.3.0",
"bytecount", "bytecount",
"fnv",
"unicode-width 0.2.0", "unicode-width 0.2.0",
] ]
@ -7034,13 +7053,13 @@ dependencies = [
[[package]] [[package]]
name = "tabled" name = "tabled"
version = "0.17.0" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/zhiburt/tabled?rev=fd48cef72a3e87beada497689509f9ab7b5823dd#fd48cef72a3e87beada497689509f9ab7b5823dd"
checksum = "c6709222f3973137427ce50559cd564dc187a95b9cfe01613d2f4e93610e510a"
dependencies = [ dependencies = [
"ansi-str", "ansi-str 0.9.0",
"ansitok", "ansitok 0.3.0",
"papergrid", "papergrid",
"testing_table",
] ]
[[package]] [[package]]
@ -7114,6 +7133,16 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
[[package]]
name = "testing_table"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f8daae29995a24f65619e19d8d31dea5b389f3d853d8bf297bbf607cd0014cc"
dependencies = [
"ansitok 0.3.0",
"unicode-width 0.2.0",
]
[[package]] [[package]]
name = "textwrap" name = "textwrap"
version = "0.16.1" version = "0.16.1"
@ -7879,6 +7908,16 @@ dependencies = [
"vte_generate_state_changes", "vte_generate_state_changes",
] ]
[[package]]
name = "vte"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077"
dependencies = [
"arrayvec 0.7.6",
"memchr",
]
[[package]] [[package]]
name = "vte_generate_state_changes" name = "vte_generate_state_changes"
version = "0.1.2" version = "0.1.2"

View File

@ -159,7 +159,7 @@ strum = "0.26"
strum_macros = "0.26" strum_macros = "0.26"
syn = "2.0" syn = "2.0"
sysinfo = "0.33" sysinfo = "0.33"
tabled = { version = "0.17.0", default-features = false } tabled = { git = "https://github.com/zhiburt/tabled", rev = "fd48cef72a3e87beada497689509f9ab7b5823dd", default-features = false }
tempfile = "3.15" tempfile = "3.15"
titlecase = "3.5" titlecase = "3.5"
toml = "0.8" toml = "0.8"

View File

@ -1,13 +1,14 @@
// note: Seems like could be simplified // note: Seems like could be simplified
// IMHO: it shall not take 300+ lines :) // IMHO: it shall not take 300+ lines :)
// TODO: simplify
use self::{global_horizontal_char::SetHorizontalChar, set_widths::SetWidths}; use self::global_horizontal_char::SetHorizontalChar;
use nu_protocol::engine::EngineState; use nu_protocol::engine::EngineState;
use nu_protocol::Value; use nu_protocol::Value;
use nu_table::{string_width, string_wrap}; use nu_table::{string_width, string_wrap};
use tabled::{ use tabled::{
grid::config::ColoredConfig, grid::config::ColoredConfig,
settings::{peaker::Priority, width::Wrap, Settings, Style}, settings::{peaker::Priority, width::Wrap, Style},
Table, Table,
}; };
@ -60,13 +61,12 @@ pub fn build_table(
desc_table.with(Style::rounded().remove_bottom().remove_horizontals()); desc_table.with(Style::rounded().remove_bottom().remove_horizontals());
let mut val_table = Table::from_iter(data); let mut val_table = Table::from_iter(data);
val_table.with( val_table.with(Style::rounded().corner_top_left('├').corner_top_right('┤'));
Settings::default() val_table.get_dimension_mut().set_widths(widths);
.with(Style::rounded().corner_top_left('├').corner_top_right('┤')) val_table.with((
.with(SetWidths(widths)) Wrap::new(width).priority(Priority::max(true)),
.with(Wrap::new(width).priority(Priority::max(true))) SetHorizontalChar::new('┼', '┴', 11 + 2 + 1),
.with(SetHorizontalChar::new('┼', '┴', 11 + 2 + 1)), ));
);
format!("{desc_table}\n{val_table}") format!("{desc_table}\n{val_table}")
} }
@ -315,8 +315,8 @@ mod util {
mod global_horizontal_char { mod global_horizontal_char {
use tabled::{ use tabled::{
grid::{ grid::{
config::{ColoredConfig, Offset}, config::{ColoredConfig, Offset, Position},
dimension::{CompleteDimensionVecRecords, Dimension}, dimension::{CompleteDimension, Dimension},
records::{ExactRecords, Records}, records::{ExactRecords, Records},
}, },
settings::TableOption, settings::TableOption,
@ -338,14 +338,14 @@ mod global_horizontal_char {
} }
} }
impl<R: Records + ExactRecords> TableOption<R, ColoredConfig, CompleteDimensionVecRecords<'_>> impl<R: Records + ExactRecords> TableOption<R, ColoredConfig, CompleteDimension<'_>>
for SetHorizontalChar for SetHorizontalChar
{ {
fn change( fn change(
self, self,
records: &mut R, records: &mut R,
cfg: &mut ColoredConfig, cfg: &mut ColoredConfig,
dimension: &mut CompleteDimensionVecRecords<'_>, dimension: &mut CompleteDimension<'_>,
) { ) {
let count_columns = records.count_columns(); let count_columns = records.count_columns();
let count_rows = records.count_rows(); let count_rows = records.count_rows();
@ -358,17 +358,21 @@ mod global_horizontal_char {
let has_vertical = cfg.has_vertical(0, count_columns); let has_vertical = cfg.has_vertical(0, count_columns);
if has_vertical && self.index == 0 { if has_vertical && self.index == 0 {
let mut border = cfg.get_border((0, 0), (count_rows, count_columns)); let mut border = cfg.get_border(Position::new(0, 0), (count_rows, count_columns));
border.left_top_corner = Some(self.intersection); border.left_top_corner = Some(self.intersection);
cfg.set_border((0, 0), border); cfg.set_border(Position::new(0, 0), border);
return; return;
} }
let mut i = 1; let mut i = 1;
for (col, width) in widths.into_iter().enumerate() { for (col, width) in widths.into_iter().enumerate() {
if self.index < i + width { if self.index < i + width {
let o = self.index - i; let offset = self.index - i;
cfg.set_horizontal_char((0, col), self.split, Offset::Begin(o)); cfg.set_horizontal_char(
Position::new(0, col),
Offset::Start(offset),
self.split,
);
return; return;
} }
@ -377,9 +381,10 @@ mod global_horizontal_char {
let has_vertical = cfg.has_vertical(col, count_columns); let has_vertical = cfg.has_vertical(col, count_columns);
if has_vertical { if has_vertical {
if self.index == i { if self.index == i {
let mut border = cfg.get_border((0, col), (count_rows, count_columns)); let mut border =
cfg.get_border(Position::new(0, col), (count_rows, count_columns));
border.right_top_corner = Some(self.intersection); border.right_top_corner = Some(self.intersection);
cfg.set_border((0, col), border); cfg.set_border(Position::new(0, col), border);
return; return;
} }
@ -389,7 +394,7 @@ mod global_horizontal_char {
} }
} }
fn get_widths(dims: &CompleteDimensionVecRecords<'_>, count_columns: usize) -> Vec<usize> { fn get_widths(dims: &CompleteDimension<'_>, count_columns: usize) -> Vec<usize> {
let mut widths = vec![0; count_columns]; let mut widths = vec![0; count_columns];
for (col, width) in widths.iter_mut().enumerate() { for (col, width) in widths.iter_mut().enumerate() {
*width = dims.get_width(col); *width = dims.get_width(col);
@ -398,23 +403,3 @@ mod global_horizontal_char {
widths widths
} }
} }
mod set_widths {
use tabled::{
grid::{config::ColoredConfig, dimension::CompleteDimensionVecRecords},
settings::TableOption,
};
pub struct SetWidths(pub Vec<usize>);
impl<R> TableOption<R, ColoredConfig, CompleteDimensionVecRecords<'_>> for SetWidths {
fn change(
self,
_: &mut R,
_: &mut ColoredConfig,
dims: &mut CompleteDimensionVecRecords<'_>,
) {
dims.set_widths(self.0);
}
}
}

View File

@ -5,6 +5,7 @@
use std::{collections::VecDeque, io::Read, path::PathBuf, str::FromStr}; use std::{collections::VecDeque, io::Read, path::PathBuf, str::FromStr};
use lscolors::{LsColors, Style}; use lscolors::{LsColors, Style};
use tabled::grid::config::Position;
use url::Url; use url::Url;
use web_time::Instant; use web_time::Instant;
@ -1092,7 +1093,7 @@ fn create_empty_placeholder(
let cell = format!("empty {}", value_type_name); let cell = format!("empty {}", value_type_name);
let mut table = NuTable::new(1, 1); let mut table = NuTable::new(1, 1);
table.insert((0, 0), cell); table.insert(Position::new(0, 0), cell);
table.set_data_style(TextStyle::default().dimmed()); table.set_data_style(TextStyle::default().dimmed());
let mut out = TableOutput::from_table(table, false, false); let mut out = TableOutput::from_table(table, false, false);

View File

@ -665,13 +665,15 @@ fn test_expand_big_0() {
"open sample.toml | table --width=80 --expand" "open sample.toml | table --width=80 --expand"
)); ));
_print_lines(&actual.out, 80);
let expected = join_lines([ let expected = join_lines([
"╭──────────────────┬───────────────────────────────────────────────────────────╮", "╭──────────────────┬───────────────────────────────────────────────────────────╮",
"│ │ ╭───────────────┬───────────────────────────────────────╮ │", "│ │ ╭───────────────┬───────────────────────────────────────╮ │",
"│ package │ │ │ ╭───┬───────────────────────────────╮ │ │", "│ package │ │ │ ╭───┬────────────────────── │ │",
"│ │ │ authors │ │ 0 │ The Nushell Project │ │", "│ │ │ authors │ │ 0 │ The Nushell Project │ │",
"│ │ │ │ │ │ Developers │ │", "│ │ │ │ │ │ Developers │ │",
"│ │ │ │ ╰───┴───────────────────────────────╯ │ │", "│ │ │ │ ╰───┴────────────────────── │ │",
"│ │ │ default-run │ nu │ │", "│ │ │ default-run │ nu │ │",
"│ │ │ description │ A new type of shell │ │", "│ │ │ description │ A new type of shell │ │",
"│ │ │ documentation │ https://www.nushell.sh/book/ │ │", "│ │ │ documentation │ https://www.nushell.sh/book/ │ │",
@ -688,21 +690,21 @@ fn test_expand_big_0() {
"│ │ │ │ ╭──────────┬────────────────────────╮ │ │", "│ │ │ │ ╭──────────┬────────────────────────╮ │ │",
"│ │ │ metadata │ │ │ ╭───────────┬────────╮ │ │ │", "│ │ │ metadata │ │ │ ╭───────────┬────────╮ │ │ │",
"│ │ │ │ │ binstall │ │ pkg-url │ { repo │ │ │ │", "│ │ │ │ │ binstall │ │ pkg-url │ { repo │ │ │ │",
"│ │ │ │ │ │ │ │ }/rel │ │ │ │", "│ │ │ │ │ │ │ │ }/rele │ │ │ │",
"│ │ │ │ │ │ │ │ eases/ │ │ │ │", "│ │ │ │ │ │ │ │ ases/d │ │ │ │",
"│ │ │ │ │ │ │ │ downlo │ │ │ │", "│ │ │ │ │ │ │ │ ownloa │ │ │ │",
"│ │ │ │ │ │ │ │ ad/{ v │ │ │ │", "│ │ │ │ │ │ │ │ d/{ ve │ │ │ │",
"│ │ │ │ │ │ │ │ ersion │ │ │ │", "│ │ │ │ │ │ │ │ rsion │ │ │ │",
"│ │ │ │ │ │ │ │ }/{ │ │ │ │", "│ │ │ │ │ │ │ │ }/{ │ │ │ │",
"│ │ │ │ │ │ │ │ name │ │ │ │", "│ │ │ │ │ │ │ │ name │ │ │ │",
"│ │ │ │ │ │ │ │ }-{ ve │ │ │ │", "│ │ │ │ │ │ │ │ }-{ ve │ │ │ │",
"│ │ │ │ │ │ │ │ rsion │ │ │ │", "│ │ │ │ │ │ │ │ rsion │ │ │ │",
"│ │ │ │ │ │ │ │ }-{ │ │ │ │", "│ │ │ │ │ │ │ │ }-{ │ │ │ │",
"│ │ │ │ │ │ │ │ target │ │ │ │", "│ │ │ │ │ │ │ │ target │ │ │ │",
"│ │ │ │ │ │ │ │ }.{ a │ │ │ │", "│ │ │ │ │ │ │ │ }.{ ar │ │ │ │",
"│ │ │ │ │ │ │ │ rchive │ │ │ │", "│ │ │ │ │ │ │ │ chive- │ │ │ │",
"│ │ │ │ │ │ │ │ -forma │ │ │ │", "│ │ │ │ │ │ │ │ format │ │ │ │",
"│ │ │ │ │ │ │ │ t } │ │ │ │", "│ │ │ │ │ │ │ │ } │ │ │ │",
"│ │ │ │ │ │ │ pkg-fmt │ tgz │ │ │ │", "│ │ │ │ │ │ │ pkg-fmt │ tgz │ │ │ │",
"│ │ │ │ │ │ │ overrides │ {recor │ │ │ │", "│ │ │ │ │ │ │ overrides │ {recor │ │ │ │",
"│ │ │ │ │ │ │ │ d 1 │ │ │ │", "│ │ │ │ │ │ │ │ d 1 │ │ │ │",
@ -856,6 +858,8 @@ fn test_expand_big_0() {
"open sample.toml | table --expand --width=120" "open sample.toml | table --expand --width=120"
)); ));
_print_lines(&actual.out, 120);
let expected = join_lines([ let expected = join_lines([
"╭──────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────╮", "╭──────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│ │ ╭───────────────┬───────────────────────────────────────────────────────────────────────────────╮ │", "│ │ ╭───────────────┬───────────────────────────────────────────────────────────────────────────────╮ │",
@ -948,7 +952,7 @@ fn test_expand_big_0() {
"│ │ │ │ │ dependencies │ │ │ ╭──────────┬─────────╮ │ │ │ │", "│ │ │ │ │ dependencies │ │ │ ╭──────────┬─────────╮ │ │ │ │",
"│ │ │ │ │ │ │ openssl │ │ version │ 0.10.38 │ │ │ │ │", "│ │ │ │ │ │ │ openssl │ │ version │ 0.10.38 │ │ │ │ │",
"│ │ │ │ │ │ │ │ │ features │ [list 1 │ │ │ │ │", "│ │ │ │ │ │ │ │ │ features │ [list 1 │ │ │ │ │",
"│ │ │ │ │ │ │ │ │ │ item] │ │ │ │ │", "│ │ │ │ │ │ │ │ │ │ item] │ │ │ │ │",
"│ │ │ │ │ │ │ │ │ optional │ true │ │ │ │ │", "│ │ │ │ │ │ │ │ │ optional │ true │ │ │ │ │",
"│ │ │ │ │ │ │ │ ╰──────────┴─────────╯ │ │ │ │", "│ │ │ │ │ │ │ │ ╰──────────┴─────────╯ │ │ │ │",
"│ │ │ │ │ │ │ signal-hook │ {record 2 fields} │ │ │ │", "│ │ │ │ │ │ │ signal-hook │ {record 2 fields} │ │ │ │",
@ -1185,19 +1189,19 @@ fn test_expand_big_0() {
"│ │ │ time │ 0.3.12 │ │", "│ │ │ time │ 0.3.12 │ │",
"│ │ ╰───────────────┴───────────────────╯ │", "│ │ ╰───────────────┴───────────────────╯ │",
"│ target │ {record 3 fields} │", "│ target │ {record 3 fields} │",
"│ │ ╭──────────────────────────────────╮ │", "│ │ ╭──────────────────────────────────╮ │",
"│ dev-dependencies │ │ nu-test-support │ {record 2 │ │", "│ dev-dependencies │ │ nu-test-support │ {record 2 │ │",
"│ │ │ │ fields} │ │", "│ │ │ │ fields} │ │",
"│ │ │ tempfile │ 3.2.0 │ │", "│ │ │ tempfile │ 3.2.0 │ │",
"│ │ │ assert_cmd │ 2.0.2 │ │", "│ │ │ assert_cmd │ 2.0.2 │ │",
"│ │ │ criterion │ 0.4 │ │", "│ │ │ criterion │ 0.4 │ │",
"│ │ │ pretty_assertions │ 1.0.0 │ │", "│ │ │ pretty_assertions │ 1.0.0 │ │",
"│ │ │ serial_test │ 0.10.0 │ │", "│ │ │ serial_test │ 0.10.0 │ │",
"│ │ │ hamcrest2 │ 0.3.0 │ │", "│ │ │ hamcrest2 │ 0.3.0 │ │",
"│ │ │ rstest │ {record 2 │ │", "│ │ │ rstest │ {record 2 │ │",
"│ │ │ │ fields} │ │", "│ │ │ │ fields} │ │",
"│ │ │ itertools │ 0.10.3 │ │", "│ │ │ itertools │ 0.10.3 │ │",
"│ │ ╰──────────────────────────────────╯ │", "│ │ ╰──────────────────────────────────╯ │",
"│ │ ╭─────────────────────┬─────────────╮ │", "│ │ ╭─────────────────────┬─────────────╮ │",
"│ features │ │ │ ╭───┬─────╮ │ │", "│ features │ │ │ ╭───┬─────╮ │ │",
"│ │ │ plugin │ │ 0 │ nu- │ │ │", "│ │ │ plugin │ │ 0 │ nu- │ │ │",
@ -2234,11 +2238,10 @@ fn test_collapse_big_0() {
"│ ├───────────────┼──────────┬───────────┬────────────────────┤", "│ ├───────────────┼──────────┬───────────┬────────────────────┤",
"│ │ metadata │ binstall │ pkg-url │ { repo }/releases/ │", "│ │ metadata │ binstall │ pkg-url │ { repo }/releases/ │",
"│ │ │ │ │ download/{ v │", "│ │ │ │ │ download/{ v │",
"│ │ │ │ │ ersion │", "│ │ │ │ │ ersion }/{ name }- │",
"│ │ │ │ │ }/{ name }-{ vers │", "│ │ │ │ │ { version }- │",
"│ │ │ │ │ ion }- │", "│ │ │ │ │ { target }.{ archi │",
"│ │ │ │ │ { target }.{ │", "│ │ │ │ │ ve-format } │",
"│ │ │ │ │ archive-format } │",
"│ │ │ ├───────────┼────────────────────┤", "│ │ │ ├───────────┼────────────────────┤",
"│ │ │ │ pkg-fmt │ tgz │", "│ │ │ │ pkg-fmt │ tgz │",
"│ │ │ ├───────────┼────────────────────┤", "│ │ │ ├───────────┼────────────────────┤",

View File

@ -17,7 +17,7 @@ use tabled::{
config::{ config::{
AlignmentHorizontal, ColoredConfig, Entity, Indent, Position, Sides, SpannedConfig, AlignmentHorizontal, ColoredConfig, Entity, Indent, Position, Sides, SpannedConfig,
}, },
dimension::{CompleteDimensionVecRecords, SpannedGridDimension}, dimension::{CompleteDimension, Dimension, IterGridDimension},
records::{ records::{
vec_records::{Cell, Text, VecRecords}, vec_records::{Cell, Text, VecRecords},
IntoRecords, IterRecords, Records, IntoRecords, IterRecords, Records,
@ -93,11 +93,11 @@ impl NuTable {
pub fn insert(&mut self, pos: Position, text: String) { pub fn insert(&mut self, pos: Position, text: String) {
let text = Text::new(text); let text = Text::new(text);
self.widths[pos.1] = max( self.widths[pos.col] = max(
self.widths[pos.1], self.widths[pos.col],
text.width() + indent_sum(self.config.indent), text.width() + indent_sum(self.config.indent),
); );
self.data[pos.0][pos.1] = text; self.data[pos.row][pos.col] = text;
} }
pub fn set_row(&mut self, index: usize, row: Vec<NuRecordsValue>) { pub fn set_row(&mut self, index: usize, row: Vec<NuRecordsValue>) {
@ -392,7 +392,7 @@ fn remove_header(t: &mut NuTable) -> HeadInfo {
let alignment = *t let alignment = *t
.styles .styles
.cfg .cfg
.get_alignment_horizontal(Entity::Cell(row, col)); .get_alignment_horizontal(Position::new(row, col));
if alignment != t.styles.alignments.data { if alignment != t.styles.alignments.data {
t.styles t.styles
.cfg .cfg
@ -400,7 +400,12 @@ fn remove_header(t: &mut NuTable) -> HeadInfo {
} }
// TODO: use get_color from upstream (when released) // TODO: use get_color from upstream (when released)
let color = t.styles.cfg.get_colors().get_color((row, col)).cloned(); let color = t
.styles
.cfg
.get_colors()
.get_color(Position::new(row, col))
.cloned();
if let Some(color) = color { if let Some(color) = color {
t.styles.cfg.set_color(Entity::Cell(row - 1, col), color); t.styles.cfg.set_color(Entity::Cell(row - 1, col), color);
} }
@ -565,12 +570,12 @@ impl WidthEstimation {
} }
} }
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>> for WidthCtrl { impl TableOption<NuRecords, ColoredConfig, CompleteDimension<'_>> for WidthCtrl {
fn change( fn change(
self, self,
recs: &mut NuRecords, recs: &mut NuRecords,
cfg: &mut ColoredConfig, cfg: &mut ColoredConfig,
dims: &mut CompleteDimensionVecRecords<'_>, dims: &mut CompleteDimension<'_>,
) { ) {
if self.width.truncate { if self.width.truncate {
width_ctrl_truncate(self, recs, cfg, dims); width_ctrl_truncate(self, recs, cfg, dims);
@ -591,7 +596,7 @@ fn width_ctrl_expand(
ctrl: WidthCtrl, ctrl: WidthCtrl,
recs: &mut NuRecords, recs: &mut NuRecords,
cfg: &mut ColoredConfig, cfg: &mut ColoredConfig,
dims: &mut CompleteDimensionVecRecords, dims: &mut CompleteDimension,
) { ) {
let opt = Width::increase(ctrl.max_width); let opt = Width::increase(ctrl.max_width);
TableOption::<VecRecords<_>, _, _>::change(opt, recs, cfg, dims); TableOption::<VecRecords<_>, _, _>::change(opt, recs, cfg, dims);
@ -601,7 +606,7 @@ fn width_ctrl_truncate(
ctrl: WidthCtrl, ctrl: WidthCtrl,
recs: &mut NuRecords, recs: &mut NuRecords,
cfg: &mut ColoredConfig, cfg: &mut ColoredConfig,
dims: &mut CompleteDimensionVecRecords, dims: &mut CompleteDimension,
) { ) {
for (col, (&width, width_original)) in ctrl for (col, (&width, width_original)) in ctrl
.width .width
@ -644,9 +649,11 @@ fn align_table(
table.with(AlignmentStrategy::PerLine); table.with(AlignmentStrategy::PerLine);
if structure.with_header { if structure.with_header {
table.modify(Rows::first(), AlignmentStrategy::PerCell);
table.modify(Rows::first(), Alignment::from(alignments.header)); table.modify(Rows::first(), Alignment::from(alignments.header));
if structure.with_footer { if structure.with_footer {
table.modify(Rows::last(), AlignmentStrategy::PerCell);
table.modify(Rows::last(), Alignment::from(alignments.header)); table.modify(Rows::last(), Alignment::from(alignments.header));
} }
} }
@ -1024,8 +1031,8 @@ fn convert_alignment(alignment: nu_color_config::Alignment) -> AlignmentHorizont
// TODO: expose it get_dims_mut() // TODO: expose it get_dims_mut()
struct SetDimensions(Vec<usize>); struct SetDimensions(Vec<usize>);
impl<R> TableOption<R, ColoredConfig, CompleteDimensionVecRecords<'_>> for SetDimensions { impl<R> TableOption<R, ColoredConfig, CompleteDimension<'_>> for SetDimensions {
fn change(self, _: &mut R, _: &mut ColoredConfig, dims: &mut CompleteDimensionVecRecords<'_>) { fn change(self, _: &mut R, _: &mut ColoredConfig, dims: &mut CompleteDimension<'_>) {
dims.set_widths(self.0); dims.set_widths(self.0);
} }
} }
@ -1044,8 +1051,7 @@ where
cfg.set_padding(Entity::Global, padding); cfg.set_padding(Entity::Global, padding);
// TODO: Use peekable width IterGridDimension::width(records, &cfg)
SpannedGridDimension::width(records, &cfg)
} }
// It's laverages a use of guuaranted cached widths before hand // It's laverages a use of guuaranted cached widths before hand
@ -1062,32 +1068,27 @@ impl SetLineHeaders {
} }
} }
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>> for SetLineHeaders { impl TableOption<NuRecords, ColoredConfig, CompleteDimension<'_>> for SetLineHeaders {
fn change( fn change(
self, self,
recs: &mut NuRecords, recs: &mut NuRecords,
cfg: &mut ColoredConfig, cfg: &mut ColoredConfig,
dims: &mut CompleteDimensionVecRecords<'_>, dims: &mut CompleteDimension<'_>,
) { ) {
let widths = match dims.get_widths() { if dims.is_empty() {
Some(widths) => widths, // we don't have widths cached; which means that NO width adjustments were done
None => { // which means we are OK to leave columns as they are.
// we don't have widths cached; which means that NO width adjustments were done //
// which means we are OK to leave columns as they are. // but we actually always have to have widths at this point
// unreachable!("must never be the case");
// but we actually always have to have widths at this point }
unreachable!("must never be the case"); let mut columns = self.head.values;
} for (i, name) in columns.iter_mut().enumerate() {
}; let width = dims.get_width(i);
let width = width - self.pad;
let columns: Vec<_> = self *name = Truncate::truncate(name, width).into_owned();
.head }
.values
.into_iter()
.zip(widths.iter().cloned()) // it must be always safe to do
.map(|(s, width)| Truncate::truncate(&s, width - self.pad).into_owned())
.collect();
let mut names = ColumnNames::new(columns) let mut names = ColumnNames::new(columns)
.line(self.line) .line(self.line)
@ -1110,20 +1111,6 @@ fn theme_copy_horizontal_line(theme: &mut tabled::settings::Theme, from: usize,
} }
} }
// todo: create a method
#[derive(Debug, Default)]
struct GetDims(Vec<usize>);
impl<R, C> TableOption<R, C, CompleteDimensionVecRecords<'_>> for &mut GetDims {
fn change(self, _: &mut R, _: &mut C, dims: &mut CompleteDimensionVecRecords<'_>) {
self.0 = dims.get_widths().expect("expected to get it").to_vec();
}
fn hint_change(&self) -> Option<Entity> {
None
}
}
pub fn get_color_if_exists(c: &Color) -> Option<Color> { pub fn get_color_if_exists(c: &Color) -> Option<Color> {
if !is_color_empty(c) { if !is_color_empty(c) {
Some(c.clone()) Some(c.clone())

View File

@ -3,6 +3,7 @@ use std::cmp::max;
use nu_color_config::{Alignment, StyleComputer, TextStyle}; use nu_color_config::{Alignment, StyleComputer, TextStyle};
use nu_engine::column::get_columns; use nu_engine::column::get_columns;
use nu_protocol::{Config, Record, ShellError, Span, Value}; use nu_protocol::{Config, Record, ShellError, Span, Value};
use tabled::grid::config::Position;
use crate::{ use crate::{
common::{ common::{
@ -157,8 +158,8 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width); let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width);
let cell = expand_entry(item, inner_cfg); let cell = expand_entry(item, inner_cfg);
table.insert((row, 0), cell.text); table.insert(Position::new(row, 0), cell.text);
table.insert_style((row, 0), cell.style); table.insert_style(Position::new(row, 0), cell.style);
total_rows = total_rows.saturating_add(cell.size); total_rows = total_rows.saturating_add(cell.size);
} }
@ -191,7 +192,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
return Ok(None); return Ok(None);
} }
table.insert((row, 0), index_value); table.insert(Position::new(row, 0), index_value);
index_column_width = max(index_column_width, index_width); index_column_width = max(index_column_width, index_width);
} }
@ -205,8 +206,8 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width); let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width);
let cell = expand_entry(item, inner_cfg); let cell = expand_entry(item, inner_cfg);
table.insert((row, 1), cell.text); table.insert(Position::new(row, 1), cell.text);
table.insert_style((row, 1), cell.style); table.insert_style(Position::new(row, 1), cell.style);
total_rows = total_rows.saturating_add(cell.size); total_rows = total_rows.saturating_add(cell.size);
} }
@ -225,7 +226,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
let mut widths = Vec::new(); let mut widths = Vec::new();
if with_index { if with_index {
table.insert((0, 0), String::from("#")); table.insert(Position::new(0, 0), String::from("#"));
let mut index_column_width = 1; let mut index_column_width = 1;
@ -242,7 +243,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
.unwrap_or_else(|| index.to_string()); .unwrap_or_else(|| index.to_string());
let index_width = string_width(&index_value); let index_width = string_width(&index_value);
table.insert((row + 1, 0), index_value); table.insert(Position::new(row + 1, 0), index_value);
index_column_width = max(index_column_width, index_width); index_column_width = max(index_column_width, index_width);
} }
@ -291,8 +292,8 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
column_width = max(column_width, value_width); column_width = max(column_width, value_width);
table.insert((row + 1, column), cell.text); table.insert(Position::new(row + 1, column), cell.text);
table.insert_style((row + 1, column), cell.style); table.insert_style(Position::new(row + 1, column), cell.style);
total_column_rows = total_column_rows.saturating_add(cell.size); total_column_rows = total_column_rows.saturating_add(cell.size);
} }
@ -304,7 +305,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
head_width = available; head_width = available;
} }
table.insert((0, column), header); table.insert(Position::new(0, column), header);
column_width = max(column_width, head_width); column_width = max(column_width, head_width);
assert!(column_width <= available); assert!(column_width <= available);
@ -406,8 +407,8 @@ fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> CellResult {
key.insert(0, '\n'); key.insert(0, '\n');
} }
table.insert((i, 0), key); table.insert(Position::new(i, 0), key);
table.insert((i, 1), value); table.insert(Position::new(i, 1), value);
total_rows = total_rows.saturating_add(cell.size); total_rows = total_rows.saturating_add(cell.size);
} }

View File

@ -1,6 +1,7 @@
use nu_color_config::TextStyle; use nu_color_config::TextStyle;
use nu_engine::column::get_columns; use nu_engine::column::get_columns;
use nu_protocol::{Config, Record, ShellError, Value}; use nu_protocol::{Config, Record, ShellError, Value};
use tabled::grid::config::Position;
use crate::{ use crate::{
clean_charset, colorize_space, clean_charset, colorize_space,
@ -50,8 +51,8 @@ fn kv_table(record: Record, opts: TableOpts<'_>) -> StringResult {
let value = nu_value_to_string_colored(&value, opts.config, &opts.style_computer); let value = nu_value_to_string_colored(&value, opts.config, &opts.style_computer);
table.insert((i, 0), key); table.insert(Position::new(i, 0), key);
table.insert((i, 1), value); table.insert(Position::new(i, 1), value);
} }
let mut out = TableOutput::from_table(table, false, true); let mut out = TableOutput::from_table(table, false, true);
@ -102,7 +103,7 @@ fn create_table_with_header(
for (col, header) in headers.iter().enumerate() { for (col, header) in headers.iter().enumerate() {
let (text, style) = get_string_value_with_header(&item, header, opts); let (text, style) = get_string_value_with_header(&item, header, opts);
let pos = (row + 1, col); let pos = Position::new(row + 1, col);
table.insert(pos, text); table.insert(pos, text);
table.insert_style(pos, style); table.insert_style(pos, style);
} }
@ -137,12 +138,12 @@ fn create_table_with_header_and_index(
check_value(&item)?; check_value(&item)?;
let text = get_table_row_index(&item, opts.config, row, row_offset); let text = get_table_row_index(&item, opts.config, row, row_offset);
table.insert((row + 1, 0), text); table.insert(Position::new(row + 1, 0), text);
for (col, head) in head.iter().enumerate().skip(1) { for (col, head) in head.iter().enumerate().skip(1) {
let (text, style) = get_string_value_with_header(&item, head.as_ref(), opts); let (text, style) = get_string_value_with_header(&item, head.as_ref(), opts);
let pos = (row + 1, col); let pos = Position::new(row + 1, col);
table.insert(pos, text); table.insert(pos, text);
table.insert_style(pos, style); table.insert_style(pos, style);
} }
@ -165,8 +166,8 @@ fn create_table_with_no_header(
let (text, style) = get_string_value(&item, opts); let (text, style) = get_string_value(&item, opts);
table.insert((row, 0), text); table.insert(Position::new(row, 0), text);
table.insert_style((row, 0), style); table.insert_style(Position::new(row, 0), style);
} }
Ok(Some(table)) Ok(Some(table))
@ -188,9 +189,9 @@ fn create_table_with_no_header_and_index(
let index = get_table_row_index(&item, opts.config, row, row_offset); let index = get_table_row_index(&item, opts.config, row, row_offset);
let (value, style) = get_string_value(&item, opts); let (value, style) = get_string_value(&item, opts);
table.insert((row, 0), index); table.insert(Position::new(row, 0), index);
table.insert((row, 1), value); table.insert(Position::new(row, 1), value);
table.insert_style((row, 1), style); table.insert_style(Position::new(row, 1), style);
} }
Ok(Some(table)) Ok(Some(table))

View File

@ -81,8 +81,8 @@ fn wrap_test() {
let tests = [ let tests = [
(15, Some("┏━━━━━━━┳━━━━━┓\n┃ 123 4 ┃ ... ┃\n┃ 5678 ┃ ┃\n┣━━━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━━━┻━━━━━┛")), (15, Some("┏━━━━━━━┳━━━━━┓\n┃ 123 4 ┃ ... ┃\n┃ 5678 ┃ ┃\n┣━━━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━━━┻━━━━━┛")),
(21, Some("┏━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ ... ┃\n┣━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━┛")), (21, Some("┏━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ ... ┃\n┣━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━┛")),
(29, Some("┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw e ┃ ... ┃\n┃ ┃ qwe ┃ ┃\n┣━━━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━┻━━━━━┛")), (29, Some("┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw e ┃ ... ┃\n┃ ┃ qwe ┃ ┃\n┣━━━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━┻━━━━━┛")),
(49, Some("┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw eqwe ┃ xxx xx xx x xx ┃ ... ┃\n┃ ┃ ┃ x xx xx ┃ ┃\n┣━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┻━━━━━┛")), (49, Some("┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw eqwe ┃ xxx xx xx x xx ┃ ... ┃\n┃ ┃ ┃ x xx xx ┃ ┃\n┣━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┻━━━━━┛")),
]; ];
test_trim(&tests, TrimStrategy::wrap(false)); test_trim(&tests, TrimStrategy::wrap(false));
@ -98,7 +98,7 @@ fn wrap_keep_words_test() {
(15, Some("┏━━━━━━━┳━━━━━┓\n┃ 123 ┃ ... ┃\n┃ 45678 ┃ ┃\n┣━━━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━━━┻━━━━━┛")), (15, Some("┏━━━━━━━┳━━━━━┓\n┃ 123 ┃ ... ┃\n┃ 45678 ┃ ┃\n┣━━━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━━━┻━━━━━┛")),
(21, Some("┏━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ ... ┃\n┣━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━┛")), (21, Some("┏━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ ... ┃\n┣━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━┛")),
(29, Some("┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw ┃ ... ┃\n┃ ┃ eqwe ┃ ┃\n┣━━━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━┻━━━━━┛")), (29, Some("┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw ┃ ... ┃\n┃ ┃ eqwe ┃ ┃\n┣━━━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━┻━━━━━┛")),
(49, Some("┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw eqwe ┃ xxx xx xx x xx ┃ ... ┃\n┃ ┃ ┃ x xx xx ┃ ┃\n┣━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┻━━━━━┛")), (49, Some("┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw eqwe ┃ xxx xx xx x xx ┃ ... ┃\n┃ ┃ ┃ x xx xx ┃ ┃\n┣━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┻━━━━━┛")),
]; ];
test_trim(&tests, TrimStrategy::wrap(true)); test_trim(&tests, TrimStrategy::wrap(true));