mirror of
https://github.com/nushell/nushell.git
synced 2025-05-05 23:42:56 +00:00
nu-table/ 1 refactoring + a few optimizations + small fix (#15653)
- A few days back I've got this idea regarding recalculus of width. Now it calculates step by step. So 1 loop over all data was removed. All though there's full recalculation in case of `header_on_border` 😞 (can be fixed..... but I decided to be short) In perfect world it also shall be refactored ...... - Also have done small refactoring to switch build table from `Vec<Vec<_>>>` to table itself. To hide internals (kind of still there's things which I don't like). It touched the `--expand` algorithm lightly you can see the tests changes. - And when doing that noticed one more opportunity, to remove HashMap usage and directly use `tabled::ColoredConfig`. Which reduces copy operations and allocations. - And fixed a small issue where trailing column being using deleted column styles.  To conclude optimizations; I did small testing and it's not slower. But I didn't get the faster results either. But I believe it must be faster well in all cases, I think maybe bigger tables must be tested. Maybe someone could have a few runs to compare performance. cc: @fdncred
This commit is contained in:
parent
60e9f469af
commit
deca337a56
@ -17,8 +17,8 @@ use nu_protocol::{
|
|||||||
Signals, TableMode, ValueIterator,
|
Signals, TableMode, ValueIterator,
|
||||||
};
|
};
|
||||||
use nu_table::{
|
use nu_table::{
|
||||||
common::configure_table, CollapsedTable, ExpandedTable, JustTable, NuRecordsValue, NuTable,
|
common::configure_table, CollapsedTable, ExpandedTable, JustTable, NuTable, StringResult,
|
||||||
StringResult, TableOpts, TableOutput,
|
TableOpts, TableOutput,
|
||||||
};
|
};
|
||||||
use nu_utils::{get_ls_colors, terminal_size};
|
use nu_utils::{get_ls_colors, terminal_size};
|
||||||
|
|
||||||
@ -609,7 +609,7 @@ fn build_table_kv(
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> StringResult {
|
) -> StringResult {
|
||||||
match table_view {
|
match table_view {
|
||||||
TableView::General => JustTable::kv_table(&record, opts),
|
TableView::General => JustTable::kv_table(record, opts),
|
||||||
TableView::Expanded {
|
TableView::Expanded {
|
||||||
limit,
|
limit,
|
||||||
flatten,
|
flatten,
|
||||||
@ -645,7 +645,7 @@ fn build_table_batch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
match view {
|
match view {
|
||||||
TableView::General => JustTable::table(&vals, opts),
|
TableView::General => JustTable::table(vals, opts),
|
||||||
TableView::Expanded {
|
TableView::Expanded {
|
||||||
limit,
|
limit,
|
||||||
flatten,
|
flatten,
|
||||||
@ -1090,9 +1090,9 @@ fn create_empty_placeholder(
|
|||||||
return String::new();
|
return String::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
let cell = NuRecordsValue::new(format!("empty {}", value_type_name));
|
let cell = format!("empty {}", value_type_name);
|
||||||
let data = vec![vec![cell]];
|
let mut table = NuTable::new(1, 1);
|
||||||
let mut table = NuTable::from(data);
|
table.insert((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);
|
||||||
|
|
||||||
|
@ -1333,15 +1333,17 @@ fn test_expand_big_0() {
|
|||||||
"│ target │ {record 3 fields} │",
|
"│ target │ {record 3 fields} │",
|
||||||
"│ dev-dependencies │ {record 9 fields} │",
|
"│ dev-dependencies │ {record 9 fields} │",
|
||||||
"│ features │ {record 8 fields} │",
|
"│ features │ {record 8 fields} │",
|
||||||
"│ │ ╭───┬─────┬─────╮ │",
|
"│ │ ╭───┬──────┬────╮ │",
|
||||||
"│ bin │ │ # │ nam │ pat │ │",
|
"│ bin │ │ # │ name │ pa │ │",
|
||||||
"│ │ │ │ e │ h │ │",
|
"│ │ │ │ │ th │ │",
|
||||||
"│ │ ├───┼─────┼─────┤ │",
|
"│ │ ├───┼──────┼────┤ │",
|
||||||
"│ │ │ 0 │ nu │ src │ │",
|
"│ │ │ 0 │ nu │ sr │ │",
|
||||||
"│ │ │ │ │ /ma │ │",
|
"│ │ │ │ │ c/ │ │",
|
||||||
"│ │ │ │ │ in. │ │",
|
"│ │ │ │ │ ma │ │",
|
||||||
"│ │ │ │ │ rs │ │",
|
"│ │ │ │ │ in │ │",
|
||||||
"│ │ ╰───┴─────┴─────╯ │",
|
"│ │ │ │ │ .r │ │",
|
||||||
|
"│ │ │ │ │ s │ │",
|
||||||
|
"│ │ ╰───┴──────┴────╯ │",
|
||||||
"│ │ ╭───────────┬───╮ │",
|
"│ │ ╭───────────┬───╮ │",
|
||||||
"│ patch │ │ crates-io │ { │ │",
|
"│ patch │ │ crates-io │ { │ │",
|
||||||
"│ │ │ │ r │ │",
|
"│ │ │ │ r │ │",
|
||||||
@ -1360,16 +1362,16 @@ fn test_expand_big_0() {
|
|||||||
"│ │ │ │ d │ │",
|
"│ │ │ │ d │ │",
|
||||||
"│ │ │ │ } │ │",
|
"│ │ │ │ } │ │",
|
||||||
"│ │ ╰───────────┴───╯ │",
|
"│ │ ╰───────────┴───╯ │",
|
||||||
"│ │ ╭───┬─────┬─────╮ │",
|
"│ │ ╭───┬──────┬────╮ │",
|
||||||
"│ bench │ │ # │ nam │ har │ │",
|
"│ bench │ │ # │ name │ ha │ │",
|
||||||
"│ │ │ │ e │ nes │ │",
|
"│ │ │ │ │ rn │ │",
|
||||||
"│ │ │ │ │ s │ │",
|
"│ │ │ │ │ es │ │",
|
||||||
"│ │ ├───┼─────┼─────┤ │",
|
"│ │ │ │ │ s │ │",
|
||||||
"│ │ │ 0 │ ben │ fal │ │",
|
"│ │ ├───┼──────┼────┤ │",
|
||||||
"│ │ │ │ chm │ se │ │",
|
"│ │ │ 0 │ benc │ fa │ │",
|
||||||
"│ │ │ │ ark │ │ │",
|
"│ │ │ │ hmar │ ls │ │",
|
||||||
"│ │ │ │ s │ │ │",
|
"│ │ │ │ ks │ e │ │",
|
||||||
"│ │ ╰───┴─────┴─────╯ │",
|
"│ │ ╰───┴──────┴────╯ │",
|
||||||
"╰──────────────────┴───────────────────╯",
|
"╰──────────────────┴───────────────────╯",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -1551,193 +1553,114 @@ fn table_expande_with_no_header_internally_0() {
|
|||||||
"│ │ │ │ │ │ ╰─────┴──────────╯ │ │ │",
|
"│ │ │ │ │ │ ╰─────┴──────────╯ │ │ │",
|
||||||
"│ │ │ │ │ display_output │ │ │ │",
|
"│ │ │ │ │ display_output │ │ │ │",
|
||||||
"│ │ │ │ ╰────────────────┴────────────────────╯ │ │",
|
"│ │ │ │ ╰────────────────┴────────────────────╯ │ │",
|
||||||
"│ │ │ │ ╭───┬───────────────────────────┬────────────────────────┬────────┬───┬─────╮ │ │",
|
"│ │ │ │ ╭───┬───────────────────────────┬────────────────────────┬────────┬─────╮ │ │",
|
||||||
"│ │ │ menus │ │ # │ name │ only_buffer_difference │ marker │ t │ ... │ │ │",
|
"│ │ │ menus │ │ # │ name │ only_buffer_difference │ marker │ ... │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ y │ │ │ │",
|
"│ │ │ │ ├───┼───────────────────────────┼────────────────────────┼────────┼─────┤ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ p │ │ │ │",
|
"│ │ │ │ │ 0 │ completion_menu │ false │ | │ ... │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ 1 │ history_menu │ true │ ? │ ... │ │ │",
|
||||||
"│ │ │ │ ├───┼───────────────────────────┼────────────────────────┼────────┼───┼─────┤ │ │",
|
"│ │ │ │ │ 2 │ help_menu │ true │ ? │ ... │ │ │",
|
||||||
"│ │ │ │ │ 0 │ completion_menu │ false │ | │ { │ ... │ │ │",
|
"│ │ │ │ │ 3 │ commands_menu │ false │ # │ ... │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ 4 │ vars_menu │ true │ # │ ... │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ 5 │ commands_with_description │ true │ # │ ... │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ c │ │ │ │",
|
"│ │ │ │ ╰───┴───────────────────────────┴────────────────────────┴────────┴─────╯ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ o │ │ │ │",
|
"│ │ │ │ ╭────┬───────────────────────────┬──────────┬─────────┬────────────────┬────╮ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ keybindings │ │ # │ name │ modifier │ keycode │ mode │ ev │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ en │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ t │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ 4 │ │ │ │",
|
"│ │ │ │ ├────┼───────────────────────────┼──────────┼─────────┼────────────────┼────┤ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ 0 │ completion_menu │ none │ tab │ ╭───┬────────╮ │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ f │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ i │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_nor │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ mal │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ l │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_ins │ │ 1 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ ert │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ s │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ ╰───┴────────╯ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ } │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d} │ │ │",
|
||||||
"│ │ │ │ │ 1 │ history_menu │ true │ ? │ { │ ... │ │ │",
|
"│ │ │ │ │ 1 │ completion_previous │ shift │ backtab │ ╭───┬────────╮ │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_nor │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ c │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ mal │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ o │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_ins │ │ 1 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ ert │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ ╰───┴────────╯ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d} │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ 2 │ │ │ │",
|
"│ │ │ │ │ 2 │ history_menu │ control │ char_r │ emacs │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ f │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ i │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ l │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ s │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ds │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ } │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
||||||
"│ │ │ │ │ 2 │ help_menu │ true │ ? │ { │ ... │ │ │",
|
"│ │ │ │ │ 3 │ next_page │ control │ char_x │ emacs │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ c │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ o │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d} │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ 6 │ │ │ │",
|
"│ │ │ │ │ 4 │ undo_or_previous_page │ control │ char_z │ emacs │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ f │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ i │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ l │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ s │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d} │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ } │ │ │ │",
|
"│ │ │ │ │ 5 │ yank │ control │ char_y │ emacs │ {r │ │ │",
|
||||||
"│ │ │ │ │ 3 │ commands_menu │ false │ # │ { │ ... │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ c │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ o │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d} │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ 6 │ unix-line-discard │ control │ char_u │ ╭───┬────────╮ │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ 4 │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_nor │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ f │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ mal │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ i │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_ins │ │ 1 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ ert │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ l │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ ╰───┴────────╯ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d} │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ s │ │ │ │",
|
"│ │ │ │ │ 7 │ kill-line │ control │ char_k │ ╭───┬────────╮ │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ } │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ 4 │ vars_menu │ true │ # │ { │ ... │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_nor │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ mal │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_ins │ │ 1 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ c │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ ert │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ o │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ ╰───┴────────╯ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d} │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ 8 │ commands_menu │ control │ char_t │ ╭───┬────────╮ │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ 2 │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_nor │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ mal │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ f │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_ins │ │ 2 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ i │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ ert │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ ╰───┴────────╯ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ l │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ds │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ s │ │ │ │",
|
"│ │ │ │ │ 9 │ vars_menu │ alt │ char_o │ ╭───┬────────╮ │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ } │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ 5 │ commands_with_description │ true │ # │ { │ ... │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_nor │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ mal │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_ins │ │ 2 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ c │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ ert │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ o │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ ╰───┴────────╯ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ r │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ds │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ 10 │ commands_with_description │ control │ char_s │ ╭───┬────────╮ │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ 6 │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_nor │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ f │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ mal │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ i │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_ins │ │ 2 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ e │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ ert │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ l │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ ╰───┴────────╯ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ d │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ds │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ s │ │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ } │ │ │ │",
|
"│ │ │ │ ╰────┴───────────────────────────┴──────────┴─────────┴────────────────┴────╯ │ │",
|
||||||
"│ │ │ │ ╰───┴───────────────────────────┴────────────────────────┴────────┴───┴─────╯ │ │",
|
|
||||||
"│ │ │ │ ╭────┬───────────────────────────┬──────────┬─────────┬───────────────┬─────╮ │ │",
|
|
||||||
"│ │ │ keybindings │ │ # │ name │ modifier │ keycode │ mode │ eve │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ nt │ │ │",
|
|
||||||
"│ │ │ │ ├────┼───────────────────────────┼──────────┼─────────┼───────────────┼─────┤ │ │",
|
|
||||||
"│ │ │ │ │ 0 │ completion_menu │ none │ tab │ ╭───┬───────╮ │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 1 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ sert │ │ } │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │",
|
|
||||||
"│ │ │ │ │ 1 │ completion_previous │ shift │ backtab │ ╭───┬───────╮ │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 1 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ sert │ │ } │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │",
|
|
||||||
"│ │ │ │ │ 2 │ history_menu │ control │ char_r │ emacs │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 2 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ s} │ │ │",
|
|
||||||
"│ │ │ │ │ 3 │ next_page │ control │ char_x │ emacs │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 1 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
|
||||||
"│ │ │ │ │ 4 │ undo_or_previous_page │ control │ char_z │ emacs │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 1 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
|
||||||
"│ │ │ │ │ 5 │ yank │ control │ char_y │ emacs │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 1 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
|
||||||
"│ │ │ │ │ 6 │ unix-line-discard │ control │ char_u │ ╭───┬───────╮ │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 1 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ sert │ │ } │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │",
|
|
||||||
"│ │ │ │ │ 7 │ kill-line │ control │ char_k │ ╭───┬───────╮ │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 1 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ sert │ │ } │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │",
|
|
||||||
"│ │ │ │ │ 8 │ commands_menu │ control │ char_t │ ╭───┬───────╮ │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 2 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ sert │ │ s} │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │",
|
|
||||||
"│ │ │ │ │ 9 │ vars_menu │ alt │ char_o │ ╭───┬───────╮ │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 2 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ sert │ │ s} │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │",
|
|
||||||
"│ │ │ │ │ 10 │ commands_with_description │ control │ char_s │ ╭───┬───────╮ │ {re │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 2 │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ │ │ sert │ │ s} │ │ │",
|
|
||||||
"│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │",
|
|
||||||
"│ │ │ │ ╰────┴───────────────────────────┴──────────┴─────────┴───────────────┴─────╯ │ │",
|
|
||||||
"│ │ ╰──────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────╯ │",
|
"│ │ ╰──────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────╯ │",
|
||||||
"╰────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
|
"╰────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
|
||||||
])
|
])
|
||||||
@ -1929,77 +1852,220 @@ fn table_expande_with_no_header_internally_1() {
|
|||||||
"│ │ │ │ │ 4 │ vars_menu │ true │ # │ ... │ │ │",
|
"│ │ │ │ │ 4 │ vars_menu │ true │ # │ ... │ │ │",
|
||||||
"│ │ │ │ │ 5 │ commands_with_description │ true │ # │ ... │ │ │",
|
"│ │ │ │ │ 5 │ commands_with_description │ true │ # │ ... │ │ │",
|
||||||
"│ │ │ │ ╰───┴───────────────────────────┴────────────────────────┴───────┴─────╯ │ │",
|
"│ │ │ │ ╰───┴───────────────────────────┴────────────────────────┴───────┴─────╯ │ │",
|
||||||
"│ │ │ │ ╭────┬───────────────────────────┬──────────┬─────────┬──────────┬─────╮ │ │",
|
"│ │ │ │ ╭────┬───────────────────────────┬──────────┬─────────┬───────────┬────╮ │ │",
|
||||||
"│ │ │ keybindings │ │ # │ name │ modifier │ keycode │ mode │ eve │ │ │",
|
"│ │ │ keybindings │ │ # │ name │ modifier │ keycode │ mode │ ev │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ nt │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ en │ │ │",
|
||||||
"│ │ │ │ ├────┼───────────────────────────┼──────────┼─────────┼──────────┼─────┤ │ │",
|
"│ │ │ │ │ │ │ │ │ │ t │ │ │",
|
||||||
"│ │ │ │ │ 0 │ completion_menu │ none │ tab │ [list 3 │ {re │ │ │",
|
"│ │ │ │ ├────┼───────────────────────────┼──────────┼─────────┼───────────┼────┤ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ items] │ cor │ │ │",
|
"│ │ │ │ │ 0 │ completion_menu │ none │ tab │ ╭───┬───╮ │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 1 │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 0 │ e │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ c │ │ 1 │ │ │",
|
||||||
"│ │ │ │ │ 1 │ completion_previous │ shift │ backtab │ [list 3 │ {re │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ items] │ cor │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ v │ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 1 │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ d} │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ o │ │ │ │ │",
|
||||||
"│ │ │ │ │ 2 │ history_menu │ control │ char_r │ emacs │ {re │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ cor │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 2 │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ l │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ v │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ s} │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
"│ │ │ │ │ 3 │ next_page │ control │ char_x │ emacs │ {re │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ cor │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 1 │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ e │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
"│ │ │ │ │ 4 │ undo_or_previous_page │ control │ char_z │ emacs │ {re │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ t │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ cor │ │ │",
|
"│ │ │ │ │ │ │ │ │ ╰───┴───╯ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 1 │ │ │",
|
"│ │ │ │ │ 1 │ completion_previous │ shift │ backtab │ ╭───┬───╮ │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 0 │ e │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ d │ │ │",
|
||||||
"│ │ │ │ │ 5 │ yank │ control │ char_y │ emacs │ {re │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ c │ │ 1 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ cor │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 1 │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ v │ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ d} │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
"│ │ │ │ │ 6 │ unix-line-discard │ control │ char_u │ [list 3 │ {re │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ o │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ items] │ cor │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 1 │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ l │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ v │ │ │ │ │",
|
||||||
"│ │ │ │ │ 7 │ kill-line │ control │ char_k │ [list 3 │ {re │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ items] │ cor │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 1 │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ e │ │ │ │ │",
|
||||||
"│ │ │ │ │ 8 │ commands_menu │ control │ char_t │ [list 3 │ {re │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ items] │ cor │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ │ t │ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 2 │ │ │",
|
"│ │ │ │ │ │ │ │ │ ╰───┴───╯ │ │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ 2 │ history_menu │ control │ char_r │ emacs │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ s} │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ or │ │ │",
|
||||||
"│ │ │ │ │ 9 │ vars_menu │ alt │ char_o │ [list 3 │ {re │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ items] │ cor │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 2 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 2 │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ el │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ds │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ s} │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ } │ │ │",
|
||||||
"│ │ │ │ │ 10 │ commands_with_description │ control │ char_s │ [list 3 │ {re │ │ │",
|
"│ │ │ │ │ 3 │ next_page │ control │ char_x │ emacs │ {r │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ items] │ cor │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ ec │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ d 2 │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ or │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ d │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ eld │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ 1 │ │ │",
|
||||||
"│ │ │ │ │ │ │ │ │ │ s} │ │ │",
|
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
||||||
"│ │ │ │ ╰────┴───────────────────────────┴──────────┴─────────┴──────────┴─────╯ │ │",
|
"│ │ │ │ │ │ │ │ │ │ el │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ d} │ │ │",
|
||||||
|
"│ │ │ │ │ 4 │ undo_or_previous_page │ control │ char_z │ emacs │ {r │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ ec │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ or │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ d │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 1 │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ el │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ d} │ │ │",
|
||||||
|
"│ │ │ │ │ 5 │ yank │ control │ char_y │ emacs │ {r │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ ec │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ or │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ d │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 1 │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ fi │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ el │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ d} │ │ │",
|
||||||
|
"│ │ │ │ │ 6 │ unix-line-discard │ control │ char_u │ ╭───┬───╮ │ {r │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 0 │ e │ │ ec │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ or │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ d │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ c │ │ 1 │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ fi │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 1 │ v │ │ el │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ d} │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ o │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ l │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 2 │ v │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ e │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ t │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ ╰───┴───╯ │ │ │ │",
|
||||||
|
"│ │ │ │ │ 7 │ kill-line │ control │ char_k │ ╭───┬───╮ │ {r │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 0 │ e │ │ ec │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ or │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ d │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ c │ │ 1 │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ fi │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 1 │ v │ │ el │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ d} │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ o │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ l │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 2 │ v │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ e │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ t │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ ╰───┴───╯ │ │ │ │",
|
||||||
|
"│ │ │ │ │ 8 │ commands_menu │ control │ char_t │ ╭───┬───╮ │ {r │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 0 │ e │ │ ec │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ or │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ d │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ c │ │ 2 │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ fi │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 1 │ v │ │ el │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ ds │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ } │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ o │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ l │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 2 │ v │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ e │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ t │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ ╰───┴───╯ │ │ │ │",
|
||||||
|
"│ │ │ │ │ 9 │ vars_menu │ alt │ char_o │ ╭───┬───╮ │ {r │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 0 │ e │ │ ec │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ or │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ d │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ c │ │ 2 │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ fi │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 1 │ v │ │ el │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ ds │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ } │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ o │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ l │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 2 │ v │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ e │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ t │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ ╰───┴───╯ │ │ │ │",
|
||||||
|
"│ │ │ │ │ 10 │ commands_with_description │ control │ char_s │ ╭───┬───╮ │ {r │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 0 │ e │ │ ec │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ or │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ d │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ c │ │ 2 │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ fi │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 1 │ v │ │ el │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ ds │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ } │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ o │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ m │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ a │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ l │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ 2 │ v │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ _ │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ i │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ n │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ s │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ e │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ r │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ │ │ t │ │ │ │ │",
|
||||||
|
"│ │ │ │ │ │ │ │ │ ╰───┴───╯ │ │ │ │",
|
||||||
|
"│ │ │ │ ╰────┴───────────────────────────┴──────────┴─────────┴───────────┴────╯ │ │",
|
||||||
"│ │ ╰──────────────────────────────────┴──────────────────────────────────────────────────────────────────────────╯ │",
|
"│ │ ╰──────────────────────────────────┴──────────────────────────────────────────────────────────────────────────╯ │",
|
||||||
"╰────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
|
"╰────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
|
||||||
])
|
])
|
||||||
|
@ -21,10 +21,12 @@ fn main() {
|
|||||||
let headers = to_cell_info_vec(&table_headers);
|
let headers = to_cell_info_vec(&table_headers);
|
||||||
let rows = to_cell_info_vec(&row_data);
|
let rows = to_cell_info_vec(&row_data);
|
||||||
|
|
||||||
let mut rows = vec![rows; 3];
|
let mut table = NuTable::new(4, 3);
|
||||||
rows.insert(0, headers);
|
table.set_row(0, headers);
|
||||||
|
|
||||||
let mut table = NuTable::from(rows);
|
for i in 0..3 {
|
||||||
|
table.set_row(i + 1, rows.clone());
|
||||||
|
}
|
||||||
|
|
||||||
table.set_data_style(TextStyle::basic_left());
|
table.set_data_style(TextStyle::basic_left());
|
||||||
table.set_header_style(TextStyle::basic_center().style(Style::new().on(Color::Blue)));
|
table.set_header_style(TextStyle::basic_center().style(Style::new().on(Color::Blue)));
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// NOTE: TODO the above we could expose something like [`WidthCtrl`] in which case we could also laverage the width list build right away.
|
// NOTE: TODO the above we could expose something like [`WidthCtrl`] in which case we could also laverage the width list build right away.
|
||||||
// currently it seems like we do recacalculate it for `table -e`?
|
// currently it seems like we do recacalculate it for `table -e`?
|
||||||
|
|
||||||
use std::{cmp::min, collections::HashMap};
|
use std::cmp::{max, min};
|
||||||
|
|
||||||
use nu_ansi_term::Style;
|
use nu_ansi_term::Style;
|
||||||
use nu_color_config::TextStyle;
|
use nu_color_config::TextStyle;
|
||||||
@ -13,13 +13,14 @@ use tabled::{
|
|||||||
builder::Builder,
|
builder::Builder,
|
||||||
grid::{
|
grid::{
|
||||||
ansi::ANSIBuf,
|
ansi::ANSIBuf,
|
||||||
|
colors::Colors,
|
||||||
config::{
|
config::{
|
||||||
AlignmentHorizontal, ColoredConfig, Entity, Indent, Position, Sides, SpannedConfig,
|
AlignmentHorizontal, ColoredConfig, Entity, Indent, Position, Sides, SpannedConfig,
|
||||||
},
|
},
|
||||||
dimension::{CompleteDimensionVecRecords, SpannedGridDimension},
|
dimension::{CompleteDimensionVecRecords, SpannedGridDimension},
|
||||||
records::{
|
records::{
|
||||||
vec_records::{Text, VecRecords},
|
vec_records::{Cell, Text, VecRecords},
|
||||||
ExactRecords, Records,
|
IntoRecords, IterRecords, Records,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
settings::{
|
settings::{
|
||||||
@ -43,24 +44,30 @@ pub type NuRecordsValue = Text<String>;
|
|||||||
/// NuTable is a table rendering implementation.
|
/// NuTable is a table rendering implementation.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NuTable {
|
pub struct NuTable {
|
||||||
data: NuRecords,
|
data: Vec<Vec<NuRecordsValue>>,
|
||||||
|
widths: Vec<usize>,
|
||||||
|
count_rows: usize,
|
||||||
|
count_cols: usize,
|
||||||
styles: Styles,
|
styles: Styles,
|
||||||
alignments: Alignments,
|
|
||||||
config: TableConfig,
|
config: TableConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NuTable {
|
impl NuTable {
|
||||||
/// Creates an empty [`NuTable`] instance.
|
/// Creates an empty [`NuTable`] instance.
|
||||||
pub fn new(count_rows: usize, count_columns: usize) -> Self {
|
pub fn new(count_rows: usize, count_cols: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: VecRecords::new(vec![vec![Text::default(); count_columns]; count_rows]),
|
data: vec![vec![Text::default(); count_cols]; count_rows],
|
||||||
styles: Styles::default(),
|
widths: vec![2; count_cols],
|
||||||
alignments: Alignments {
|
count_rows,
|
||||||
data: AlignmentHorizontal::Left,
|
count_cols,
|
||||||
index: AlignmentHorizontal::Right,
|
styles: Styles {
|
||||||
header: AlignmentHorizontal::Center,
|
cfg: ColoredConfig::default(),
|
||||||
columns: HashMap::default(),
|
alignments: CellConfiguration {
|
||||||
cells: HashMap::default(),
|
data: AlignmentHorizontal::Left,
|
||||||
|
index: AlignmentHorizontal::Right,
|
||||||
|
header: AlignmentHorizontal::Center,
|
||||||
|
},
|
||||||
|
colors: CellConfiguration::default(),
|
||||||
},
|
},
|
||||||
config: TableConfig {
|
config: TableConfig {
|
||||||
theme: TableTheme::basic(),
|
theme: TableTheme::basic(),
|
||||||
@ -76,84 +83,125 @@ impl NuTable {
|
|||||||
|
|
||||||
/// Return amount of rows.
|
/// Return amount of rows.
|
||||||
pub fn count_rows(&self) -> usize {
|
pub fn count_rows(&self) -> usize {
|
||||||
self.data.count_rows()
|
self.count_rows
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return amount of columns.
|
/// Return amount of columns.
|
||||||
pub fn count_columns(&self) -> usize {
|
pub fn count_columns(&self) -> usize {
|
||||||
self.data.count_columns()
|
self.count_cols
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, pos: Position, text: String) {
|
pub fn insert(&mut self, pos: Position, text: String) {
|
||||||
self.data[pos.0][pos.1] = Text::new(text);
|
let text = Text::new(text);
|
||||||
}
|
self.widths[pos.1] = max(
|
||||||
|
self.widths[pos.1],
|
||||||
pub fn insert_row(&mut self, index: usize, row: Vec<String>) {
|
text.width() + indent_sum(self.config.indent),
|
||||||
let data = &mut self.data[index];
|
);
|
||||||
|
self.data[pos.0][pos.1] = text;
|
||||||
for (col, text) in row.into_iter().enumerate() {
|
|
||||||
data[col] = Text::new(text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_row(&mut self, index: usize, row: Vec<NuRecordsValue>) {
|
pub fn set_row(&mut self, index: usize, row: Vec<NuRecordsValue>) {
|
||||||
assert_eq!(self.data[index].len(), row.len());
|
assert_eq!(self.data[index].len(), row.len());
|
||||||
|
|
||||||
|
for (i, text) in row.iter().enumerate() {
|
||||||
|
self.widths[i] = max(
|
||||||
|
self.widths[i],
|
||||||
|
text.width() + indent_sum(self.config.indent),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
self.data[index] = row;
|
self.data[index] = row;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_column_style(&mut self, column: usize, style: TextStyle) {
|
pub fn pop_column(&mut self, count: usize) {
|
||||||
if let Some(style) = style.color_style {
|
self.count_cols -= count;
|
||||||
let style = convert_style(style);
|
self.widths.truncate(self.count_cols);
|
||||||
self.styles.columns.insert(column, style);
|
for row in &mut self.data[..] {
|
||||||
|
row.truncate(self.count_cols);
|
||||||
}
|
}
|
||||||
|
|
||||||
let alignment = convert_alignment(style.alignment);
|
// set to default styles of the popped columns
|
||||||
if alignment != self.alignments.data {
|
for i in 0..count {
|
||||||
self.alignments.columns.insert(column, alignment);
|
let col = self.count_cols + i;
|
||||||
|
for row in 0..self.count_rows {
|
||||||
|
self.styles
|
||||||
|
.cfg
|
||||||
|
.set_alignment_horizontal(Entity::Cell(row, col), self.styles.alignments.data);
|
||||||
|
self.styles
|
||||||
|
.cfg
|
||||||
|
.set_color(Entity::Cell(row, col), ANSIBuf::default());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_column(&mut self, text: String) {
|
||||||
|
let value = Text::new(text);
|
||||||
|
|
||||||
|
self.widths
|
||||||
|
.push(value.width() + indent_sum(self.config.indent));
|
||||||
|
|
||||||
|
for row in &mut self.data[..] {
|
||||||
|
row.push(value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.count_cols += 1;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn insert_style(&mut self, pos: Position, style: TextStyle) {
|
pub fn insert_style(&mut self, pos: Position, style: TextStyle) {
|
||||||
if let Some(style) = style.color_style {
|
if let Some(style) = style.color_style {
|
||||||
let style = convert_style(style);
|
let style = convert_style(style);
|
||||||
self.styles.cells.insert(pos, style);
|
self.styles.cfg.set_color(pos.into(), style.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let alignment = convert_alignment(style.alignment);
|
let alignment = convert_alignment(style.alignment);
|
||||||
if alignment != self.alignments.data {
|
if alignment != self.styles.alignments.data {
|
||||||
self.alignments.cells.insert(pos, alignment);
|
self.styles
|
||||||
|
.cfg
|
||||||
|
.set_alignment_horizontal(pos.into(), alignment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_header_style(&mut self, style: TextStyle) {
|
pub fn set_header_style(&mut self, style: TextStyle) {
|
||||||
if let Some(style) = style.color_style {
|
if let Some(style) = style.color_style {
|
||||||
let style = convert_style(style);
|
let style = convert_style(style);
|
||||||
self.styles.header = style;
|
self.styles.colors.header = style;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.alignments.header = convert_alignment(style.alignment);
|
self.styles.alignments.header = convert_alignment(style.alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_index_style(&mut self, style: TextStyle) {
|
pub fn set_index_style(&mut self, style: TextStyle) {
|
||||||
if let Some(style) = style.color_style {
|
if let Some(style) = style.color_style {
|
||||||
let style = convert_style(style);
|
let style = convert_style(style);
|
||||||
self.styles.index = style;
|
self.styles.colors.index = style;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.alignments.index = convert_alignment(style.alignment);
|
self.styles.alignments.index = convert_alignment(style.alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_data_style(&mut self, style: TextStyle) {
|
pub fn set_data_style(&mut self, style: TextStyle) {
|
||||||
if let Some(style) = style.color_style {
|
if let Some(style) = style.color_style {
|
||||||
let style = convert_style(style);
|
if !style.is_plain() {
|
||||||
self.styles.data = style;
|
let style = convert_style(style);
|
||||||
|
self.styles.cfg.set_color(Entity::Global, style.into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.alignments.data = convert_alignment(style.alignment);
|
let alignment = convert_alignment(style.alignment);
|
||||||
|
self.styles
|
||||||
|
.cfg
|
||||||
|
.set_alignment_horizontal(Entity::Global, alignment);
|
||||||
|
self.styles.alignments.data = alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Crusial to be called before data changes (todo fix interface)
|
||||||
pub fn set_indent(&mut self, indent: TableIndent) {
|
pub fn set_indent(&mut self, indent: TableIndent) {
|
||||||
self.config.indent = indent;
|
self.config.indent = indent;
|
||||||
|
|
||||||
|
let pad = indent_sum(indent);
|
||||||
|
for w in &mut self.widths {
|
||||||
|
*w = pad;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_theme(&mut self, theme: TableTheme) {
|
pub fn set_theme(&mut self, theme: TableTheme) {
|
||||||
@ -180,7 +228,9 @@ impl NuTable {
|
|||||||
self.config.border_color = (!color.is_plain()).then_some(color);
|
self.config.border_color = (!color.is_plain()).then_some(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_records_mut(&mut self) -> &mut NuRecords {
|
// NOTE: BE CAREFUL TO KEEP WIDTH UNCHANGED
|
||||||
|
// TODO: fix interface
|
||||||
|
pub fn get_records_mut(&mut self) -> &mut [Vec<NuRecordsValue>] {
|
||||||
&mut self.data
|
&mut self.data
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,32 +244,42 @@ impl NuTable {
|
|||||||
/// Return a total table width.
|
/// Return a total table width.
|
||||||
pub fn total_width(&self) -> usize {
|
pub fn total_width(&self) -> usize {
|
||||||
let config = create_config(&self.config.theme, false, None);
|
let config = create_config(&self.config.theme, false, None);
|
||||||
let pad = indent_sum(self.config.indent);
|
get_total_width2(&self.widths, &config)
|
||||||
let widths = build_width(&self.data, pad);
|
|
||||||
get_total_width2(&widths, &config)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<Vec<Text<String>>>> for NuTable {
|
impl From<Vec<Vec<Text<String>>>> for NuTable {
|
||||||
fn from(value: Vec<Vec<Text<String>>>) -> Self {
|
fn from(value: Vec<Vec<Text<String>>>) -> Self {
|
||||||
let mut nutable = Self::new(0, 0);
|
let count_rows = value.len();
|
||||||
nutable.data = VecRecords::new(value);
|
let count_cols = if value.is_empty() { 0 } else { value[0].len() };
|
||||||
|
|
||||||
nutable
|
let mut t = Self::new(count_rows, count_cols);
|
||||||
|
t.data = value;
|
||||||
|
table_recalculate_widths(&mut t);
|
||||||
|
|
||||||
|
t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Alignments = CellConfiguration<AlignmentHorizontal>;
|
fn table_recalculate_widths(t: &mut NuTable) {
|
||||||
|
let pad = indent_sum(t.config.indent);
|
||||||
|
let records = IterRecords::new(&t.data, t.count_cols, Some(t.count_rows));
|
||||||
|
let widths = build_width(records, pad);
|
||||||
|
t.widths = widths;
|
||||||
|
}
|
||||||
|
|
||||||
type Styles = CellConfiguration<Color>;
|
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Hash)]
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
|
||||||
struct CellConfiguration<Value> {
|
struct CellConfiguration<Value> {
|
||||||
data: Value,
|
|
||||||
index: Value,
|
index: Value,
|
||||||
header: Value,
|
header: Value,
|
||||||
columns: HashMap<usize, Value>,
|
data: Value,
|
||||||
cells: HashMap<Position, Value>,
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
struct Styles {
|
||||||
|
cfg: ColoredConfig,
|
||||||
|
colors: CellConfiguration<Color>,
|
||||||
|
alignments: CellConfiguration<AlignmentHorizontal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -304,49 +364,67 @@ fn table_insert_footer_if(t: &mut NuTable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn table_truncate(t: &mut NuTable, termwidth: usize) -> Option<WidthEstimation> {
|
fn table_truncate(t: &mut NuTable, termwidth: usize) -> Option<WidthEstimation> {
|
||||||
let widths = maybe_truncate_columns(&mut t.data, &t.config, termwidth);
|
let widths = maybe_truncate_columns(&mut t.data, t.widths.clone(), &t.config, termwidth);
|
||||||
if widths.needed.is_empty() {
|
if widths.needed.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset style for last column which is a trail one
|
||||||
|
if widths.trail {
|
||||||
|
let col = widths.needed.len() - 1;
|
||||||
|
for row in 0..t.count_rows {
|
||||||
|
t.styles
|
||||||
|
.cfg
|
||||||
|
.set_alignment_horizontal(Entity::Cell(row, col), t.styles.alignments.data);
|
||||||
|
t.styles
|
||||||
|
.cfg
|
||||||
|
.set_color(Entity::Cell(row, col), ANSIBuf::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Some(widths)
|
Some(widths)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_header(t: &mut NuTable) -> HeadInfo {
|
fn remove_header(t: &mut NuTable) -> HeadInfo {
|
||||||
let head: Vec<String> = t
|
// move settings by one row down
|
||||||
|
for row in 1..t.data.len() {
|
||||||
|
for col in 0..t.count_cols {
|
||||||
|
let alignment = *t
|
||||||
|
.styles
|
||||||
|
.cfg
|
||||||
|
.get_alignment_horizontal(Entity::Cell(row, col));
|
||||||
|
if alignment != t.styles.alignments.data {
|
||||||
|
t.styles
|
||||||
|
.cfg
|
||||||
|
.set_alignment_horizontal(Entity::Cell(row - 1, col), alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: use get_color from upstream (when released)
|
||||||
|
let color = t.styles.cfg.get_colors().get_color((row, col)).cloned();
|
||||||
|
if let Some(color) = color {
|
||||||
|
t.styles.cfg.set_color(Entity::Cell(row - 1, col), color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let head = t
|
||||||
.data
|
.data
|
||||||
.remove(0)
|
.remove(0)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
let align = t.alignments.header;
|
|
||||||
let color = if is_color_empty(&t.styles.header) {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(t.styles.header.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
// move settings by one row down
|
// WE NEED TO RELCULATE WIDTH.
|
||||||
t.alignments.cells = t
|
// TODO: cause we have configuration beforehand we can just not calculate it in?
|
||||||
.alignments
|
table_recalculate_widths(t);
|
||||||
.cells
|
|
||||||
.drain()
|
|
||||||
.filter(|(k, _)| k.0 != 0)
|
|
||||||
.map(|(k, v)| ((k.0 - 1, k.1), v))
|
|
||||||
.collect();
|
|
||||||
t.alignments.header = AlignmentHorizontal::Center;
|
|
||||||
|
|
||||||
// move settings by one row down
|
let alignment = t.styles.alignments.header;
|
||||||
t.styles.cells = t
|
let color = get_color_if_exists(&t.styles.colors.header);
|
||||||
.styles
|
|
||||||
.cells
|
|
||||||
.drain()
|
|
||||||
.filter(|(k, _)| k.0 != 0)
|
|
||||||
.map(|(k, v)| ((k.0 - 1, k.1), v))
|
|
||||||
.collect();
|
|
||||||
t.styles.header = Color::empty();
|
|
||||||
|
|
||||||
HeadInfo::new(head, align, color)
|
t.styles.alignments.header = AlignmentHorizontal::Center;
|
||||||
|
t.styles.colors.header = Color::empty();
|
||||||
|
|
||||||
|
HeadInfo::new(head, alignment, color)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_table(
|
fn draw_table(
|
||||||
@ -359,19 +437,24 @@ fn draw_table(
|
|||||||
structure.with_footer = structure.with_footer && head.is_none();
|
structure.with_footer = structure.with_footer && head.is_none();
|
||||||
let sep_color = t.config.border_color;
|
let sep_color = t.config.border_color;
|
||||||
|
|
||||||
let data: Vec<Vec<_>> = t.data.into();
|
let data = t.data;
|
||||||
let mut table = Builder::from_vec(data).build();
|
let mut table = Builder::from_vec(data).build();
|
||||||
|
|
||||||
|
set_styles(&mut table, t.styles, &structure);
|
||||||
set_indent(&mut table, t.config.indent);
|
set_indent(&mut table, t.config.indent);
|
||||||
load_theme(&mut table, &t.config.theme, &structure, sep_color);
|
load_theme(&mut table, &t.config.theme, &structure, sep_color);
|
||||||
align_table(&mut table, t.alignments, &structure);
|
|
||||||
colorize_table(&mut table, t.styles, &structure);
|
|
||||||
truncate_table(&mut table, &t.config, width, termwidth);
|
truncate_table(&mut table, &t.config, width, termwidth);
|
||||||
table_set_border_header(&mut table, head, &t.config);
|
table_set_border_header(&mut table, head, &t.config);
|
||||||
|
|
||||||
table_to_string(table, termwidth)
|
table_to_string(table, termwidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_styles(table: &mut Table, styles: Styles, structure: &TableStructure) {
|
||||||
|
table.with(styles.cfg);
|
||||||
|
align_table(table, styles.alignments, structure);
|
||||||
|
colorize_table(table, styles.colors, structure);
|
||||||
|
}
|
||||||
|
|
||||||
fn table_set_border_header(table: &mut Table, head: Option<HeadInfo>, cfg: &TableConfig) {
|
fn table_set_border_header(table: &mut Table, head: Option<HeadInfo>, cfg: &TableConfig) {
|
||||||
let head = match head {
|
let head = match head {
|
||||||
Some(head) => head,
|
Some(head) => head,
|
||||||
@ -420,7 +503,6 @@ fn set_indent(table: &mut Table, indent: TableIndent) {
|
|||||||
|
|
||||||
fn table_to_string(table: Table, termwidth: usize) -> Option<String> {
|
fn table_to_string(table: Table, termwidth: usize) -> Option<String> {
|
||||||
let total_width = table.total_width();
|
let total_width = table.total_width();
|
||||||
|
|
||||||
if total_width > termwidth {
|
if total_width > termwidth {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -462,15 +544,23 @@ struct WidthEstimation {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
total: usize,
|
total: usize,
|
||||||
truncate: bool,
|
truncate: bool,
|
||||||
|
trail: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidthEstimation {
|
impl WidthEstimation {
|
||||||
fn new(original: Vec<usize>, needed: Vec<usize>, total: usize, truncate: bool) -> Self {
|
fn new(
|
||||||
|
original: Vec<usize>,
|
||||||
|
needed: Vec<usize>,
|
||||||
|
total: usize,
|
||||||
|
truncate: bool,
|
||||||
|
trail: bool,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
original,
|
original,
|
||||||
needed,
|
needed,
|
||||||
total,
|
total,
|
||||||
truncate,
|
truncate,
|
||||||
|
trail,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -546,17 +636,12 @@ fn width_ctrl_truncate(
|
|||||||
dims.set_widths(ctrl.width.needed);
|
dims.set_widths(ctrl.width.needed);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn align_table(table: &mut Table, alignments: Alignments, structure: &TableStructure) {
|
fn align_table(
|
||||||
|
table: &mut Table,
|
||||||
|
alignments: CellConfiguration<AlignmentHorizontal>,
|
||||||
|
structure: &TableStructure,
|
||||||
|
) {
|
||||||
table.with(AlignmentStrategy::PerLine);
|
table.with(AlignmentStrategy::PerLine);
|
||||||
table.with(Alignment::from(alignments.data));
|
|
||||||
|
|
||||||
for (column, alignment) in alignments.columns {
|
|
||||||
table.modify(Columns::single(column), Alignment::from(alignment));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (pos, alignment) in alignments.cells {
|
|
||||||
table.modify(pos, Alignment::from(alignment));
|
|
||||||
}
|
|
||||||
|
|
||||||
if structure.with_header {
|
if structure.with_header {
|
||||||
table.modify(Rows::first(), Alignment::from(alignments.header));
|
table.modify(Rows::first(), Alignment::from(alignments.header));
|
||||||
@ -571,23 +656,7 @@ fn align_table(table: &mut Table, alignments: Alignments, structure: &TableStruc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn colorize_table(table: &mut Table, styles: Styles, structure: &TableStructure) {
|
fn colorize_table(table: &mut Table, styles: CellConfiguration<Color>, structure: &TableStructure) {
|
||||||
if !is_color_empty(&styles.data) {
|
|
||||||
table.with(styles.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (column, color) in styles.columns {
|
|
||||||
if !is_color_empty(&color) {
|
|
||||||
table.modify(Columns::single(column), color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (pos, color) in styles.cells {
|
|
||||||
if !is_color_empty(&color) {
|
|
||||||
table.modify(pos, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if structure.with_index && !is_color_empty(&styles.index) {
|
if structure.with_index && !is_color_empty(&styles.index) {
|
||||||
table.modify(Columns::first(), styles.index);
|
table.modify(Columns::first(), styles.index);
|
||||||
}
|
}
|
||||||
@ -629,7 +698,8 @@ fn load_theme(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_truncate_columns(
|
fn maybe_truncate_columns(
|
||||||
data: &mut NuRecords,
|
data: &mut Vec<Vec<NuRecordsValue>>,
|
||||||
|
widths: Vec<usize>,
|
||||||
cfg: &TableConfig,
|
cfg: &TableConfig,
|
||||||
termwidth: usize,
|
termwidth: usize,
|
||||||
) -> WidthEstimation {
|
) -> WidthEstimation {
|
||||||
@ -639,15 +709,16 @@ fn maybe_truncate_columns(
|
|||||||
let preserve_content = termwidth > TERMWIDTH_THRESHOLD;
|
let preserve_content = termwidth > TERMWIDTH_THRESHOLD;
|
||||||
|
|
||||||
if preserve_content {
|
if preserve_content {
|
||||||
truncate_columns_by_columns(data, &cfg.theme, pad, termwidth)
|
truncate_columns_by_columns(data, widths, &cfg.theme, pad, termwidth)
|
||||||
} else {
|
} else {
|
||||||
truncate_columns_by_content(data, &cfg.theme, pad, termwidth)
|
truncate_columns_by_content(data, widths, &cfg.theme, pad, termwidth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VERSION where we are showing AS LITTLE COLUMNS AS POSSIBLE but WITH AS MUCH CONTENT AS POSSIBLE.
|
// VERSION where we are showing AS LITTLE COLUMNS AS POSSIBLE but WITH AS MUCH CONTENT AS POSSIBLE.
|
||||||
fn truncate_columns_by_content(
|
fn truncate_columns_by_content(
|
||||||
data: &mut NuRecords,
|
data: &mut Vec<Vec<NuRecordsValue>>,
|
||||||
|
widths: Vec<usize>,
|
||||||
theme: &TableTheme,
|
theme: &TableTheme,
|
||||||
pad: usize,
|
pad: usize,
|
||||||
termwidth: usize,
|
termwidth: usize,
|
||||||
@ -658,13 +729,14 @@ fn truncate_columns_by_content(
|
|||||||
let trailing_column_width = TRAILING_COLUMN_WIDTH + pad;
|
let trailing_column_width = TRAILING_COLUMN_WIDTH + pad;
|
||||||
let min_column_width = MIN_ACCEPTABLE_WIDTH + pad;
|
let min_column_width = MIN_ACCEPTABLE_WIDTH + pad;
|
||||||
|
|
||||||
|
let count_columns = data[0].len();
|
||||||
|
|
||||||
let config = create_config(theme, false, None);
|
let config = create_config(theme, false, None);
|
||||||
let widths_original = build_width(data, pad);
|
let widths_original = widths;
|
||||||
let mut widths = vec![];
|
let mut widths = vec![];
|
||||||
|
|
||||||
let borders = config.get_borders();
|
let borders = config.get_borders();
|
||||||
let vertical = borders.has_vertical() as usize;
|
let vertical = borders.has_vertical() as usize;
|
||||||
let count_columns = data.count_columns();
|
|
||||||
|
|
||||||
let mut width = borders.has_left() as usize + borders.has_right() as usize;
|
let mut width = borders.has_left() as usize + borders.has_right() as usize;
|
||||||
let mut truncate_pos = 0;
|
let mut truncate_pos = 0;
|
||||||
@ -685,7 +757,7 @@ fn truncate_columns_by_content(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if truncate_pos == count_columns {
|
if truncate_pos == count_columns {
|
||||||
return WidthEstimation::new(widths_original, widths, width, false);
|
return WidthEstimation::new(widths_original, widths, width, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if truncate_pos == 0 {
|
if truncate_pos == 0 {
|
||||||
@ -702,11 +774,11 @@ fn truncate_columns_by_content(
|
|||||||
widths.push(trailing_column_width);
|
widths.push(trailing_column_width);
|
||||||
width += trailing_column_width + vertical;
|
width += trailing_column_width + vertical;
|
||||||
|
|
||||||
return WidthEstimation::new(widths_original, widths, width, true);
|
return WidthEstimation::new(widths_original, widths, width, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return WidthEstimation::new(widths_original, widths, width, false);
|
return WidthEstimation::new(widths_original, widths, width, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let available = termwidth - width;
|
let available = termwidth - width;
|
||||||
@ -718,7 +790,7 @@ fn truncate_columns_by_content(
|
|||||||
widths.push(w);
|
widths.push(w);
|
||||||
width += w + vertical;
|
width += w + vertical;
|
||||||
|
|
||||||
return WidthEstimation::new(widths_original, widths, width, true);
|
return WidthEstimation::new(widths_original, widths, width, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// special case where the last column is smaller then a trailing column
|
// special case where the last column is smaller then a trailing column
|
||||||
@ -736,7 +808,7 @@ fn truncate_columns_by_content(
|
|||||||
widths.push(next_column_width);
|
widths.push(next_column_width);
|
||||||
width += next_column_width + vertical;
|
width += next_column_width + vertical;
|
||||||
|
|
||||||
return WidthEstimation::new(widths_original, widths, width, true);
|
return WidthEstimation::new(widths_original, widths, width, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -753,7 +825,7 @@ fn truncate_columns_by_content(
|
|||||||
widths.push(trailing_column_width);
|
widths.push(trailing_column_width);
|
||||||
width += trailing_column_width + vertical;
|
width += trailing_column_width + vertical;
|
||||||
|
|
||||||
return WidthEstimation::new(widths_original, widths, width, true);
|
return WidthEstimation::new(widths_original, widths, width, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if available >= trailing_column_width + vertical {
|
if available >= trailing_column_width + vertical {
|
||||||
@ -763,7 +835,7 @@ fn truncate_columns_by_content(
|
|||||||
widths.push(trailing_column_width);
|
widths.push(trailing_column_width);
|
||||||
width += trailing_column_width + vertical;
|
width += trailing_column_width + vertical;
|
||||||
|
|
||||||
return WidthEstimation::new(widths_original, widths, width, false);
|
return WidthEstimation::new(widths_original, widths, width, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let last_width = widths.last().cloned().expect("ok");
|
let last_width = widths.last().cloned().expect("ok");
|
||||||
@ -787,7 +859,7 @@ fn truncate_columns_by_content(
|
|||||||
widths.push(trailing_column_width);
|
widths.push(trailing_column_width);
|
||||||
width += trailing_column_width + vertical;
|
width += trailing_column_width + vertical;
|
||||||
|
|
||||||
return WidthEstimation::new(widths_original, widths, width, true);
|
return WidthEstimation::new(widths_original, widths, width, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,10 +873,10 @@ fn truncate_columns_by_content(
|
|||||||
|
|
||||||
if widths.len() == 1 {
|
if widths.len() == 1 {
|
||||||
// nothing to show anyhow
|
// nothing to show anyhow
|
||||||
return WidthEstimation::new(widths_original, vec![], width, false);
|
return WidthEstimation::new(widths_original, vec![], width, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
WidthEstimation::new(widths_original, widths, width, false)
|
WidthEstimation::new(widths_original, widths, width, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VERSION where we are showing AS MANY COLUMNS AS POSSIBLE but as a side affect they MIGHT CONTAIN AS LITTLE CONTENT AS POSSIBLE
|
// VERSION where we are showing AS MANY COLUMNS AS POSSIBLE but as a side affect they MIGHT CONTAIN AS LITTLE CONTENT AS POSSIBLE
|
||||||
@ -818,7 +890,8 @@ fn truncate_columns_by_content(
|
|||||||
// Point being of the column needs more space we do can give it a little more based on it's distance from the start.
|
// Point being of the column needs more space we do can give it a little more based on it's distance from the start.
|
||||||
// Percentage wise.
|
// Percentage wise.
|
||||||
fn truncate_columns_by_columns(
|
fn truncate_columns_by_columns(
|
||||||
data: &mut NuRecords,
|
data: &mut Vec<Vec<NuRecordsValue>>,
|
||||||
|
widths: Vec<usize>,
|
||||||
theme: &TableTheme,
|
theme: &TableTheme,
|
||||||
pad: usize,
|
pad: usize,
|
||||||
termwidth: usize,
|
termwidth: usize,
|
||||||
@ -829,13 +902,14 @@ fn truncate_columns_by_columns(
|
|||||||
let trailing_column_width = TRAILING_COLUMN_WIDTH + pad;
|
let trailing_column_width = TRAILING_COLUMN_WIDTH + pad;
|
||||||
let min_column_width = MIN_ACCEPTABLE_WIDTH + pad;
|
let min_column_width = MIN_ACCEPTABLE_WIDTH + pad;
|
||||||
|
|
||||||
|
let count_columns = data[0].len();
|
||||||
|
|
||||||
let config = create_config(theme, false, None);
|
let config = create_config(theme, false, None);
|
||||||
let widths_original = build_width(data, pad);
|
let widths_original = widths;
|
||||||
let mut widths = vec![];
|
let mut widths = vec![];
|
||||||
|
|
||||||
let borders = config.get_borders();
|
let borders = config.get_borders();
|
||||||
let vertical = borders.has_vertical() as usize;
|
let vertical = borders.has_vertical() as usize;
|
||||||
let count_columns = data.count_columns();
|
|
||||||
|
|
||||||
let mut width = borders.has_left() as usize + borders.has_right() as usize;
|
let mut width = borders.has_left() as usize + borders.has_right() as usize;
|
||||||
let mut truncate_pos = 0;
|
let mut truncate_pos = 0;
|
||||||
@ -857,7 +931,7 @@ fn truncate_columns_by_columns(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if truncate_pos == 0 {
|
if truncate_pos == 0 {
|
||||||
return WidthEstimation::new(widths_original, widths, width, false);
|
return WidthEstimation::new(widths_original, widths, width, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut available = termwidth - width;
|
let mut available = termwidth - width;
|
||||||
@ -882,7 +956,7 @@ fn truncate_columns_by_columns(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if truncate_pos == count_columns {
|
if truncate_pos == count_columns {
|
||||||
return WidthEstimation::new(widths_original, widths, width, true);
|
return WidthEstimation::new(widths_original, widths, width, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if available >= trailing_column_width + vertical {
|
if available >= trailing_column_width + vertical {
|
||||||
@ -892,7 +966,7 @@ fn truncate_columns_by_columns(
|
|||||||
widths.push(trailing_column_width);
|
widths.push(trailing_column_width);
|
||||||
width += trailing_column_width + vertical;
|
width += trailing_column_width + vertical;
|
||||||
|
|
||||||
return WidthEstimation::new(widths_original, widths, width, true);
|
return WidthEstimation::new(widths_original, widths, width, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
truncate_rows(data, truncate_pos - 1);
|
truncate_rows(data, truncate_pos - 1);
|
||||||
@ -903,7 +977,7 @@ fn truncate_columns_by_columns(
|
|||||||
widths.push(trailing_column_width);
|
widths.push(trailing_column_width);
|
||||||
width += trailing_column_width;
|
width += trailing_column_width;
|
||||||
|
|
||||||
WidthEstimation::new(widths_original, widths, width, true)
|
WidthEstimation::new(widths_original, widths, width, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_total_width2(widths: &[usize], cfg: &ColoredConfig) -> usize {
|
fn get_total_width2(widths: &[usize], cfg: &ColoredConfig) -> usize {
|
||||||
@ -921,37 +995,22 @@ fn create_config(theme: &TableTheme, with_header: bool, color: Option<Style>) ->
|
|||||||
table.get_config().clone()
|
table.get_config().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_empty_column(data: &mut NuRecords) {
|
fn push_empty_column(data: &mut Vec<Vec<NuRecordsValue>>) {
|
||||||
let records = std::mem::take(data);
|
|
||||||
let mut inner: Vec<Vec<_>> = records.into();
|
|
||||||
|
|
||||||
let empty_cell = Text::new(String::from(EMPTY_COLUMN_TEXT));
|
let empty_cell = Text::new(String::from(EMPTY_COLUMN_TEXT));
|
||||||
for row in &mut inner {
|
for row in data {
|
||||||
row.push(empty_cell.clone());
|
row.push(empty_cell.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
*data = VecRecords::new(inner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn duplicate_row(data: &mut NuRecords, row: usize) {
|
fn duplicate_row(data: &mut Vec<Vec<NuRecordsValue>>, row: usize) {
|
||||||
let records = std::mem::take(data);
|
let duplicate = data[row].clone();
|
||||||
let mut inner: Vec<Vec<_>> = records.into();
|
data.push(duplicate);
|
||||||
|
|
||||||
let duplicate = inner[row].clone();
|
|
||||||
inner.push(duplicate);
|
|
||||||
|
|
||||||
*data = VecRecords::new(inner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn truncate_rows(data: &mut NuRecords, count: usize) {
|
fn truncate_rows(data: &mut Vec<Vec<NuRecordsValue>>, count: usize) {
|
||||||
let records = std::mem::take(data);
|
for row in data {
|
||||||
let mut inner: Vec<Vec<_>> = records.into();
|
|
||||||
|
|
||||||
for row in &mut inner {
|
|
||||||
row.truncate(count);
|
row.truncate(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
*data = VecRecords::new(inner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_alignment(alignment: nu_color_config::Alignment) -> AlignmentHorizontal {
|
fn convert_alignment(alignment: nu_color_config::Alignment) -> AlignmentHorizontal {
|
||||||
@ -971,7 +1030,11 @@ impl<R> TableOption<R, ColoredConfig, CompleteDimensionVecRecords<'_>> for SetDi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_width(records: &NuRecords, pad: usize) -> Vec<usize> {
|
fn build_width<R>(records: R, pad: usize) -> Vec<usize>
|
||||||
|
where
|
||||||
|
R: Records,
|
||||||
|
<R::Iter as IntoRecords>::Cell: AsRef<str>,
|
||||||
|
{
|
||||||
// TODO: Expose not spaned version (could be optimized).
|
// TODO: Expose not spaned version (could be optimized).
|
||||||
let mut cfg = SpannedConfig::default();
|
let mut cfg = SpannedConfig::default();
|
||||||
let padding = Sides {
|
let padding = Sides {
|
||||||
@ -981,6 +1044,7 @@ fn build_width(records: &NuRecords, pad: usize) -> Vec<usize> {
|
|||||||
|
|
||||||
cfg.set_padding(Entity::Global, padding);
|
cfg.set_padding(Entity::Global, padding);
|
||||||
|
|
||||||
|
// TODO: Use peekable width
|
||||||
SpannedGridDimension::width(records, &cfg)
|
SpannedGridDimension::width(records, &cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1059,3 +1123,11 @@ impl<R, C> TableOption<R, C, CompleteDimensionVecRecords<'_>> for &mut GetDims {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_color_if_exists(c: &Color) -> Option<Color> {
|
||||||
|
if !is_color_empty(c) {
|
||||||
|
Some(c.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
use std::{cmp::max, collections::HashMap};
|
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::{
|
||||||
check_value, configure_table, error_sign, get_header_style, get_index_style, load_theme,
|
check_value, configure_table, error_sign, get_header_style, get_index_style, load_theme,
|
||||||
@ -14,7 +12,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
string_width,
|
string_width,
|
||||||
types::has_index,
|
types::has_index,
|
||||||
NuRecordsValue, NuTable, TableOpts, TableOutput,
|
NuTable, TableOpts, TableOutput,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -106,7 +104,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
|||||||
const PADDING_SPACE: usize = 2;
|
const PADDING_SPACE: usize = 2;
|
||||||
const SPLIT_LINE_SPACE: usize = 1;
|
const SPLIT_LINE_SPACE: usize = 1;
|
||||||
const ADDITIONAL_CELL_SPACE: usize = PADDING_SPACE + SPLIT_LINE_SPACE;
|
const ADDITIONAL_CELL_SPACE: usize = PADDING_SPACE + SPLIT_LINE_SPACE;
|
||||||
const MIN_CELL_CONTENT_WIDTH: usize = 1;
|
const MIN_CELL_CONTENT_WIDTH: usize = 3;
|
||||||
const TRUNCATE_CONTENT_WIDTH: usize = 3;
|
const TRUNCATE_CONTENT_WIDTH: usize = 3;
|
||||||
const TRUNCATE_CELL_WIDTH: usize = TRUNCATE_CONTENT_WIDTH + PADDING_SPACE;
|
const TRUNCATE_CELL_WIDTH: usize = TRUNCATE_CONTENT_WIDTH + PADDING_SPACE;
|
||||||
|
|
||||||
@ -124,10 +122,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let headers = get_columns(input);
|
let headers = get_columns(input);
|
||||||
|
|
||||||
let with_index = has_index(&cfg.opts, &headers);
|
let with_index = has_index(&cfg.opts, &headers);
|
||||||
let row_offset = cfg.opts.index_offset;
|
|
||||||
let mut rows_count = 0usize;
|
|
||||||
|
|
||||||
// The header with the INDEX is removed from the table headers since
|
// The header with the INDEX is removed from the table headers since
|
||||||
// it is added to the natural table index
|
// it is added to the natural table index
|
||||||
@ -135,162 +130,171 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|header| header != INDEX_COLUMN_NAME)
|
.filter(|header| header != INDEX_COLUMN_NAME)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let with_header = !headers.is_empty();
|
let with_header = !headers.is_empty();
|
||||||
|
let row_offset = cfg.opts.index_offset;
|
||||||
|
|
||||||
let mut data = vec![vec![]; input.len() + with_header as usize];
|
let mut total_rows = 0usize;
|
||||||
let mut data_styles = HashMap::new();
|
|
||||||
|
|
||||||
if with_index {
|
if !with_index && !with_header {
|
||||||
if with_header {
|
if available_width <= ADDITIONAL_CELL_SPACE {
|
||||||
data[0].push(NuRecordsValue::exact(String::from("#"), 1, vec![]));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
|
||||||
cfg.opts.signals.check(cfg.opts.span)?;
|
|
||||||
check_value(item)?;
|
|
||||||
|
|
||||||
let index = row + row_offset;
|
|
||||||
let text = item
|
|
||||||
.as_record()
|
|
||||||
.ok()
|
|
||||||
.and_then(|val| val.get(INDEX_COLUMN_NAME))
|
|
||||||
.map(|value| value.to_expanded_string("", cfg.opts.config))
|
|
||||||
.unwrap_or_else(|| index.to_string());
|
|
||||||
|
|
||||||
let row = row + with_header as usize;
|
|
||||||
let value = NuRecordsValue::new(text);
|
|
||||||
data[row].push(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
let column_width = string_width(data[data.len() - 1][0].as_ref());
|
|
||||||
|
|
||||||
if column_width + ADDITIONAL_CELL_SPACE > available_width {
|
|
||||||
available_width = 0;
|
|
||||||
} else {
|
|
||||||
available_width -= column_width + ADDITIONAL_CELL_SPACE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !with_header {
|
|
||||||
if available_width > ADDITIONAL_CELL_SPACE {
|
|
||||||
available_width -= PADDING_SPACE;
|
|
||||||
} else {
|
|
||||||
// it means we have no space left for actual content;
|
// it means we have no space left for actual content;
|
||||||
// which means there's no point in index itself if it was even used.
|
// which means there's no point in index itself if it was even used.
|
||||||
// so we do not print it.
|
// so we do not print it.
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
available_width -= PADDING_SPACE;
|
||||||
|
|
||||||
|
let mut table = NuTable::new(input.len(), 1);
|
||||||
|
table.set_index_style(get_index_style(&cfg.opts.style_computer));
|
||||||
|
table.set_header_style(get_header_style(&cfg.opts.style_computer));
|
||||||
|
table.set_indent(cfg.opts.config.table.padding);
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
for (row, item) in input.iter().enumerate() {
|
||||||
cfg.opts.signals.check(cfg.opts.span)?;
|
cfg.opts.signals.check(cfg.opts.span)?;
|
||||||
check_value(item)?;
|
check_value(item)?;
|
||||||
|
|
||||||
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width);
|
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width);
|
||||||
let mut cell = expand_entry(item, inner_cfg);
|
let cell = expand_entry(item, inner_cfg);
|
||||||
|
|
||||||
let value_width = string_width(&cell.text);
|
table.insert((row, 0), cell.text);
|
||||||
if value_width > available_width {
|
table.insert_style((row, 0), cell.style);
|
||||||
// it must only happen when a string is produced, so we can safely wrap it.
|
|
||||||
// (it might be string table representation as well) (I guess I mean default { table ...} { list ...})
|
|
||||||
//
|
|
||||||
// todo: Maybe convert_to_table2_entry could do for strings to not mess caller code?
|
|
||||||
|
|
||||||
cell.text = wrap_text(&cell.text, available_width, cfg.opts.config);
|
total_rows = total_rows.saturating_add(cell.size);
|
||||||
}
|
|
||||||
|
|
||||||
let value = NuRecordsValue::new(cell.text);
|
|
||||||
data[row].push(value);
|
|
||||||
data_styles.insert((row, with_index as usize), cell.style);
|
|
||||||
|
|
||||||
rows_count = rows_count.saturating_add(cell.size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut table = NuTable::from(data);
|
return Ok(Some(TableOutput::new(table, false, false, total_rows)));
|
||||||
table.set_indent(cfg.opts.config.table.padding);
|
|
||||||
table.set_index_style(get_index_style(&cfg.opts.style_computer));
|
|
||||||
set_data_styles(&mut table, data_styles);
|
|
||||||
|
|
||||||
return Ok(Some(TableOutput::new(table, false, with_index, rows_count)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !headers.is_empty() {
|
if !with_header && with_index {
|
||||||
let mut pad_space = PADDING_SPACE;
|
let mut table = NuTable::new(input.len(), 2);
|
||||||
if headers.len() > 1 {
|
table.set_index_style(get_index_style(&cfg.opts.style_computer));
|
||||||
pad_space += SPLIT_LINE_SPACE;
|
table.set_header_style(get_header_style(&cfg.opts.style_computer));
|
||||||
|
table.set_indent(cfg.opts.config.table.padding);
|
||||||
|
|
||||||
|
let mut index_column_width = 0;
|
||||||
|
|
||||||
|
for (row, item) in input.iter().enumerate() {
|
||||||
|
cfg.opts.signals.check(cfg.opts.span)?;
|
||||||
|
check_value(item)?;
|
||||||
|
|
||||||
|
let index = row + row_offset;
|
||||||
|
let index_value = item
|
||||||
|
.as_record()
|
||||||
|
.ok()
|
||||||
|
.and_then(|val| val.get(INDEX_COLUMN_NAME))
|
||||||
|
.map(|value| value.to_expanded_string("", cfg.opts.config))
|
||||||
|
.unwrap_or_else(|| index.to_string());
|
||||||
|
let index_width = string_width(&index_value);
|
||||||
|
if available_width <= index_width + ADDITIONAL_CELL_SPACE + PADDING_SPACE {
|
||||||
|
// NOTE: we don't wanna wrap index; so we return
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.insert((row, 0), index_value);
|
||||||
|
|
||||||
|
index_column_width = max(index_column_width, index_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
if available_width < pad_space {
|
available_width -= index_column_width + ADDITIONAL_CELL_SPACE + PADDING_SPACE;
|
||||||
// there's no space for actual data so we don't return index if it's present.
|
|
||||||
// (also see the comment after the loop)
|
|
||||||
|
|
||||||
|
for (row, item) in input.iter().enumerate() {
|
||||||
|
cfg.opts.signals.check(cfg.opts.span)?;
|
||||||
|
check_value(item)?;
|
||||||
|
|
||||||
|
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width);
|
||||||
|
let cell = expand_entry(item, inner_cfg);
|
||||||
|
|
||||||
|
table.insert((row, 1), cell.text);
|
||||||
|
table.insert_style((row, 1), cell.style);
|
||||||
|
|
||||||
|
total_rows = total_rows.saturating_add(cell.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(Some(TableOutput::new(table, false, true, total_rows)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: redefine to not break above logic (fixme)
|
||||||
|
let mut available_width = cfg.opts.width - SPLIT_LINE_SPACE;
|
||||||
|
|
||||||
|
let mut table = NuTable::new(input.len() + 1, headers.len() + with_index as usize);
|
||||||
|
table.set_index_style(get_index_style(&cfg.opts.style_computer));
|
||||||
|
table.set_header_style(get_header_style(&cfg.opts.style_computer));
|
||||||
|
table.set_indent(cfg.opts.config.table.padding);
|
||||||
|
|
||||||
|
let mut widths = Vec::new();
|
||||||
|
|
||||||
|
if with_index {
|
||||||
|
table.insert((0, 0), String::from("#"));
|
||||||
|
|
||||||
|
let mut index_column_width = 1;
|
||||||
|
|
||||||
|
for (row, item) in input.iter().enumerate() {
|
||||||
|
cfg.opts.signals.check(cfg.opts.span)?;
|
||||||
|
check_value(item)?;
|
||||||
|
|
||||||
|
let index = row + row_offset;
|
||||||
|
let index_value = item
|
||||||
|
.as_record()
|
||||||
|
.ok()
|
||||||
|
.and_then(|val| val.get(INDEX_COLUMN_NAME))
|
||||||
|
.map(|value| value.to_expanded_string("", cfg.opts.config))
|
||||||
|
.unwrap_or_else(|| index.to_string());
|
||||||
|
let index_width = string_width(&index_value);
|
||||||
|
|
||||||
|
table.insert((row + 1, 0), index_value);
|
||||||
|
index_column_width = max(index_column_width, index_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
if available_width <= index_column_width + ADDITIONAL_CELL_SPACE {
|
||||||
|
// NOTE: we don't wanna wrap index; so we return
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
available_width -= index_column_width + ADDITIONAL_CELL_SPACE;
|
||||||
|
widths.push(index_column_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
let count_columns = headers.len();
|
let count_columns = headers.len();
|
||||||
let mut widths = Vec::new();
|
|
||||||
let mut truncate = false;
|
let mut truncate = false;
|
||||||
let mut rendered_column = 0;
|
let mut rendered_column = 0;
|
||||||
for (col, header) in headers.into_iter().enumerate() {
|
for (col, header) in headers.into_iter().enumerate() {
|
||||||
|
let column = col + with_index as usize;
|
||||||
|
let extra_space = PADDING_SPACE + SPLIT_LINE_SPACE;
|
||||||
|
|
||||||
|
if available_width <= extra_space {
|
||||||
|
table.pop_column(table.count_columns() - column);
|
||||||
|
widths.pop();
|
||||||
|
truncate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut available = available_width - extra_space;
|
||||||
|
|
||||||
|
// We want to reserver some space for next column
|
||||||
|
// If we can't fit it in it will be popped anyhow.
|
||||||
let is_last_column = col + 1 == count_columns;
|
let is_last_column = col + 1 == count_columns;
|
||||||
let mut pad_space = PADDING_SPACE;
|
if !is_last_column && available > TRUNCATE_CELL_WIDTH {
|
||||||
if !is_last_column {
|
available -= TRUNCATE_CELL_WIDTH;
|
||||||
pad_space += SPLIT_LINE_SPACE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut available = available_width - pad_space;
|
let mut total_column_rows = 0usize;
|
||||||
let mut column_width = 0;
|
let mut column_width = 0;
|
||||||
|
|
||||||
if !is_last_column {
|
|
||||||
// we need to make sure that we have a space for a next column if we use available width
|
|
||||||
// so we might need to decrease a bit it.
|
|
||||||
|
|
||||||
// we consider a header width be a minimum width
|
|
||||||
let pad_space = PADDING_SPACE + TRUNCATE_CONTENT_WIDTH;
|
|
||||||
|
|
||||||
if available > pad_space {
|
|
||||||
// In we have no space for a next column,
|
|
||||||
// We consider showing something better then nothing,
|
|
||||||
// So we try to decrease the width to show at least a truncution column
|
|
||||||
|
|
||||||
available -= pad_space;
|
|
||||||
} else {
|
|
||||||
truncate = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if available < column_width {
|
|
||||||
truncate = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut column_rows = 0usize;
|
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
for (row, item) in input.iter().enumerate() {
|
||||||
cfg.opts.signals.check(cfg.opts.span)?;
|
cfg.opts.signals.check(cfg.opts.span)?;
|
||||||
check_value(item)?;
|
check_value(item)?;
|
||||||
|
|
||||||
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available);
|
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available);
|
||||||
let mut cell = expand_entry_with_header(item, &header, inner_cfg);
|
let cell = expand_entry_with_header(item, &header, inner_cfg);
|
||||||
|
let value_width = string_width(&cell.text); // TODO: optimize cause when we expand we alrready know the width (most of the time or all)
|
||||||
let mut value_width = string_width(&cell.text);
|
|
||||||
if value_width > available {
|
|
||||||
// it must only happen when a string is produced, so we can safely wrap it.
|
|
||||||
// (it might be string table representation as well)
|
|
||||||
|
|
||||||
cell.text = wrap_text(&cell.text, available, cfg.opts.config);
|
|
||||||
value_width = available;
|
|
||||||
}
|
|
||||||
|
|
||||||
column_width = max(column_width, value_width);
|
column_width = max(column_width, value_width);
|
||||||
|
|
||||||
let value = NuRecordsValue::new(cell.text);
|
table.insert((row + 1, column), cell.text);
|
||||||
data[row + 1].push(value);
|
table.insert_style((row + 1, column), cell.style);
|
||||||
data_styles.insert((row + 1, col + with_index as usize), cell.style);
|
|
||||||
|
|
||||||
column_rows = column_rows.saturating_add(cell.size);
|
total_column_rows = total_column_rows.saturating_add(cell.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut head_width = string_width(&header);
|
let mut head_width = string_width(&header);
|
||||||
@ -300,50 +304,37 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
|||||||
head_width = available;
|
head_width = available;
|
||||||
}
|
}
|
||||||
|
|
||||||
let head_cell = NuRecordsValue::new(header);
|
table.insert((0, column), header);
|
||||||
data[0].push(head_cell);
|
|
||||||
|
|
||||||
column_width = max(column_width, head_width);
|
column_width = max(column_width, head_width);
|
||||||
|
assert!(column_width <= available);
|
||||||
if column_width > available {
|
|
||||||
// remove the column we just inserted
|
|
||||||
for row in &mut data {
|
|
||||||
row.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
truncate = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
widths.push(column_width);
|
widths.push(column_width);
|
||||||
|
|
||||||
available_width -= pad_space + column_width;
|
available_width -= column_width + extra_space;
|
||||||
rendered_column += 1;
|
rendered_column += 1;
|
||||||
|
|
||||||
rows_count = std::cmp::max(rows_count, column_rows);
|
total_rows = std::cmp::max(total_rows, total_column_rows);
|
||||||
}
|
|
||||||
|
|
||||||
if truncate && rendered_column == 0 {
|
|
||||||
// it means that no actual data was rendered, there might be only index present,
|
|
||||||
// so there's no point in rendering the table.
|
|
||||||
//
|
|
||||||
// It's actually quite important in case it's called recursively,
|
|
||||||
// cause we will back up to the basic table view as a string e.g. '[table 123 columns]'.
|
|
||||||
//
|
|
||||||
// But potentially if its reached as a 1st called function we might would love to see the index.
|
|
||||||
|
|
||||||
return Ok(None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if truncate {
|
if truncate {
|
||||||
|
if rendered_column == 0 {
|
||||||
|
// it means that no actual data was rendered, there might be only index present,
|
||||||
|
// so there's no point in rendering the table.
|
||||||
|
//
|
||||||
|
// It's actually quite important in case it's called recursively,
|
||||||
|
// cause we will back up to the basic table view as a string e.g. '[table 123 columns]'.
|
||||||
|
//
|
||||||
|
// But potentially if its reached as a 1st called function we might would love to see the index.
|
||||||
|
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
if available_width < TRUNCATE_CELL_WIDTH {
|
if available_width < TRUNCATE_CELL_WIDTH {
|
||||||
// back up by removing last column.
|
// back up by removing last column.
|
||||||
// it's LIKELY that removing only 1 column will leave us enough space for a shift column.
|
// it's LIKELY that removing only 1 column will leave us enough space for a shift column.
|
||||||
|
|
||||||
while let Some(width) = widths.pop() {
|
while let Some(width) = widths.pop() {
|
||||||
for row in &mut data {
|
table.pop_column(1);
|
||||||
row.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
available_width += width + PADDING_SPACE;
|
available_width += width + PADDING_SPACE;
|
||||||
if !widths.is_empty() {
|
if !widths.is_empty() {
|
||||||
@ -364,22 +355,12 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
|||||||
|
|
||||||
let is_last_column = widths.len() == count_columns;
|
let is_last_column = widths.len() == count_columns;
|
||||||
if !is_last_column {
|
if !is_last_column {
|
||||||
let shift = NuRecordsValue::exact(String::from("..."), 3, vec![]);
|
table.push_column(String::from("..."));
|
||||||
for row in &mut data {
|
|
||||||
row.push(shift.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
widths.push(3);
|
widths.push(3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut table = NuTable::from(data);
|
Ok(Some(TableOutput::new(table, true, with_index, total_rows)))
|
||||||
table.set_index_style(get_index_style(&cfg.opts.style_computer));
|
|
||||||
table.set_header_style(get_header_style(&cfg.opts.style_computer));
|
|
||||||
table.set_indent(cfg.opts.config.table.padding);
|
|
||||||
set_data_styles(&mut table, data_styles);
|
|
||||||
|
|
||||||
Ok(Some(TableOutput::new(table, true, with_index, rows_count)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> CellResult {
|
fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> CellResult {
|
||||||
@ -400,10 +381,13 @@ fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> CellResult {
|
|||||||
|
|
||||||
let value_width = cfg.opts.width - key_width - count_borders - padding - padding;
|
let value_width = cfg.opts.width - key_width - count_borders - padding - padding;
|
||||||
|
|
||||||
let mut count_rows = 0usize;
|
let mut total_rows = 0usize;
|
||||||
|
|
||||||
let mut data = Vec::with_capacity(record.len());
|
let mut table = NuTable::new(record.len(), 2);
|
||||||
for (key, value) in record {
|
table.set_index_style(get_key_style(&cfg));
|
||||||
|
table.set_indent(cfg.opts.config.table.padding);
|
||||||
|
|
||||||
|
for (i, (key, value)) in record.iter().enumerate() {
|
||||||
cfg.opts.signals.check(cfg.opts.span)?;
|
cfg.opts.signals.check(cfg.opts.span)?;
|
||||||
|
|
||||||
let cell = match expand_value(value, value_width, &cfg)? {
|
let cell = match expand_value(value, value_width, &cfg)? {
|
||||||
@ -411,29 +395,24 @@ fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> CellResult {
|
|||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let value = cell.text;
|
||||||
|
let mut key = key.to_owned();
|
||||||
|
|
||||||
// we want to have a key being aligned to 2nd line,
|
// we want to have a key being aligned to 2nd line,
|
||||||
// we could use Padding for it but,
|
// we could use Padding for it but,
|
||||||
// the easiest way to do so is just push a new_line char before
|
// the easiest way to do so is just push a new_line char before
|
||||||
let mut key = key.to_owned();
|
|
||||||
let is_key_on_next_line = !key.is_empty() && cell.is_expanded && theme.borders_has_top();
|
let is_key_on_next_line = !key.is_empty() && cell.is_expanded && theme.borders_has_top();
|
||||||
if is_key_on_next_line {
|
if is_key_on_next_line {
|
||||||
key.insert(0, '\n');
|
key.insert(0, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = NuRecordsValue::new(key);
|
table.insert((i, 0), key);
|
||||||
let val = NuRecordsValue::new(cell.text);
|
table.insert((i, 1), value);
|
||||||
let row = vec![key, val];
|
|
||||||
|
|
||||||
data.push(row);
|
total_rows = total_rows.saturating_add(cell.size);
|
||||||
|
|
||||||
count_rows = count_rows.saturating_add(cell.size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut table = NuTable::from(data);
|
let mut out = TableOutput::new(table, false, true, total_rows);
|
||||||
table.set_index_style(get_key_style(&cfg));
|
|
||||||
table.set_indent(cfg.opts.config.table.padding);
|
|
||||||
|
|
||||||
let mut out = TableOutput::new(table, false, true, count_rows);
|
|
||||||
|
|
||||||
configure_table(
|
configure_table(
|
||||||
&mut out,
|
&mut out,
|
||||||
@ -443,7 +422,7 @@ fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> CellResult {
|
|||||||
);
|
);
|
||||||
|
|
||||||
maybe_expand_table(out, cfg.opts.width)
|
maybe_expand_table(out, cfg.opts.width)
|
||||||
.map(|value| value.map(|value| CellOutput::clean(value, count_rows, false)))
|
.map(|value| value.map(|value| CellOutput::clean(value, total_rows, false)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// the flag is used as an optimization to not do `value.lines().count()` search.
|
// the flag is used as an optimization to not do `value.lines().count()` search.
|
||||||
@ -519,6 +498,7 @@ fn expand_entry_with_header(item: &Value, header: &str, cfg: Cfg<'_>) -> CellOut
|
|||||||
fn expand_entry(item: &Value, cfg: Cfg<'_>) -> CellOutput {
|
fn expand_entry(item: &Value, cfg: Cfg<'_>) -> CellOutput {
|
||||||
if is_limit_reached(&cfg) {
|
if is_limit_reached(&cfg) {
|
||||||
let value = nu_value_to_string_clean(item, cfg.opts.config, &cfg.opts.style_computer);
|
let value = nu_value_to_string_clean(item, cfg.opts.config, &cfg.opts.style_computer);
|
||||||
|
let value = nutext_wrap(value, &cfg);
|
||||||
return CellOutput::styled(value);
|
return CellOutput::styled(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,6 +507,7 @@ fn expand_entry(item: &Value, cfg: Cfg<'_>) -> CellOutput {
|
|||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
if record.is_empty() {
|
if record.is_empty() {
|
||||||
let value = nu_value_to_string(item, cfg.opts.config, &cfg.opts.style_computer);
|
let value = nu_value_to_string(item, cfg.opts.config, &cfg.opts.style_computer);
|
||||||
|
let value = nutext_wrap(value, &cfg);
|
||||||
return CellOutput::styled(value);
|
return CellOutput::styled(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,6 +519,7 @@ fn expand_entry(item: &Value, cfg: Cfg<'_>) -> CellOutput {
|
|||||||
Ok(Some(table)) => table,
|
Ok(Some(table)) => table,
|
||||||
_ => {
|
_ => {
|
||||||
let value = nu_value_to_string(item, cfg.opts.config, &cfg.opts.style_computer);
|
let value = nu_value_to_string(item, cfg.opts.config, &cfg.opts.style_computer);
|
||||||
|
let value = nutext_wrap(value, &cfg);
|
||||||
CellOutput::styled(value)
|
CellOutput::styled(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -560,6 +542,7 @@ fn expand_entry(item: &Value, cfg: Cfg<'_>) -> CellOutput {
|
|||||||
Ok(Some(out)) => out,
|
Ok(Some(out)) => out,
|
||||||
_ => {
|
_ => {
|
||||||
let value = nu_value_to_string(item, cfg.opts.config, &cfg.opts.style_computer);
|
let value = nu_value_to_string(item, cfg.opts.config, &cfg.opts.style_computer);
|
||||||
|
let value = nutext_wrap(value, &cfg);
|
||||||
return CellOutput::styled(value);
|
return CellOutput::styled(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -571,17 +554,28 @@ fn expand_entry(item: &Value, cfg: Cfg<'_>) -> CellOutput {
|
|||||||
Some(table) => CellOutput::clean(table, out.count_rows, false),
|
Some(table) => CellOutput::clean(table, out.count_rows, false),
|
||||||
None => {
|
None => {
|
||||||
let value = nu_value_to_string(item, cfg.opts.config, &cfg.opts.style_computer);
|
let value = nu_value_to_string(item, cfg.opts.config, &cfg.opts.style_computer);
|
||||||
|
let value = nutext_wrap(value, &cfg);
|
||||||
CellOutput::styled(value)
|
CellOutput::styled(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let value = nu_value_to_string_clean(item, cfg.opts.config, &cfg.opts.style_computer);
|
let value = nu_value_to_string_clean(item, cfg.opts.config, &cfg.opts.style_computer);
|
||||||
|
let value = nutext_wrap(value, &cfg);
|
||||||
CellOutput::styled(value)
|
CellOutput::styled(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn nutext_wrap(mut text: NuText, cfg: &Cfg<'_>) -> NuText {
|
||||||
|
let width = string_width(&text.0);
|
||||||
|
if width > cfg.opts.width {
|
||||||
|
text.0 = wrap_text(&text.0, cfg.opts.width, cfg.opts.config);
|
||||||
|
}
|
||||||
|
|
||||||
|
text
|
||||||
|
}
|
||||||
|
|
||||||
fn is_limit_reached(cfg: &Cfg<'_>) -> bool {
|
fn is_limit_reached(cfg: &Cfg<'_>) -> bool {
|
||||||
matches!(cfg.format.expand_limit, Some(0))
|
matches!(cfg.format.expand_limit, Some(0))
|
||||||
}
|
}
|
||||||
@ -626,12 +620,6 @@ fn maybe_expand_table(mut out: TableOutput, term_width: usize) -> StringResult {
|
|||||||
Ok(table)
|
Ok(table)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_data_styles(table: &mut NuTable, styles: HashMap<Position, TextStyle>) {
|
|
||||||
for (pos, style) in styles {
|
|
||||||
table.insert_style(pos, style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn table_apply_config(out: &mut TableOutput, cfg: &Cfg<'_>) {
|
fn table_apply_config(out: &mut TableOutput, cfg: &Cfg<'_>) {
|
||||||
configure_table(
|
configure_table(
|
||||||
out,
|
out,
|
||||||
|
@ -15,23 +15,23 @@ use crate::{
|
|||||||
pub struct JustTable;
|
pub struct JustTable;
|
||||||
|
|
||||||
impl JustTable {
|
impl JustTable {
|
||||||
pub fn table(input: &[Value], opts: TableOpts<'_>) -> StringResult {
|
pub fn table(input: Vec<Value>, opts: TableOpts<'_>) -> StringResult {
|
||||||
list_table(input, opts)
|
list_table(input, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kv_table(record: &Record, opts: TableOpts<'_>) -> StringResult {
|
pub fn kv_table(record: Record, opts: TableOpts<'_>) -> StringResult {
|
||||||
kv_table(record, opts)
|
kv_table(record, opts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_table(input: &[Value], opts: TableOpts<'_>) -> Result<Option<String>, ShellError> {
|
fn list_table(input: Vec<Value>, opts: TableOpts<'_>) -> Result<Option<String>, ShellError> {
|
||||||
let mut out = match create_table(input, &opts)? {
|
let output = create_table(input, &opts)?;
|
||||||
|
let mut out = match output {
|
||||||
Some(out) => out,
|
Some(out) => out,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
out.table.set_indent(opts.config.table.padding);
|
// TODO: It would be WAY more effitient to do right away instead of second pass over the data.
|
||||||
|
|
||||||
colorize_space(out.table.get_records_mut(), &opts.style_computer);
|
colorize_space(out.table.get_records_mut(), &opts.style_computer);
|
||||||
|
|
||||||
configure_table(&mut out, opts.config, &opts.style_computer, opts.mode);
|
configure_table(&mut out, opts.config, &opts.style_computer, opts.mode);
|
||||||
@ -40,25 +40,20 @@ fn list_table(input: &[Value], opts: TableOpts<'_>) -> Result<Option<String>, Sh
|
|||||||
Ok(table)
|
Ok(table)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kv_table(record: &Record, opts: TableOpts<'_>) -> StringResult {
|
fn kv_table(record: Record, opts: TableOpts<'_>) -> StringResult {
|
||||||
let mut data = vec![Vec::with_capacity(2); record.len()];
|
let mut table = NuTable::new(record.len(), 2);
|
||||||
|
|
||||||
for ((column, value), row) in record.iter().zip(data.iter_mut()) {
|
|
||||||
opts.signals.check(opts.span)?;
|
|
||||||
|
|
||||||
let key = NuRecordsValue::new(column.to_string());
|
|
||||||
|
|
||||||
let value = nu_value_to_string_colored(value, opts.config, &opts.style_computer);
|
|
||||||
let value = NuRecordsValue::new(value);
|
|
||||||
|
|
||||||
row.push(key);
|
|
||||||
row.push(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut table = NuTable::from(data);
|
|
||||||
table.set_index_style(TextStyle::default_field());
|
table.set_index_style(TextStyle::default_field());
|
||||||
table.set_indent(opts.config.table.padding);
|
table.set_indent(opts.config.table.padding);
|
||||||
|
|
||||||
|
for (i, (key, value)) in record.into_iter().enumerate() {
|
||||||
|
opts.signals.check(opts.span)?;
|
||||||
|
|
||||||
|
let value = nu_value_to_string_colored(&value, opts.config, &opts.style_computer);
|
||||||
|
|
||||||
|
table.insert((i, 0), key);
|
||||||
|
table.insert((i, 1), value);
|
||||||
|
}
|
||||||
|
|
||||||
let mut out = TableOutput::from_table(table, false, true);
|
let mut out = TableOutput::from_table(table, false, true);
|
||||||
configure_table(&mut out, opts.config, &opts.style_computer, opts.mode);
|
configure_table(&mut out, opts.config, &opts.style_computer, opts.mode);
|
||||||
let table = out.table.draw(opts.width);
|
let table = out.table.draw(opts.width);
|
||||||
@ -66,12 +61,12 @@ fn kv_table(record: &Record, opts: TableOpts<'_>) -> StringResult {
|
|||||||
Ok(table)
|
Ok(table)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_table(input: &[Value], opts: &TableOpts<'_>) -> TableResult {
|
fn create_table(input: Vec<Value>, opts: &TableOpts<'_>) -> TableResult {
|
||||||
if input.is_empty() {
|
if input.is_empty() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let headers = get_columns(input);
|
let headers = get_columns(&input);
|
||||||
let with_index = has_index(opts, &headers);
|
let with_index = has_index(opts, &headers);
|
||||||
let with_header = !headers.is_empty();
|
let with_header = !headers.is_empty();
|
||||||
let row_offset = opts.index_offset;
|
let row_offset = opts.index_offset;
|
||||||
@ -89,27 +84,23 @@ fn create_table(input: &[Value], opts: &TableOpts<'_>) -> TableResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_table_with_header(
|
fn create_table_with_header(
|
||||||
input: &[Value],
|
input: Vec<Value>,
|
||||||
headers: Vec<String>,
|
headers: Vec<String>,
|
||||||
opts: &TableOpts<'_>,
|
opts: &TableOpts<'_>,
|
||||||
) -> Result<Option<NuTable>, ShellError> {
|
) -> Result<Option<NuTable>, ShellError> {
|
||||||
let headers = collect_headers(headers, false);
|
|
||||||
|
|
||||||
let count_rows = input.len() + 1;
|
let count_rows = input.len() + 1;
|
||||||
let count_columns = headers.len();
|
let count_columns = headers.len();
|
||||||
let mut table = NuTable::new(count_rows, count_columns);
|
let mut table = NuTable::new(count_rows, count_columns);
|
||||||
|
|
||||||
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));
|
||||||
|
table.set_indent(opts.config.table.padding);
|
||||||
|
|
||||||
table.set_row(0, headers.clone());
|
for (row, item) in input.into_iter().enumerate() {
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
|
||||||
opts.signals.check(opts.span)?;
|
opts.signals.check(opts.span)?;
|
||||||
check_value(item)?;
|
check_value(&item)?;
|
||||||
|
|
||||||
for (col, header) in headers.iter().enumerate() {
|
for (col, header) in headers.iter().enumerate() {
|
||||||
let (text, style) = get_string_value_with_header(item, header.as_ref(), opts);
|
let (text, style) = get_string_value_with_header(&item, header, opts);
|
||||||
|
|
||||||
let pos = (row + 1, col);
|
let pos = (row + 1, col);
|
||||||
table.insert(pos, text);
|
table.insert(pos, text);
|
||||||
@ -117,35 +108,39 @@ fn create_table_with_header(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let headers = collect_headers(headers, false);
|
||||||
|
table.set_row(0, headers);
|
||||||
|
|
||||||
Ok(Some(table))
|
Ok(Some(table))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_table_with_header_and_index(
|
fn create_table_with_header_and_index(
|
||||||
input: &[Value],
|
input: Vec<Value>,
|
||||||
headers: Vec<String>,
|
headers: Vec<String>,
|
||||||
row_offset: usize,
|
row_offset: usize,
|
||||||
opts: &TableOpts<'_>,
|
opts: &TableOpts<'_>,
|
||||||
) -> Result<Option<NuTable>, ShellError> {
|
) -> Result<Option<NuTable>, ShellError> {
|
||||||
let headers = collect_headers(headers, true);
|
let head = collect_headers(headers, true);
|
||||||
|
|
||||||
let count_rows = input.len() + 1;
|
let count_rows = input.len() + 1;
|
||||||
let count_columns = headers.len();
|
let count_columns = head.len();
|
||||||
let mut table = NuTable::new(count_rows, count_columns);
|
|
||||||
|
|
||||||
|
let mut table = NuTable::new(count_rows, count_columns);
|
||||||
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));
|
||||||
|
table.set_indent(opts.config.table.padding);
|
||||||
|
|
||||||
table.set_row(0, headers.clone());
|
table.set_row(0, head.clone());
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
for (row, item) in input.into_iter().enumerate() {
|
||||||
opts.signals.check(opts.span)?;
|
opts.signals.check(opts.span)?;
|
||||||
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((row + 1, 0), text);
|
||||||
|
|
||||||
for (col, header) in headers.iter().enumerate().skip(1) {
|
for (col, head) in head.iter().enumerate().skip(1) {
|
||||||
let (text, style) = get_string_value_with_header(item, header.as_ref(), opts);
|
let (text, style) = get_string_value_with_header(&item, head.as_ref(), opts);
|
||||||
|
|
||||||
let pos = (row + 1, col);
|
let pos = (row + 1, col);
|
||||||
table.insert(pos, text);
|
table.insert(pos, text);
|
||||||
@ -157,46 +152,45 @@ fn create_table_with_header_and_index(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_table_with_no_header(
|
fn create_table_with_no_header(
|
||||||
input: &[Value],
|
input: Vec<Value>,
|
||||||
opts: &TableOpts<'_>,
|
opts: &TableOpts<'_>,
|
||||||
) -> Result<Option<NuTable>, ShellError> {
|
) -> Result<Option<NuTable>, ShellError> {
|
||||||
let mut table = NuTable::new(input.len(), 1);
|
let mut table = NuTable::new(input.len(), 1);
|
||||||
table.set_index_style(get_index_style(&opts.style_computer));
|
table.set_index_style(get_index_style(&opts.style_computer));
|
||||||
|
table.set_indent(opts.config.table.padding);
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
for (row, item) in input.into_iter().enumerate() {
|
||||||
opts.signals.check(opts.span)?;
|
opts.signals.check(opts.span)?;
|
||||||
check_value(item)?;
|
check_value(&item)?;
|
||||||
|
|
||||||
let (text, style) = get_string_value(item, opts);
|
let (text, style) = get_string_value(&item, opts);
|
||||||
|
|
||||||
let pos = (row, 0);
|
table.insert((row, 0), text);
|
||||||
table.insert(pos, text);
|
table.insert_style((row, 0), style);
|
||||||
table.insert_style(pos, style);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(table))
|
Ok(Some(table))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_table_with_no_header_and_index(
|
fn create_table_with_no_header_and_index(
|
||||||
input: &[Value],
|
input: Vec<Value>,
|
||||||
row_offset: usize,
|
row_offset: usize,
|
||||||
opts: &TableOpts<'_>,
|
opts: &TableOpts<'_>,
|
||||||
) -> Result<Option<NuTable>, ShellError> {
|
) -> Result<Option<NuTable>, ShellError> {
|
||||||
let mut table = NuTable::new(input.len(), 1 + 1);
|
let mut table = NuTable::new(input.len(), 1 + 1);
|
||||||
table.set_index_style(get_index_style(&opts.style_computer));
|
table.set_index_style(get_index_style(&opts.style_computer));
|
||||||
|
table.set_indent(opts.config.table.padding);
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
for (row, item) in input.into_iter().enumerate() {
|
||||||
opts.signals.check(opts.span)?;
|
opts.signals.check(opts.span)?;
|
||||||
check_value(item)?;
|
check_value(&item)?;
|
||||||
|
|
||||||
let text = get_table_row_index(item, opts.config, row, row_offset);
|
let index = get_table_row_index(&item, opts.config, row, row_offset);
|
||||||
table.insert((row, 0), text);
|
let (value, style) = get_string_value(&item, opts);
|
||||||
|
|
||||||
let (text, style) = get_string_value(item, opts);
|
table.insert((row, 0), index);
|
||||||
|
table.insert((row, 1), value);
|
||||||
let pos = (row, 1);
|
table.insert_style((row, 1), style);
|
||||||
table.insert(pos, text);
|
|
||||||
table.insert_style(pos, style);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(table))
|
Ok(Some(table))
|
||||||
|
@ -88,7 +88,14 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_table(data: Data, case: TestCase) -> Option<String> {
|
pub fn create_table(data: Data, case: TestCase) -> Option<String> {
|
||||||
let mut table = NuTable::from(data);
|
let count_rows = data.len();
|
||||||
|
let count_cols = data[0].len();
|
||||||
|
|
||||||
|
let mut table = NuTable::new(count_rows, count_cols);
|
||||||
|
for (i, row) in data.into_iter().enumerate() {
|
||||||
|
table.set_row(i, row);
|
||||||
|
}
|
||||||
|
|
||||||
table.set_theme(case.theme);
|
table.set_theme(case.theme);
|
||||||
table.set_structure(case.with_index, case.with_header, case.with_footer);
|
table.set_structure(case.with_index, case.with_header, case.with_footer);
|
||||||
table.set_trim(case.strategy);
|
table.set_trim(case.strategy);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user