mirror of
https://github.com/nushell/nushell
synced 2024-12-26 13:03:07 +00:00
nu-table: Fix padding 0 width issues (#10011)
close #10001 cc: @fdncred @amtoine note: make sure you rebase/squash --------- Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
This commit is contained in:
parent
435348aa61
commit
696b2cda4a
2 changed files with 46 additions and 45 deletions
|
@ -2596,16 +2596,16 @@ fn table_expand_padding_not_default() {
|
||||||
let actual = nu!("$env.config.table.padding = 5; [[a b, c]; [1 2 3] [4 5 [1 2 3]]] | table -e");
|
let actual = nu!("$env.config.table.padding = 5; [[a b, c]; [1 2 3] [4 5 [1 2 3]]] | table -e");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
actual.out,
|
actual.out,
|
||||||
"╭───────────┬───────────┬───────────┬───────────────────────────────────╮\
|
"╭─────────────┬─────────────┬─────────────┬────────────────────────────────────╮\
|
||||||
│ # │ a │ b │ c │\
|
│ # │ a │ b │ c │\
|
||||||
├───────────┼───────────┼───────────┼───────────────────────────────────┤\
|
├─────────────┼─────────────┼─────────────┼────────────────────────────────────┤\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\
|
│ 0 │ 1 │ 2 │ 3 │\
|
||||||
│ 1 │ 4 │ 5 │ ╭───────────┬───────────╮ │\
|
│ 1 │ 4 │ 5 │ ╭───────────┬───────────╮ │\
|
||||||
│ │ │ │ │ 0 │ 1 │ │\
|
│ │ │ │ │ 0 │ 1 │ │\
|
||||||
│ │ │ │ │ 1 │ 2 │ │\
|
│ │ │ │ │ 1 │ 2 │ │\
|
||||||
│ │ │ │ │ 2 │ 3 │ │\
|
│ │ │ │ │ 2 │ 3 │ │\
|
||||||
│ │ │ │ ╰───────────┴───────────╯ │\
|
│ │ │ │ ╰───────────┴───────────╯ │\
|
||||||
╰───────────┴───────────┴───────────┴───────────────────────────────────╯"
|
╰─────────────┴─────────────┴─────────────┴────────────────────────────────────╯"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,13 @@ use tabled::{
|
||||||
/// 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: NuTableData,
|
data: NuRecords,
|
||||||
styles: Styles,
|
styles: Styles,
|
||||||
alignments: Alignments,
|
alignments: Alignments,
|
||||||
indent: (usize, usize),
|
indent: (usize, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
type NuTableData = VecRecords<NuTableCell>;
|
pub type NuRecords = VecRecords<NuTableCell>;
|
||||||
pub type NuTableCell = CellInfo<String>;
|
pub type NuTableCell = CellInfo<String>;
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
|
@ -158,7 +158,7 @@ impl NuTable {
|
||||||
/// Return a total table width.
|
/// Return a total table width.
|
||||||
pub fn total_width(&self, config: &NuTableConfig) -> usize {
|
pub fn total_width(&self, config: &NuTableConfig) -> usize {
|
||||||
let config = get_config(&config.theme, false, None);
|
let config = get_config(&config.theme, false, None);
|
||||||
let widths = build_width(&self.data);
|
let widths = build_width(&self.data, self.indent.0 + self.indent.1);
|
||||||
get_total_width2(&widths, &config)
|
get_total_width2(&widths, &config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ impl Default for NuTableConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_table(
|
fn build_table(
|
||||||
mut data: NuTableData,
|
mut data: NuRecords,
|
||||||
cfg: NuTableConfig,
|
cfg: NuTableConfig,
|
||||||
alignments: Alignments,
|
alignments: Alignments,
|
||||||
styles: Styles,
|
styles: Styles,
|
||||||
|
@ -211,7 +211,8 @@ fn build_table(
|
||||||
return Some(String::new());
|
return Some(String::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
let widths = maybe_truncate_columns(&mut data, &cfg.theme, termwidth);
|
let pad = indent.0 + indent.1;
|
||||||
|
let widths = maybe_truncate_columns(&mut data, &cfg.theme, termwidth, pad);
|
||||||
if widths.is_empty() {
|
if widths.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -224,7 +225,7 @@ fn build_table(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_table(
|
fn draw_table(
|
||||||
data: NuTableData,
|
data: NuRecords,
|
||||||
alignments: Alignments,
|
alignments: Alignments,
|
||||||
styles: Styles,
|
styles: Styles,
|
||||||
widths: Vec<usize>,
|
widths: Vec<usize>,
|
||||||
|
@ -437,9 +438,10 @@ fn table_trim_columns(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_truncate_columns(
|
fn maybe_truncate_columns(
|
||||||
data: &mut NuTableData,
|
data: &mut NuRecords,
|
||||||
theme: &TableTheme,
|
theme: &TableTheme,
|
||||||
termwidth: usize,
|
termwidth: usize,
|
||||||
|
pad: usize,
|
||||||
) -> Vec<usize> {
|
) -> Vec<usize> {
|
||||||
const TERMWIDTH_THRESHOLD: usize = 120;
|
const TERMWIDTH_THRESHOLD: usize = 120;
|
||||||
|
|
||||||
|
@ -449,20 +451,21 @@ fn maybe_truncate_columns(
|
||||||
truncate_columns_by_content
|
truncate_columns_by_content
|
||||||
};
|
};
|
||||||
|
|
||||||
truncate(data, theme, termwidth)
|
truncate(data, 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 NuTableData,
|
data: &mut NuRecords,
|
||||||
theme: &TableTheme,
|
theme: &TableTheme,
|
||||||
|
pad: usize,
|
||||||
termwidth: usize,
|
termwidth: usize,
|
||||||
) -> Vec<usize> {
|
) -> Vec<usize> {
|
||||||
const MIN_ACCEPTABLE_WIDTH: usize = 3;
|
const MIN_ACCEPTABLE_WIDTH: usize = 3;
|
||||||
const TRAILING_COLUMN_WIDTH: usize = 5;
|
const TRAILING_COLUMN_WIDTH: usize = 5;
|
||||||
|
|
||||||
let config = get_config(theme, false, None);
|
let config = get_config(theme, false, None);
|
||||||
let mut widths = build_width(&*data);
|
let mut widths = build_width(&*data, pad);
|
||||||
let total_width = get_total_width2(&widths, &config);
|
let total_width = get_total_width2(&widths, &config);
|
||||||
if total_width <= termwidth {
|
if total_width <= termwidth {
|
||||||
return widths;
|
return widths;
|
||||||
|
@ -516,7 +519,7 @@ fn truncate_columns_by_content(
|
||||||
|
|
||||||
if can_be_squeezed {
|
if can_be_squeezed {
|
||||||
push_empty_column(data);
|
push_empty_column(data);
|
||||||
widths.push(3 + 2);
|
widths.push(3 + pad);
|
||||||
} else {
|
} else {
|
||||||
if data.count_columns() == 1 {
|
if data.count_columns() == 1 {
|
||||||
return vec![];
|
return vec![];
|
||||||
|
@ -525,7 +528,7 @@ fn truncate_columns_by_content(
|
||||||
truncate_columns(data, data.count_columns() - 1);
|
truncate_columns(data, data.count_columns() - 1);
|
||||||
push_empty_column(data);
|
push_empty_column(data);
|
||||||
widths.pop();
|
widths.pop();
|
||||||
widths.push(3 + 2);
|
widths.push(3 + pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
widths
|
widths
|
||||||
|
@ -533,15 +536,16 @@ fn truncate_columns_by_content(
|
||||||
|
|
||||||
// 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
|
||||||
fn truncate_columns_by_columns(
|
fn truncate_columns_by_columns(
|
||||||
data: &mut NuTableData,
|
data: &mut NuRecords,
|
||||||
theme: &TableTheme,
|
theme: &TableTheme,
|
||||||
|
pad: usize,
|
||||||
termwidth: usize,
|
termwidth: usize,
|
||||||
) -> Vec<usize> {
|
) -> Vec<usize> {
|
||||||
const ACCEPTABLE_WIDTH: usize = 10 + 2;
|
let acceptable_width = 10 + pad;
|
||||||
const TRAILING_COLUMN_WIDTH: usize = 3 + 2;
|
let trailing_column_width = 3 + pad;
|
||||||
|
|
||||||
let config = get_config(theme, false, None);
|
let config = get_config(theme, false, None);
|
||||||
let mut widths = build_width(&*data);
|
let mut widths = build_width(&*data, pad);
|
||||||
let total_width = get_total_width2(&widths, &config);
|
let total_width = get_total_width2(&widths, &config);
|
||||||
if total_width <= termwidth {
|
if total_width <= termwidth {
|
||||||
return widths;
|
return widths;
|
||||||
|
@ -550,7 +554,7 @@ fn truncate_columns_by_columns(
|
||||||
let widths_total = widths.iter().sum::<usize>();
|
let widths_total = widths.iter().sum::<usize>();
|
||||||
let min_widths = widths
|
let min_widths = widths
|
||||||
.iter()
|
.iter()
|
||||||
.map(|w| min(*w, ACCEPTABLE_WIDTH))
|
.map(|w| min(*w, acceptable_width))
|
||||||
.sum::<usize>();
|
.sum::<usize>();
|
||||||
let mut min_total = total_width - widths_total + min_widths;
|
let mut min_total = total_width - widths_total + min_widths;
|
||||||
|
|
||||||
|
@ -564,7 +568,7 @@ fn truncate_columns_by_columns(
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
||||||
let column = data.count_columns() - 1 - i;
|
let column = data.count_columns() - 1 - i;
|
||||||
let width = min(widths[column], ACCEPTABLE_WIDTH);
|
let width = min(widths[column], acceptable_width);
|
||||||
min_total -= width;
|
min_total -= width;
|
||||||
|
|
||||||
if config.get_borders().has_vertical() {
|
if config.get_borders().has_vertical() {
|
||||||
|
@ -585,9 +589,9 @@ fn truncate_columns_by_columns(
|
||||||
|
|
||||||
// Append columns with a trailing column
|
// Append columns with a trailing column
|
||||||
let diff = termwidth - min_total;
|
let diff = termwidth - min_total;
|
||||||
if diff > TRAILING_COLUMN_WIDTH {
|
if diff > trailing_column_width {
|
||||||
push_empty_column(data);
|
push_empty_column(data);
|
||||||
widths.push(3 + 2);
|
widths.push(3 + pad);
|
||||||
} else {
|
} else {
|
||||||
if data.count_columns() == 1 {
|
if data.count_columns() == 1 {
|
||||||
return vec![];
|
return vec![];
|
||||||
|
@ -596,7 +600,7 @@ fn truncate_columns_by_columns(
|
||||||
truncate_columns(data, data.count_columns() - 1);
|
truncate_columns(data, data.count_columns() - 1);
|
||||||
push_empty_column(data);
|
push_empty_column(data);
|
||||||
widths.pop();
|
widths.pop();
|
||||||
widths.push(3 + 2);
|
widths.push(3 + pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
widths
|
widths
|
||||||
|
@ -631,7 +635,7 @@ fn get_config(theme: &TableTheme, with_header: bool, color: Option<Style>) -> Co
|
||||||
table.get_config().clone()
|
table.get_config().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_empty_column(data: &mut NuTableData) {
|
fn push_empty_column(data: &mut NuRecords) {
|
||||||
let records = std::mem::take(data);
|
let records = std::mem::take(data);
|
||||||
let mut inner: Vec<Vec<_>> = records.into();
|
let mut inner: Vec<Vec<_>> = records.into();
|
||||||
|
|
||||||
|
@ -643,7 +647,7 @@ fn push_empty_column(data: &mut NuTableData) {
|
||||||
*data = VecRecords::new(inner);
|
*data = VecRecords::new(inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn duplicate_row(data: &mut NuTableData, row: usize) {
|
fn duplicate_row(data: &mut NuRecords, row: usize) {
|
||||||
let records = std::mem::take(data);
|
let records = std::mem::take(data);
|
||||||
let mut inner: Vec<Vec<_>> = records.into();
|
let mut inner: Vec<Vec<_>> = records.into();
|
||||||
|
|
||||||
|
@ -653,7 +657,7 @@ fn duplicate_row(data: &mut NuTableData, row: usize) {
|
||||||
*data = VecRecords::new(inner);
|
*data = VecRecords::new(inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn truncate_columns(data: &mut NuTableData, count: usize) {
|
fn truncate_columns(data: &mut NuRecords, count: usize) {
|
||||||
let records = std::mem::take(data);
|
let records = std::mem::take(data);
|
||||||
let mut inner: Vec<Vec<_>> = records.into();
|
let mut inner: Vec<Vec<_>> = records.into();
|
||||||
|
|
||||||
|
@ -693,15 +697,14 @@ impl<R> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for SetDi
|
||||||
}
|
}
|
||||||
|
|
||||||
// it assumes no spans is used.
|
// it assumes no spans is used.
|
||||||
fn build_width(records: &VecRecords<CellInfo<String>>) -> Vec<usize> {
|
fn build_width(records: &NuRecords, pad: usize) -> Vec<usize> {
|
||||||
use tabled::grid::records::vec_records::Cell;
|
use tabled::grid::records::vec_records::Cell;
|
||||||
const PAD: usize = 2;
|
|
||||||
|
|
||||||
let count_columns = records.count_columns();
|
let count_columns = records.count_columns();
|
||||||
let mut widths = vec![0; count_columns];
|
let mut widths = vec![0; count_columns];
|
||||||
for columns in records.iter_rows() {
|
for columns in records.iter_rows() {
|
||||||
for (col, cell) in columns.iter().enumerate() {
|
for (col, cell) in columns.iter().enumerate() {
|
||||||
let width = Cell::width(cell) + PAD;
|
let width = Cell::width(cell) + pad;
|
||||||
widths[col] = std::cmp::max(widths[col], width);
|
widths[col] = std::cmp::max(widths[col], width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -711,12 +714,10 @@ fn build_width(records: &VecRecords<CellInfo<String>>) -> Vec<usize> {
|
||||||
|
|
||||||
struct HeaderMove((usize, usize), bool);
|
struct HeaderMove((usize, usize), bool);
|
||||||
|
|
||||||
impl TableOption<VecRecords<CellInfo<String>>, CompleteDimensionVecRecords<'_>, ColoredConfig>
|
impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for HeaderMove {
|
||||||
for HeaderMove
|
|
||||||
{
|
|
||||||
fn change(
|
fn change(
|
||||||
self,
|
self,
|
||||||
recs: &mut VecRecords<CellInfo<String>>,
|
recs: &mut NuRecords,
|
||||||
cfg: &mut ColoredConfig,
|
cfg: &mut ColoredConfig,
|
||||||
dims: &mut CompleteDimensionVecRecords<'_>,
|
dims: &mut CompleteDimensionVecRecords<'_>,
|
||||||
) {
|
) {
|
||||||
|
@ -730,7 +731,7 @@ impl TableOption<VecRecords<CellInfo<String>>, CompleteDimensionVecRecords<'_>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_header_on_next(
|
fn move_header_on_next(
|
||||||
recs: &mut VecRecords<CellInfo<String>>,
|
recs: &mut NuRecords,
|
||||||
cfg: &mut ColoredConfig,
|
cfg: &mut ColoredConfig,
|
||||||
dims: &mut CompleteDimensionVecRecords<'_>,
|
dims: &mut CompleteDimensionVecRecords<'_>,
|
||||||
row: usize,
|
row: usize,
|
||||||
|
@ -772,7 +773,7 @@ fn move_header_on_next(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_header_on_prev(
|
fn move_header_on_prev(
|
||||||
recs: &mut VecRecords<CellInfo<String>>,
|
recs: &mut NuRecords,
|
||||||
cfg: &mut ColoredConfig,
|
cfg: &mut ColoredConfig,
|
||||||
dims: &mut CompleteDimensionVecRecords<'_>,
|
dims: &mut CompleteDimensionVecRecords<'_>,
|
||||||
row: usize,
|
row: usize,
|
||||||
|
@ -857,7 +858,7 @@ fn shift_lines_up(cfg: &mut ColoredConfig, count_rows: usize, lines: &[usize]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_column_names(
|
fn set_column_names(
|
||||||
records: &mut VecRecords<CellInfo<String>>,
|
records: &mut NuRecords,
|
||||||
cfg: &mut ColoredConfig,
|
cfg: &mut ColoredConfig,
|
||||||
dims: &mut CompleteDimensionVecRecords<'_>,
|
dims: &mut CompleteDimensionVecRecords<'_>,
|
||||||
head: Vec<String>,
|
head: Vec<String>,
|
||||||
|
@ -873,7 +874,7 @@ fn set_column_names(
|
||||||
ColumnNames::change(names, records, cfg, dims)
|
ColumnNames::change(names, records, cfg, dims)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_row(recs: &mut VecRecords<CellInfo<String>>, row: usize) -> Vec<String> {
|
fn remove_row(recs: &mut NuRecords, row: usize) -> Vec<String> {
|
||||||
let count_columns = recs.count_columns();
|
let count_columns = recs.count_columns();
|
||||||
let columns = (0..count_columns)
|
let columns = (0..count_columns)
|
||||||
.map(|column| recs.get_text((row, column)).to_owned())
|
.map(|column| recs.get_text((row, column)).to_owned())
|
||||||
|
|
Loading…
Reference in a new issue