diff --git a/crates/nu-command/tests/commands/table.rs b/crates/nu-command/tests/commands/table.rs index 6bd7dfbc00..cc40a41a74 100644 --- a/crates/nu-command/tests/commands/table.rs +++ b/crates/nu-command/tests/commands/table.rs @@ -1333,15 +1333,7 @@ fn test_expand_big_0() { "│ target │ {record 3 fields} │", "│ dev-dependencies │ {record 9 fields} │", "│ features │ {record 8 fields} │", - "│ │ ╭───┬─────┬─────╮ │", - "│ bin │ │ # │ nam │ pat │ │", - "│ │ │ │ e │ h │ │", - "│ │ ├───┼─────┼─────┤ │", - "│ │ │ 0 │ nu │ src │ │", - "│ │ │ │ │ /ma │ │", - "│ │ │ │ │ in. │ │", - "│ │ │ │ │ rs │ │", - "│ │ ╰───┴─────┴─────╯ │", + "│ bin │ [table 1 row] │", "│ │ ╭───────────┬───╮ │", "│ patch │ │ crates-io │ { │ │", "│ │ │ │ r │ │", @@ -1360,16 +1352,7 @@ fn test_expand_big_0() { "│ │ │ │ d │ │", "│ │ │ │ } │ │", "│ │ ╰───────────┴───╯ │", - "│ │ ╭───┬─────┬─────╮ │", - "│ bench │ │ # │ nam │ har │ │", - "│ │ │ │ e │ nes │ │", - "│ │ │ │ │ s │ │", - "│ │ ├───┼─────┼─────┤ │", - "│ │ │ 0 │ ben │ fal │ │", - "│ │ │ │ chm │ se │ │", - "│ │ │ │ ark │ │ │", - "│ │ │ │ s │ │ │", - "│ │ ╰───┴─────┴─────╯ │", + "│ bench │ [table 1 row] │", "╰──────────────────┴───────────────────╯", ]); @@ -1383,8 +1366,6 @@ fn table_expande_with_no_header_internally_0() { let actual = nu!(format!("{} | table --expand --width 141", nu_value.trim())); - _print_lines(&actual.out, 141); - assert_eq!( actual.out, join_lines([ @@ -1551,191 +1532,71 @@ fn table_expande_with_no_header_internally_0() { "│ │ │ │ │ │ ╰─────┴──────────╯ │ │ │", "│ │ │ │ │ display_output │ │ │ │", "│ │ │ │ ╰────────────────┴────────────────────╯ │ │", - "│ │ │ │ ╭───┬───────────────────────────┬────────────────────────┬────────┬───┬─────╮ │ │", - "│ │ │ menus │ │ # │ name │ only_buffer_difference │ marker │ t │ ... │ │ │", - "│ │ │ │ │ │ │ │ │ y │ │ │ │", - "│ │ │ │ │ │ │ │ │ p │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ ├───┼───────────────────────────┼────────────────────────┼────────┼───┼─────┤ │ │", - "│ │ │ │ │ 0 │ completion_menu │ false │ | │ { │ ... │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ c │ │ │ │", - "│ │ │ │ │ │ │ │ │ o │ │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ 4 │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ f │ │ │ │", - "│ │ │ │ │ │ │ │ │ i │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ l │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ s │ │ │ │", - "│ │ │ │ │ │ │ │ │ } │ │ │ │", - "│ │ │ │ │ 1 │ history_menu │ true │ ? │ { │ ... │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ c │ │ │ │", - "│ │ │ │ │ │ │ │ │ o │ │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ 2 │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ f │ │ │ │", - "│ │ │ │ │ │ │ │ │ i │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ l │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ s │ │ │ │", - "│ │ │ │ │ │ │ │ │ } │ │ │ │", - "│ │ │ │ │ 2 │ help_menu │ true │ ? │ { │ ... │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ c │ │ │ │", - "│ │ │ │ │ │ │ │ │ o │ │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ 6 │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ f │ │ │ │", - "│ │ │ │ │ │ │ │ │ i │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ l │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ s │ │ │ │", - "│ │ │ │ │ │ │ │ │ } │ │ │ │", - "│ │ │ │ │ 3 │ commands_menu │ false │ # │ { │ ... │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ c │ │ │ │", - "│ │ │ │ │ │ │ │ │ o │ │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ 4 │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ f │ │ │ │", - "│ │ │ │ │ │ │ │ │ i │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ l │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ s │ │ │ │", - "│ │ │ │ │ │ │ │ │ } │ │ │ │", - "│ │ │ │ │ 4 │ vars_menu │ true │ # │ { │ ... │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ c │ │ │ │", - "│ │ │ │ │ │ │ │ │ o │ │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ 2 │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ f │ │ │ │", - "│ │ │ │ │ │ │ │ │ i │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ l │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ s │ │ │ │", - "│ │ │ │ │ │ │ │ │ } │ │ │ │", - "│ │ │ │ │ 5 │ commands_with_description │ true │ # │ { │ ... │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ c │ │ │ │", - "│ │ │ │ │ │ │ │ │ o │ │ │ │", - "│ │ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ 6 │ │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ │ │", - "│ │ │ │ │ │ │ │ │ f │ │ │ │", - "│ │ │ │ │ │ │ │ │ i │ │ │ │", - "│ │ │ │ │ │ │ │ │ e │ │ │ │", - "│ │ │ │ │ │ │ │ │ l │ │ │ │", - "│ │ │ │ │ │ │ │ │ d │ │ │ │", - "│ │ │ │ │ │ │ │ │ s │ │ │ │", - "│ │ │ │ │ │ │ │ │ } │ │ │ │", - "│ │ │ │ ╰───┴───────────────────────────┴────────────────────────┴────────┴───┴─────╯ │ │", + "│ │ │ │ ╭───┬───────────────────────────┬────────────────────────┬────────┬─────╮ │ │", + "│ │ │ menus │ │ # │ name │ only_buffer_difference │ marker │ ... │ │ │", + "│ │ │ │ ├───┼───────────────────────────┼────────────────────────┼────────┼─────┤ │ │", + "│ │ │ │ │ 0 │ completion_menu │ false │ | │ ... │ │ │", + "│ │ │ │ │ 1 │ history_menu │ true │ ? │ ... │ │ │", + "│ │ │ │ │ 2 │ help_menu │ true │ ? │ ... │ │ │", + "│ │ │ │ │ 3 │ commands_menu │ false │ # │ ... │ │ │", + "│ │ │ │ │ 4 │ vars_menu │ true │ # │ ... │ │ │", + "│ │ │ │ │ 5 │ commands_with_description │ true │ # │ ... │ │ │", + "│ │ │ │ ╰───┴───────────────────────────┴────────────────────────┴────────┴─────╯ │ │", "│ │ │ │ ╭────┬───────────────────────────┬──────────┬─────────┬───────────────┬─────╮ │ │", - "│ │ │ keybindings │ │ # │ name │ modifier │ keycode │ mode │ eve │ │ │", - "│ │ │ │ │ │ │ │ │ │ nt │ │ │", + "│ │ │ keybindings │ │ # │ name │ modifier │ keycode │ mode │ ... │ │ │", "│ │ │ │ ├────┼───────────────────────────┼──────────┼─────────┼───────────────┼─────┤ │ │", - "│ │ │ │ │ 0 │ completion_menu │ none │ tab │ ╭───┬───────╮ │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 1 │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ sert │ │ } │ │ │", + "│ │ │ │ │ 0 │ completion_menu │ none │ tab │ ╭───┬───────╮ │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ sert │ │ │ │ │", "│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │", - "│ │ │ │ │ 1 │ completion_previous │ shift │ backtab │ ╭───┬───────╮ │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 1 │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ sert │ │ } │ │ │", + "│ │ │ │ │ 1 │ completion_previous │ shift │ backtab │ ╭───┬───────╮ │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ 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 │ │ } │ │ │", + "│ │ │ │ │ 2 │ history_menu │ control │ char_r │ emacs │ ... │ │ │", + "│ │ │ │ │ 3 │ next_page │ control │ char_x │ emacs │ ... │ │ │", + "│ │ │ │ │ 4 │ undo_or_previous_page │ control │ char_z │ emacs │ ... │ │ │", + "│ │ │ │ │ 5 │ yank │ control │ char_y │ emacs │ ... │ │ │", + "│ │ │ │ │ 6 │ unix-line-discard │ control │ char_u │ ╭───┬───────╮ │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ sert │ │ │ │ │", "│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │", - "│ │ │ │ │ 7 │ kill-line │ control │ char_k │ ╭───┬───────╮ │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 1 │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ sert │ │ } │ │ │", + "│ │ │ │ │ 7 │ kill-line │ control │ char_k │ ╭───┬───────╮ │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ sert │ │ │ │ │", "│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │", - "│ │ │ │ │ 8 │ commands_menu │ control │ char_t │ ╭───┬───────╮ │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 2 │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ sert │ │ s} │ │ │", + "│ │ │ │ │ 8 │ commands_menu │ control │ char_t │ ╭───┬───────╮ │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ sert │ │ │ │ │", "│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │", - "│ │ │ │ │ 9 │ vars_menu │ alt │ char_o │ ╭───┬───────╮ │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 2 │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ sert │ │ s} │ │ │", + "│ │ │ │ │ 9 │ vars_menu │ alt │ char_o │ ╭───┬───────╮ │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ sert │ │ │ │ │", "│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │", - "│ │ │ │ │ 10 │ commands_with_description │ control │ char_s │ ╭───┬───────╮ │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ d 2 │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ │ sert │ │ s} │ │ │", + "│ │ │ │ │ 10 │ commands_with_description │ control │ char_s │ ╭───┬───────╮ │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ │ 0 │ emacs │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 1 │ vi_no │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ rmal │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ 2 │ vi_in │ │ │ │ │", + "│ │ │ │ │ │ │ │ │ │ │ sert │ │ │ │ │", "│ │ │ │ │ │ │ │ │ ╰───┴───────╯ │ │ │ │", "│ │ │ │ ╰────┴───────────────────────────┴──────────┴─────────┴───────────────┴─────╯ │ │", "│ │ ╰──────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────╯ │", @@ -1750,8 +1611,6 @@ fn table_expande_with_no_header_internally_1() { let actual = nu!(format!("{} | table --expand --width 136", nu_value.trim())); - _print_lines(&actual.out, 136); - assert_eq!( actual.out, join_lines([ @@ -1918,87 +1777,37 @@ fn table_expande_with_no_header_internally_1() { "│ │ │ │ │ │ ╰─────┴──────────╯ │ │ │", "│ │ │ │ │ display_output │ │ │ │", "│ │ │ │ ╰────────────────┴────────────────────╯ │ │", - "│ │ │ │ ╭───┬───────────────────────────┬────────────────────────┬───────┬─────╮ │ │", - "│ │ │ menus │ │ # │ name │ only_buffer_difference │ marke │ ... │ │ │", - "│ │ │ │ │ │ │ │ r │ │ │ │", - "│ │ │ │ ├───┼───────────────────────────┼────────────────────────┼───────┼─────┤ │ │", - "│ │ │ │ │ 0 │ completion_menu │ false │ | │ ... │ │ │", - "│ │ │ │ │ 1 │ history_menu │ true │ ? │ ... │ │ │", - "│ │ │ │ │ 2 │ help_menu │ true │ ? │ ... │ │ │", - "│ │ │ │ │ 3 │ commands_menu │ false │ # │ ... │ │ │", - "│ │ │ │ │ 4 │ vars_menu │ true │ # │ ... │ │ │", - "│ │ │ │ │ 5 │ commands_with_description │ true │ # │ ... │ │ │", - "│ │ │ │ ╰───┴───────────────────────────┴────────────────────────┴───────┴─────╯ │ │", + "│ │ │ │ ╭───┬───────────────────────────┬────────────────────────┬─────╮ │ │", + "│ │ │ menus │ │ # │ name │ only_buffer_difference │ ... │ │ │", + "│ │ │ │ ├───┼───────────────────────────┼────────────────────────┼─────┤ │ │", + "│ │ │ │ │ 0 │ completion_menu │ false │ ... │ │ │", + "│ │ │ │ │ 1 │ history_menu │ true │ ... │ │ │", + "│ │ │ │ │ 2 │ help_menu │ true │ ... │ │ │", + "│ │ │ │ │ 3 │ commands_menu │ false │ ... │ │ │", + "│ │ │ │ │ 4 │ vars_menu │ true │ ... │ │ │", + "│ │ │ │ │ 5 │ commands_with_description │ true │ ... │ │ │", + "│ │ │ │ ╰───┴───────────────────────────┴────────────────────────┴─────╯ │ │", "│ │ │ │ ╭────┬───────────────────────────┬──────────┬─────────┬──────────┬─────╮ │ │", - "│ │ │ keybindings │ │ # │ name │ modifier │ keycode │ mode │ eve │ │ │", - "│ │ │ │ │ │ │ │ │ │ nt │ │ │", + "│ │ │ keybindings │ │ # │ name │ modifier │ keycode │ mode │ ... │ │ │", "│ │ │ │ ├────┼───────────────────────────┼──────────┼─────────┼──────────┼─────┤ │ │", - "│ │ │ │ │ 0 │ completion_menu │ none │ tab │ [list 3 │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ items] │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ d 1 │ │ │", - "│ │ │ │ │ │ │ │ │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ } │ │ │", - "│ │ │ │ │ 1 │ completion_previous │ shift │ backtab │ [list 3 │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ items] │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ d 1 │ │ │", - "│ │ │ │ │ │ │ │ │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ } │ │ │", - "│ │ │ │ │ 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 │ [list 3 │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ items] │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ d 1 │ │ │", - "│ │ │ │ │ │ │ │ │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ } │ │ │", - "│ │ │ │ │ 7 │ kill-line │ control │ char_k │ [list 3 │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ items] │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ d 1 │ │ │", - "│ │ │ │ │ │ │ │ │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ } │ │ │", - "│ │ │ │ │ 8 │ commands_menu │ control │ char_t │ [list 3 │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ items] │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ d 2 │ │ │", - "│ │ │ │ │ │ │ │ │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ s} │ │ │", - "│ │ │ │ │ 9 │ vars_menu │ alt │ char_o │ [list 3 │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ items] │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ d 2 │ │ │", - "│ │ │ │ │ │ │ │ │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ s} │ │ │", - "│ │ │ │ │ 10 │ commands_with_description │ control │ char_s │ [list 3 │ {re │ │ │", - "│ │ │ │ │ │ │ │ │ items] │ cor │ │ │", - "│ │ │ │ │ │ │ │ │ │ d 2 │ │ │", - "│ │ │ │ │ │ │ │ │ │ fi │ │ │", - "│ │ │ │ │ │ │ │ │ │ eld │ │ │", - "│ │ │ │ │ │ │ │ │ │ s} │ │ │", + "│ │ │ │ │ 0 │ completion_menu │ none │ tab │ [list 3 │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ items] │ │ │ │", + "│ │ │ │ │ 1 │ completion_previous │ shift │ backtab │ [list 3 │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ items] │ │ │ │", + "│ │ │ │ │ 2 │ history_menu │ control │ char_r │ emacs │ ... │ │ │", + "│ │ │ │ │ 3 │ next_page │ control │ char_x │ emacs │ ... │ │ │", + "│ │ │ │ │ 4 │ undo_or_previous_page │ control │ char_z │ emacs │ ... │ │ │", + "│ │ │ │ │ 5 │ yank │ control │ char_y │ emacs │ ... │ │ │", + "│ │ │ │ │ 6 │ unix-line-discard │ control │ char_u │ [list 3 │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ items] │ │ │ │", + "│ │ │ │ │ 7 │ kill-line │ control │ char_k │ [list 3 │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ items] │ │ │ │", + "│ │ │ │ │ 8 │ commands_menu │ control │ char_t │ [list 3 │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ items] │ │ │ │", + "│ │ │ │ │ 9 │ vars_menu │ alt │ char_o │ [list 3 │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ items] │ │ │ │", + "│ │ │ │ │ 10 │ commands_with_description │ control │ char_s │ [list 3 │ ... │ │ │", + "│ │ │ │ │ │ │ │ │ items] │ │ │ │", "│ │ │ │ ╰────┴───────────────────────────┴──────────┴─────────┴──────────┴─────╯ │ │", "│ │ ╰──────────────────────────────────┴──────────────────────────────────────────────────────────────────────────╯ │", "╰────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯", @@ -2712,7 +2521,6 @@ fn table_theme_on_border_with_love() { fn table_theme_on_border_thin() { assert_eq!( create_theme_output("thin"), - // ["┌─#─┬a_looooooong_name┬─b─┬─c─┐│ 0 │ 1 │ 2 │ 3 │└─#─┴a_looooooong_name┴─b─┴─c─┘"] [ "┌─#─┬─a─┬─b─┬───────c────────┐│ 0 │ 1 │ 2 │ 3 │├───┼───┼───┼────────────────┤│ 1 │ 4 │ 5 │ [list 3 items] │└───┴───┴───┴────────────────┘", "┌─#─┬─a─┬─b─┬───────c────────┐│ 0 │ 1 │ 2 │ 3 │├───┼───┼───┼────────────────┤│ 1 │ 4 │ 5 │ [list 3 items] │└─#─┴─a─┴─b─┴───────c────────┘", @@ -3341,21 +3149,3 @@ fn table_index_expand() { ╰─────┴─────╯" ); } - -#[test] -fn table_expand_big_header() { - let actual = nu!(" - let column_name = (('' | fill -c 'a' --width 81)) - [{ $column_name: 'contents' }] | table -e --width=80 - "); - - assert_eq!( - actual.out, - "╭───┬──────────────────────────────────────────────────────────────────────────╮\ - │ # │ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa │\ - │ │ aaaaaaaaa │\ - ├───┼──────────────────────────────────────────────────────────────────────────┤\ - │ 0 │ contents │\ - ╰───┴──────────────────────────────────────────────────────────────────────────╯" - ); -} diff --git a/crates/nu-table/src/table.rs b/crates/nu-table/src/table.rs index 90d23e0269..b706a41eb2 100644 --- a/crates/nu-table/src/table.rs +++ b/crates/nu-table/src/table.rs @@ -3,30 +3,33 @@ use std::{cmp::min, collections::HashMap}; use nu_ansi_term::Style; use nu_color_config::TextStyle; use nu_protocol::{TableIndent, TrimStrategy}; +use nu_utils::strip_ansi_unlikely; use tabled::{ builder::Builder, grid::{ ansi::ANSIBuf, + colors::Colors, config::{AlignmentHorizontal, ColoredConfig, Entity, Position}, dimension::CompleteDimensionVecRecords, records::{ vec_records::{Cell, Text, VecRecords}, - ExactRecords, Records, + ExactRecords, Records, Resizable, }, }, settings::{ + format::FormatContent, formatting::AlignmentStrategy, - object::{Columns, Rows}, + object::{Columns, Row, Rows}, peaker::Priority, themes::ColumnNames, width::Truncate, - Alignment, Color, Modify, Padding, TableOption, Width, + Alignment, Color, Format, Modify, ModifyList, Padding, Settings, TableOption, Width, }, Table, }; -use crate::{convert_style, is_color_empty, string_width, table_theme::TableTheme}; +use crate::{convert_style, is_color_empty, table_theme::TableTheme}; pub type NuRecords = VecRecords; pub type NuRecordsValue = Text; @@ -241,41 +244,14 @@ impl TableStructure { } } -#[derive(Debug, Clone)] -struct HeadInfo { - values: Vec, - align: AlignmentHorizontal, - color: Option, -} - fn build_table(mut t: NuTable, termwidth: usize) -> Option { if t.count_columns() == 0 || t.count_rows() == 0 { return Some(String::new()); } - let mut head = None; - if is_header_on_border(&t) { - head = Some(remove_header(&mut t)); - } else { - table_insert_footer(&mut t); - } - - let widths = table_truncate(&mut t, head.clone(), termwidth)?; - if let Some(head) = head.as_mut() { - if head.values.len() > widths.len() { - head.values[widths.len() - 1] = String::from("..."); - } - } - - draw_table(t, widths, head, termwidth) -} - -fn is_header_on_border(t: &NuTable) -> bool { - let structure = get_table_structure(&t.data, &t.config); - let is_configured = structure.with_header && t.config.header_on_border; - let has_horizontal = t.config.theme.as_base().borders_has_top() - || t.config.theme.as_base().get_horizontal_line(1).is_some(); - is_configured && has_horizontal + let widths = table_truncate(&mut t, termwidth)?; + table_insert_footer(&mut t); + draw_table(t, widths, termwidth) } fn table_insert_footer(t: &mut NuTable) { @@ -284,8 +260,9 @@ fn table_insert_footer(t: &mut NuTable) { } } -fn table_truncate(t: &mut NuTable, head: Option, termwidth: usize) -> Option> { - let widths = maybe_truncate_columns(&mut t.data, &t.config, head, termwidth); +fn table_truncate(t: &mut NuTable, termwidth: usize) -> Option> { + let pad = t.config.indent.left + t.config.indent.right; + let widths = maybe_truncate_columns(&mut t.data, &t.config, termwidth, pad); if widths.is_empty() { return None; } @@ -293,52 +270,10 @@ fn table_truncate(t: &mut NuTable, head: Option, termwidth: usize) -> Some(widths) } -fn remove_header(t: &mut NuTable) -> HeadInfo { - let head: Vec = t - .data - .remove(0) - .into_iter() - .map(|s| s.to_string()) - .collect(); - let align = t.alignments.header; - let color = is_color_empty(&t.styles.header).then(|| t.styles.header.clone()); - - // move settings by one row down - t.alignments.cells = t - .alignments - .cells - .drain() - .filter(|(k, _)| k.0 != 0) - .map(|(k, v)| ((k.0 - 1, k.1), v)) - .collect(); - - // move settings by one row down - t.styles.cells = t - .styles - .cells - .drain() - .filter(|(k, _)| k.0 != 0) - .map(|(k, v)| ((k.0 - 1, k.1), v)) - .collect(); - - HeadInfo { - values: head, - align, - color, - } -} - -fn draw_table( - t: NuTable, - widths: Vec, - head: Option, - termwidth: usize, -) -> Option { - let mut structure = get_table_structure(&t.data, &t.config); +fn draw_table(t: NuTable, widths: Vec, termwidth: usize) -> Option { + let structure = get_table_structure(&t.data, &t.config); let sep_color = t.config.border_color; - if head.is_some() { - structure.with_header = false; - } + let border_header = structure.with_header && t.config.header_on_border; let data: Vec> = t.data.into(); let mut table = Builder::from_vec(data).build(); @@ -347,51 +282,15 @@ fn draw_table( 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.clone(), widths, termwidth); - table_set_border_header(&mut table, head, &t.config.theme, structure); + + let pad = indent_sum(t.config.indent); + let width_ctrl = WidthCtrl::new(widths, t.config, termwidth, pad); + + adjust_table(&mut table, width_ctrl, border_header, structure.with_footer); table_to_string(table, termwidth) } -fn table_set_border_header( - table: &mut Table, - head: Option, - theme: &TableTheme, - structure: TableStructure, -) { - let head = match head { - Some(head) => head, - None => return, - }; - - let mut widths = GetDims(Vec::new()); - table.with(&mut widths); - - if !theme.as_base().borders_has_top() { - let line = theme.as_base().get_horizontal_line(1); - if let Some(line) = line.cloned() { - table.get_config_mut().insert_horizontal_line(0, line); - if structure.with_footer { - let last_row = table.count_rows(); - table - .get_config_mut() - .insert_horizontal_line(last_row, line); - } - }; - } - - if structure.with_footer { - let last_row = table.count_rows(); - table.with(SetLineHeaders::new(last_row, head.clone())); - } - - table.with(SetLineHeaders::new(0, head)); -} - -fn truncate_table(table: &mut Table, cfg: TableConfig, widths: Vec, termwidth: usize) { - table.with(WidthCtrl::new(widths, cfg, termwidth)); -} - fn indent_sum(indent: TableIndent) -> usize { indent.left + indent.right } @@ -404,10 +303,75 @@ fn get_table_structure(data: &VecRecords>, cfg: &TableConfig) -> Ta TableStructure::new(with_index, with_header, with_footer) } +fn adjust_table(table: &mut Table, width_ctrl: WidthCtrl, border_header: bool, with_footer: bool) { + if border_header { + if with_footer { + set_border_head_with_footer(table, width_ctrl); + } else { + set_border_head(table, width_ctrl); + } + } else { + table.with(width_ctrl); + } +} + fn set_indent(table: &mut Table, indent: TableIndent) { table.with(Padding::new(indent.left, indent.right, 0, 0)); } +fn set_border_head(table: &mut Table, wctrl: WidthCtrl) { + let mut row = GetRow(0, Vec::new()); + let mut row_opts = GetRowSettings(0, AlignmentHorizontal::Left, None); + + table.with(&mut row); + table.with(&mut row_opts); + + table.with( + Settings::default() + .with(strip_color_from_row(0)) + .with(wctrl) + .with(MoveRowNext::new(0, 0)) + .with(SetLineHeaders::new(0, row.1, row_opts.1, row_opts.2)), + ); +} + +fn set_border_head_with_footer(table: &mut Table, wctrl: WidthCtrl) { + // note: funnily last and row must be equal at this point but we do not rely on it just in case. + + let count_rows = table.count_rows(); + let last_row_index = count_rows - 1; + + let mut first_row = GetRow(0, Vec::new()); + let mut head_settings = GetRowSettings(0, AlignmentHorizontal::Left, None); + let mut last_row = GetRow(last_row_index, Vec::new()); + + table.with(&mut first_row); + table.with(&mut head_settings); + table.with(&mut last_row); + + let head = first_row.1; + let footer = last_row.1; + let alignment = head_settings.1; + let head_color = head_settings.2.clone(); + let footer_color = head_settings.2; + + table.with( + Settings::default() + .with(strip_color_from_row(0)) + .with(strip_color_from_row(count_rows - 1)) + .with(wctrl) + .with(MoveRowNext::new(0, 0)) + .with(MoveRowPrev::new(last_row_index - 1, last_row_index)) + .with(SetLineHeaders::new(0, head, alignment, head_color)) + .with(SetLineHeaders::new( + last_row_index - 1, + footer, + alignment, + footer_color, + )), + ); +} + fn table_to_string(table: Table, termwidth: usize) -> Option { let total_width = table.total_width(); @@ -423,14 +387,16 @@ struct WidthCtrl { width: Vec, cfg: TableConfig, width_max: usize, + pad: usize, } impl WidthCtrl { - fn new(width: Vec, cfg: TableConfig, max: usize) -> Self { + fn new(width: Vec, cfg: TableConfig, max: usize, pad: usize) -> Self { Self { width, cfg, width_max: max, + pad, } } } @@ -448,9 +414,8 @@ impl TableOption> for if need_truncation { let has_header = self.cfg.structure.with_header && rec.count_rows() > 1; let as_head = has_header && self.cfg.header_on_border; - let pad = indent_sum(self.cfg.indent); - let trim = TableTrim::new(self.width, self.width_max, self.cfg.trim, as_head, pad); + let trim = TableTrim::new(self.width, self.width_max, self.cfg.trim, as_head, self.pad); trim.change(rec, cfg, dim); return; } @@ -698,22 +663,24 @@ fn load_theme( fn maybe_truncate_columns( data: &mut NuRecords, cfg: &TableConfig, - head: Option, termwidth: usize, + pad: usize, ) -> Vec { const TERMWIDTH_THRESHOLD: usize = 120; - let pad = cfg.indent.left + cfg.indent.right; - let preserve_content = termwidth > TERMWIDTH_THRESHOLD; + let has_header = cfg.structure.with_header && data.count_rows() > 1; + let is_header_on_border = has_header && cfg.header_on_border; - if let Some(head) = head { - truncate_columns_by_head(data, &cfg.theme, head, pad, termwidth) + let truncate = if is_header_on_border { + truncate_columns_by_head } else if preserve_content { - truncate_columns_by_columns(data, &cfg.theme, pad, termwidth) + truncate_columns_by_columns } else { - truncate_columns_by_content(data, &cfg.theme, pad, termwidth) - } + truncate_columns_by_content + }; + + truncate(data, &cfg.theme, pad, termwidth) } // VERSION where we are showing AS LITTLE COLUMNS AS POSSIBLE but WITH AS MUCH CONTENT AS POSSIBLE. @@ -868,76 +835,51 @@ fn truncate_columns_by_columns( widths } -// VERSION where we are showing AS LITTLE COLUMNS AS POSSIBLE but -// WITH AS MUCH CONTENT AS POSSIBLE BY ACCOUNTED BY HEADERS. +// VERSION where we are showing AS LITTLE COLUMNS AS POSSIBLE but WITH AS MUCH CONTENT AS POSSIBLE. fn truncate_columns_by_head( data: &mut NuRecords, theme: &TableTheme, - head: HeadInfo, pad: usize, termwidth: usize, ) -> Vec { - const MIN_ACCEPTABLE_WIDTH: usize = 3; const TRAILING_COLUMN_WIDTH: usize = 5; - if data.is_empty() { - return vec![0; data.count_columns()]; + let config = create_config(theme, false, None); + let mut widths = build_width(&*data, pad); + let total_width = get_total_width2(&widths, &config); + if total_width <= termwidth { + return widths; } - let mut widths = build_width(data, pad); + if data.is_empty() { + return widths; + } + + let head = &data[0]; - let config = create_config(theme, false, None); let borders = config.get_borders(); let has_vertical = borders.has_vertical(); let mut width = borders.has_left() as usize + borders.has_right() as usize; let mut truncate_pos = 0; - for (i, head) in head.values.iter().enumerate() { - let head_width = string_width(head); - let col_width = widths[i]; - if head_width + pad <= col_width { - let move_width = head_width + pad + (i > 0 && has_vertical) as usize; - if width + move_width >= termwidth { - break; - } + for (i, column_header) in head.iter().enumerate() { + let column_header_width = Cell::width(column_header); + width += column_header_width + pad; - width += move_width; - truncate_pos += 1; - continue; + if i > 0 { + width += has_vertical as usize; } - // NOTE: So header is bigger then a column - // Therefore we must try to expand the column to head text width as much as possible. - // - // The kicker is that we will truncate the header if we can't fit it totally. - // Therefore it's not guaranteed that the column will be expanded to exactly head width. - widths[i] = head_width + pad; - let col_width = widths[i]; - - let move_width = col_width + (i > 0 && has_vertical) as usize; - if width + move_width >= termwidth { - let mut used_width = width + pad + (i > 0 && has_vertical) as usize; - if i + 1 != widths.len() { - used_width += TRAILING_COLUMN_WIDTH; - } - - let available = termwidth.saturating_sub(used_width); - - if available > MIN_ACCEPTABLE_WIDTH { - width += available; - widths[i] = available; - truncate_pos += 1; - } - + if width >= termwidth { + width -= column_header_width + (i > 0 && has_vertical) as usize + pad; break; } - width += move_width; truncate_pos += 1; } // we don't need any truncation then (is it possible?) - if truncate_pos == head.values.len() { + if truncate_pos == head.len() { return widths; } @@ -1049,16 +991,63 @@ fn build_width(records: &NuRecords, pad: usize) -> Vec { widths } +struct GetRow(usize, Vec); + +impl TableOption> for &mut GetRow { + fn change( + self, + recs: &mut NuRecords, + _: &mut ColoredConfig, + _: &mut CompleteDimensionVecRecords<'_>, + ) { + let row = self.0; + self.1 = recs[row].iter().map(|c| c.as_ref().to_owned()).collect(); + } +} + +struct GetRowSettings(usize, AlignmentHorizontal, Option); + +impl TableOption> + for &mut GetRowSettings +{ + fn change( + self, + _: &mut NuRecords, + cfg: &mut ColoredConfig, + _: &mut CompleteDimensionVecRecords<'_>, + ) { + let row = self.0; + self.1 = *cfg.get_alignment_horizontal(Entity::Row(row)); + self.2 = cfg + .get_colors() + .get_color((row, 0)) + .cloned() + .map(Color::from); + } +} + // It's laverages a use of guuaranted cached widths before hand // to speed up things a bit. struct SetLineHeaders { line: usize, - head: HeadInfo, + columns: Vec, + alignment: AlignmentHorizontal, + color: Option, } impl SetLineHeaders { - fn new(line: usize, head: HeadInfo) -> Self { - Self { line, head } + fn new( + line: usize, + columns: Vec, + alignment: AlignmentHorizontal, + color: Option, + ) -> Self { + Self { + line, + columns, + alignment, + color, + } } } @@ -1082,8 +1071,7 @@ impl TableOption> for }; let columns: Vec<_> = self - .head - .values + .columns .into_iter() .zip(widths.iter().cloned()) // it must be always safe to do .map(|(s, width)| Truncate::truncate(&s, width).into_owned()) @@ -1091,8 +1079,8 @@ impl TableOption> for let mut names = ColumnNames::new(columns) .line(self.line) - .alignment(Alignment::from(self.head.align)); - if let Some(color) = self.head.color { + .alignment(Alignment::from(self.alignment)); + if let Some(color) = self.color { names = names.color(color); } @@ -1104,25 +1092,163 @@ impl TableOption> for } } -fn theme_copy_horizontal_line(theme: &mut tabled::settings::Theme, from: usize, to: usize) { - if let Some(line) = theme.get_horizontal_line(from) { - theme.insert_horizontal_line(to, *line); +struct MoveRowNext { + row: usize, + line: usize, +} + +impl MoveRowNext { + fn new(row: usize, line: usize) -> Self { + Self { row, line } } } -struct GetDims(Vec); +struct MoveRowPrev { + row: usize, + line: usize, +} -impl TableOption> for &mut GetDims { +impl MoveRowPrev { + fn new(row: usize, line: usize) -> Self { + Self { row, line } + } +} + +impl TableOption> for MoveRowNext { fn change( self, - _: &mut NuRecords, - _: &mut ColoredConfig, - dims: &mut CompleteDimensionVecRecords<'_>, + recs: &mut NuRecords, + cfg: &mut ColoredConfig, + _: &mut CompleteDimensionVecRecords<'_>, ) { - self.0 = dims.get_widths().expect("expected to get it").to_vec(); + row_shift_next(recs, cfg, self.row, self.line); } fn hint_change(&self) -> Option { None } } + +impl TableOption> for MoveRowPrev { + fn change( + self, + recs: &mut NuRecords, + cfg: &mut ColoredConfig, + _: &mut CompleteDimensionVecRecords<'_>, + ) { + row_shift_prev(recs, cfg, self.row, self.line); + } + + fn hint_change(&self) -> Option { + None + } +} + +fn row_shift_next(recs: &mut NuRecords, cfg: &mut ColoredConfig, row: usize, line: usize) { + let count_rows = recs.count_rows(); + let count_columns = recs.count_columns(); + let has_line = cfg.has_horizontal(line, count_rows); + let has_next_line = cfg.has_horizontal(line + 1, count_rows); + if !has_line && !has_next_line { + return; + } + + recs.remove_row(row); + let count_rows = recs.count_rows(); + + shift_alignments_down(cfg, row, count_rows, count_columns); + shift_colors_down(cfg, row, count_rows, count_columns); + + if !has_line { + shift_lines_up(cfg, count_rows, &[line + 1]); + } else { + remove_lines(cfg, count_rows, &[line + 1]); + } + + shift_lines_up(cfg, count_rows, &[count_rows]); +} + +fn row_shift_prev(recs: &mut NuRecords, cfg: &mut ColoredConfig, row: usize, line: usize) { + let mut count_rows = recs.count_rows(); + let count_columns = recs.count_columns(); + let has_line = cfg.has_horizontal(line, count_rows); + let has_prev_line = cfg.has_horizontal(line - 1, count_rows); + if !has_line && !has_prev_line { + return; + } + + recs.remove_row(row); + + if !has_line { + return; + } + + count_rows -= 1; + + shift_alignments_down(cfg, row, count_rows, count_columns); + shift_colors_down(cfg, row, count_rows, count_columns); + remove_lines(cfg, count_rows, &[line - 1]); +} + +fn remove_lines(cfg: &mut ColoredConfig, count_rows: usize, line: &[usize]) { + for &line in line { + cfg.remove_horizontal_line(line, count_rows) + } +} + +fn shift_alignments_down( + cfg: &mut ColoredConfig, + row: usize, + count_rows: usize, + count_columns: usize, +) { + for row in row..count_rows { + for col in 0..count_columns { + let pos = (row + 1, col).into(); + let posn = (row, col).into(); + let align = *cfg.get_alignment_horizontal(pos); + cfg.set_alignment_horizontal(posn, align); + } + + let align = *cfg.get_alignment_horizontal(Entity::Row(row + 1)); + cfg.set_alignment_horizontal(Entity::Row(row), align); + } +} + +fn shift_colors_down(cfg: &mut ColoredConfig, row: usize, count_rows: usize, count_columns: usize) { + for row in row..count_rows { + for col in 0..count_columns { + let pos = (row + 1, col); + let posn = (row, col).into(); + let color = cfg.get_colors().get_color(pos).cloned(); + if let Some(color) = color { + cfg.set_color(posn, color); + } + } + } +} + +fn shift_lines_up(cfg: &mut ColoredConfig, count_rows: usize, lines: &[usize]) { + for &i in lines { + let line = cfg.get_horizontal_line(i).cloned(); + if let Some(line) = line { + cfg.insert_horizontal_line(i - 1, line); + cfg.remove_horizontal_line(i, count_rows); + } + } +} + +fn theme_copy_horizontal_line(theme: &mut tabled::settings::Theme, from: usize, to: usize) { + if let Some(line) = theme.get_horizontal_line(from) { + theme.insert_horizontal_line(to, *line); + } +} + +#[allow(clippy::type_complexity)] +fn strip_color_from_row(row: usize) -> ModifyList String>> { + fn foo(s: &str) -> String { + strip_ansi_unlikely(s).into_owned() + } + + Modify::new(Rows::single(row)).with(Format::content(foo)) +} diff --git a/crates/nu-table/src/types/expanded.rs b/crates/nu-table/src/types/expanded.rs index c93832fc19..393a381646 100644 --- a/crates/nu-table/src/types/expanded.rs +++ b/crates/nu-table/src/types/expanded.rs @@ -240,7 +240,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult { } let mut available = available_width - pad_space; - let mut column_width = 0; + let mut column_width = string_width(&header); if !is_last_column { // we need to make sure that we have a space for a next column if we use available width @@ -293,18 +293,9 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult { column_rows = column_rows.saturating_add(cell.size); } - let mut head_width = string_width(&header); - let mut header = header; - if head_width > available { - header = wrap_text(&header, available, cfg.opts.config); - head_width = available; - } - let head_cell = NuRecordsValue::new(header); data[0].push(head_cell); - column_width = max(column_width, head_width); - if column_width > available { // remove the column we just inserted for row in &mut data { diff --git a/crates/nu-table/src/util.rs b/crates/nu-table/src/util.rs index 8784454cfb..8384ef144f 100644 --- a/crates/nu-table/src/util.rs +++ b/crates/nu-table/src/util.rs @@ -31,27 +31,6 @@ pub fn string_wrap(text: &str, width: usize, keep_words: bool) -> String { Wrap::wrap(text, width, keep_words) } -pub fn string_expand(text: &str, width: usize) -> String { - use std::{borrow::Cow, iter::repeat}; - use tabled::grid::util::string::{get_line_width, get_lines}; - - get_lines(text) - .map(|line| { - let length = get_line_width(&line); - - if length < width { - let mut line = line.into_owned(); - let remain = width - length; - line.extend(repeat(' ').take(remain)); - Cow::Owned(line) - } else { - line - } - }) - .collect::>() - .join("\n") -} - pub fn string_truncate(text: &str, width: usize) -> String { let line = match text.lines().next() { Some(line) => line, diff --git a/typos.toml b/typos.toml index 76d8b8959a..14baa39811 100644 --- a/typos.toml +++ b/typos.toml @@ -1,7 +1,6 @@ [files] extend-exclude = [ ".git/", - "crates/nu-command/tests/commands/table.rs", "crates/nu-cmd-extra/assets/228_themes.json", "tests/fixtures/formats/", ]