mirror of
https://github.com/nushell/nushell
synced 2024-12-25 12:33:17 +00:00
fix https://github.com/nushell/nushell/issues/7380
This commit is contained in:
parent
b6683a3010
commit
33aea56ccd
16 changed files with 1006 additions and 609 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -1889,9 +1889,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "json_to_table"
|
name = "json_to_table"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "408f09e42613f7a9902ecf2f30bcd053cf9f5668d0b1493ae1669070338d661b"
|
checksum = "a0be33515faeb3773f550c80fd7a889148164e58f7e3cf36467718c8ce71ee55"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tabled",
|
"tabled",
|
||||||
|
@ -2576,6 +2576,7 @@ version = "0.72.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"alphanumeric-sort",
|
"alphanumeric-sort",
|
||||||
|
"atty",
|
||||||
"base64",
|
"base64",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"bytesize",
|
"bytesize",
|
||||||
|
@ -2811,7 +2812,6 @@ dependencies = [
|
||||||
name = "nu-table"
|
name = "nu-table"
|
||||||
version = "0.72.2"
|
version = "0.72.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
|
||||||
"json_to_table",
|
"json_to_table",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
"nu-protocol",
|
"nu-protocol",
|
||||||
|
|
|
@ -29,6 +29,7 @@ num-format = { version = "0.4.3" }
|
||||||
|
|
||||||
# Potential dependencies for extras
|
# Potential dependencies for extras
|
||||||
alphanumeric-sort = "1.4.4"
|
alphanumeric-sort = "1.4.4"
|
||||||
|
atty = "0.2.14"
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
bytesize = "1.1.0"
|
bytesize = "1.1.0"
|
||||||
|
|
|
@ -8,7 +8,7 @@ use nu_protocol::{
|
||||||
PipelineData, PipelineMetadata, RawStream, ShellError, Signature, Span, SyntaxShape,
|
PipelineData, PipelineMetadata, RawStream, ShellError, Signature, Span, SyntaxShape,
|
||||||
TableIndexMode, Value,
|
TableIndexMode, Value,
|
||||||
};
|
};
|
||||||
use nu_table::{string_width, Alignment, Alignments, Table as NuTable, TableTheme, TextStyle};
|
use nu_table::{string_width, Alignment, Table as NuTable, TableConfig, TableTheme, TextStyle};
|
||||||
use nu_utils::get_ls_colors;
|
use nu_utils::get_ls_colors;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
@ -302,6 +302,8 @@ fn handle_table_command(
|
||||||
TableView::Collapsed => build_collapsed_table(cols, vals, config, term_width),
|
TableView::Collapsed => build_collapsed_table(cols, vals, config, term_width),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
let result = strip_output_color(result, config);
|
||||||
|
|
||||||
let ctrl_c_was_triggered = || match &ctrlc {
|
let ctrl_c_was_triggered = || match &ctrlc {
|
||||||
Some(ctrlc) => ctrlc.load(Ordering::SeqCst),
|
Some(ctrlc) => ctrlc.load(Ordering::SeqCst),
|
||||||
None => false,
|
None => false,
|
||||||
|
@ -411,19 +413,12 @@ fn build_general_table2(
|
||||||
}
|
}
|
||||||
|
|
||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
let table = NuTable::new(data, (data_len, 2), term_width, false, false);
|
|
||||||
|
|
||||||
let theme = load_theme_from_config(config);
|
|
||||||
let color_hm = get_color_config(config);
|
let color_hm = get_color_config(config);
|
||||||
|
let table_config = create_table_config(config, &color_hm, data_len, false, false, false);
|
||||||
|
|
||||||
let table = table.draw_table(
|
let table = NuTable::new(data, (data_len, 2));
|
||||||
config,
|
|
||||||
&color_hm,
|
let table = table.draw(table_config, term_width);
|
||||||
Alignments::default(),
|
|
||||||
&theme,
|
|
||||||
term_width,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(table)
|
Ok(table)
|
||||||
}
|
}
|
||||||
|
@ -440,16 +435,18 @@ fn build_expanded_table(
|
||||||
flatten: bool,
|
flatten: bool,
|
||||||
flatten_sep: &str,
|
flatten_sep: &str,
|
||||||
) -> Result<Option<String>, ShellError> {
|
) -> Result<Option<String>, ShellError> {
|
||||||
let theme = load_theme_from_config(config);
|
|
||||||
let color_hm = get_color_config(config);
|
let color_hm = get_color_config(config);
|
||||||
let alignments = Alignments::default();
|
let theme = load_theme_from_config(config);
|
||||||
|
|
||||||
// calculate the width of a key part + the rest of table so we know the rest of the table width available for value.
|
// calculate the width of a key part + the rest of table so we know the rest of the table width available for value.
|
||||||
let key_width = cols.iter().map(|col| string_width(col)).max().unwrap_or(0);
|
let key_width = cols.iter().map(|col| string_width(col)).max().unwrap_or(0);
|
||||||
let key = NuTable::create_cell(" ".repeat(key_width), TextStyle::default());
|
let key = NuTable::create_cell(" ".repeat(key_width), TextStyle::default());
|
||||||
let key_table = NuTable::new(vec![vec![key]], (1, 2), term_width, false, false);
|
let key_table = NuTable::new(vec![vec![key]], (1, 2));
|
||||||
let key_width = key_table
|
let key_width = key_table
|
||||||
.draw_table(config, &color_hm, alignments, &theme, usize::MAX, false)
|
.draw(
|
||||||
|
create_table_config(config, &color_hm, 1, false, false, false),
|
||||||
|
usize::MAX,
|
||||||
|
)
|
||||||
.map(|table| string_width(&table))
|
.map(|table| string_width(&table))
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
@ -486,7 +483,6 @@ fn build_expanded_table(
|
||||||
config,
|
config,
|
||||||
span,
|
span,
|
||||||
&color_hm,
|
&color_hm,
|
||||||
&theme,
|
|
||||||
deep,
|
deep,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -494,21 +490,23 @@ fn build_expanded_table(
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
match table {
|
match table {
|
||||||
Some(mut table) => {
|
Some((mut table, with_header, with_index)) => {
|
||||||
// controll width via removing table columns.
|
// controll width via removing table columns.
|
||||||
let theme = load_theme_from_config(config);
|
let theme = load_theme_from_config(config);
|
||||||
table.truncate(remaining_width, &theme);
|
table.truncate(remaining_width, &theme);
|
||||||
|
|
||||||
is_expanded = true;
|
is_expanded = true;
|
||||||
|
|
||||||
let val = table.draw_table(
|
let table_config = create_table_config(
|
||||||
config,
|
config,
|
||||||
&color_hm,
|
&color_hm,
|
||||||
alignments,
|
table.count_rows(),
|
||||||
&theme,
|
with_header,
|
||||||
remaining_width,
|
with_index,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let val = table.draw(table_config, remaining_width);
|
||||||
match val {
|
match val {
|
||||||
Some(result) => result,
|
Some(result) => result,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
|
@ -573,11 +571,10 @@ fn build_expanded_table(
|
||||||
}
|
}
|
||||||
|
|
||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
let table = NuTable::new(data, (data_len, 2), term_width, false, false);
|
let table_config = create_table_config(config, &color_hm, data_len, false, false, false);
|
||||||
|
let table = NuTable::new(data, (data_len, 2));
|
||||||
|
|
||||||
let table_s = table
|
let table_s = table.clone().draw(table_config.clone(), term_width);
|
||||||
.clone()
|
|
||||||
.draw_table(config, &color_hm, alignments, &theme, term_width, false);
|
|
||||||
|
|
||||||
let table = match table_s {
|
let table = match table_s {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
|
@ -590,7 +587,8 @@ fn build_expanded_table(
|
||||||
let used_percent = width as f32 / term_width as f32;
|
let used_percent = width as f32 / term_width as f32;
|
||||||
|
|
||||||
if width < term_width && used_percent > EXPAND_TREASHHOLD {
|
if width < term_width && used_percent > EXPAND_TREASHHOLD {
|
||||||
table.draw_table(config, &color_hm, alignments, &theme, term_width, true)
|
let table_config = table_config.expand();
|
||||||
|
table.draw(table_config, term_width)
|
||||||
} else {
|
} else {
|
||||||
Some(s)
|
Some(s)
|
||||||
}
|
}
|
||||||
|
@ -760,15 +758,15 @@ fn make_clickable_link(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn convert_to_table(
|
fn convert_to_table(
|
||||||
row_offset: usize,
|
row_offset: usize,
|
||||||
input: &[Value],
|
input: &[Value],
|
||||||
ctrlc: Option<Arc<AtomicBool>>,
|
ctrlc: Option<Arc<AtomicBool>>,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
head: Span,
|
head: Span,
|
||||||
termwidth: usize,
|
|
||||||
color_hm: &NuColorMap,
|
color_hm: &NuColorMap,
|
||||||
) -> Result<Option<NuTable>, ShellError> {
|
) -> Result<Option<(NuTable, bool, bool)>, ShellError> {
|
||||||
let mut headers = get_columns(input);
|
let mut headers = get_columns(input);
|
||||||
let mut input = input.iter().peekable();
|
let mut input = input.iter().peekable();
|
||||||
let float_precision = config.float_precision as usize;
|
let float_precision = config.float_precision as usize;
|
||||||
|
@ -861,15 +859,9 @@ fn convert_to_table(
|
||||||
}
|
}
|
||||||
|
|
||||||
let count_rows = data.len();
|
let count_rows = data.len();
|
||||||
let table = NuTable::new(
|
let table = NuTable::new(data, (count_rows, count_columns));
|
||||||
data,
|
|
||||||
(count_rows, count_columns),
|
|
||||||
termwidth,
|
|
||||||
with_header,
|
|
||||||
with_index,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(Some(table))
|
Ok(Some((table, with_header, with_index)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
@ -881,12 +873,11 @@ fn convert_to_table2<'a>(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
head: Span,
|
head: Span,
|
||||||
color_hm: &NuColorMap,
|
color_hm: &NuColorMap,
|
||||||
theme: &TableTheme,
|
|
||||||
deep: Option<usize>,
|
deep: Option<usize>,
|
||||||
flatten: bool,
|
flatten: bool,
|
||||||
flatten_sep: &str,
|
flatten_sep: &str,
|
||||||
available_width: usize,
|
available_width: usize,
|
||||||
) -> Result<Option<NuTable>, ShellError> {
|
) -> Result<Option<(NuTable, bool, bool)>, ShellError> {
|
||||||
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;
|
||||||
|
@ -984,7 +975,6 @@ fn convert_to_table2<'a>(
|
||||||
config,
|
config,
|
||||||
&ctrlc,
|
&ctrlc,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep,
|
deep,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -997,9 +987,10 @@ fn convert_to_table2<'a>(
|
||||||
|
|
||||||
let count_columns = if with_index { 2 } else { 1 };
|
let count_columns = if with_index { 2 } else { 1 };
|
||||||
let size = (data.len(), count_columns);
|
let size = (data.len(), count_columns);
|
||||||
let table = NuTable::new(data, size, usize::MAX, with_header, with_index);
|
|
||||||
|
|
||||||
return Ok(Some(table));
|
let table = NuTable::new(data, size);
|
||||||
|
|
||||||
|
return Ok(Some((table, with_header, with_index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut widths = Vec::new();
|
let mut widths = Vec::new();
|
||||||
|
@ -1045,7 +1036,6 @@ fn convert_to_table2<'a>(
|
||||||
config,
|
config,
|
||||||
&ctrlc,
|
&ctrlc,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep,
|
deep,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -1162,9 +1152,9 @@ fn convert_to_table2<'a>(
|
||||||
let count_rows = data.len();
|
let count_rows = data.len();
|
||||||
let size = (count_rows, count_columns);
|
let size = (count_rows, count_columns);
|
||||||
|
|
||||||
let table = NuTable::new(data, size, usize::MAX, with_header, with_index);
|
let table = NuTable::new(data, size);
|
||||||
|
|
||||||
Ok(Some(table))
|
Ok(Some((table, with_header, with_index)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_index_value(item: &Value, config: &Config) -> Option<String> {
|
fn lookup_index_value(item: &Value, config: &Config) -> Option<String> {
|
||||||
|
@ -1210,7 +1200,6 @@ fn create_table2_entry(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
ctrlc: &Option<Arc<AtomicBool>>,
|
ctrlc: &Option<Arc<AtomicBool>>,
|
||||||
color_hm: &NuColorMap,
|
color_hm: &NuColorMap,
|
||||||
theme: &TableTheme,
|
|
||||||
deep: Option<usize>,
|
deep: Option<usize>,
|
||||||
flatten: bool,
|
flatten: bool,
|
||||||
flatten_sep: &str,
|
flatten_sep: &str,
|
||||||
|
@ -1228,7 +1217,6 @@ fn create_table2_entry(
|
||||||
config,
|
config,
|
||||||
ctrlc,
|
ctrlc,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep,
|
deep,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -1242,7 +1230,6 @@ fn create_table2_entry(
|
||||||
config,
|
config,
|
||||||
ctrlc,
|
ctrlc,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep,
|
deep,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -1266,7 +1253,6 @@ fn convert_to_table2_entry(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
ctrlc: &Option<Arc<AtomicBool>>,
|
ctrlc: &Option<Arc<AtomicBool>>,
|
||||||
color_hm: &NuColorMap,
|
color_hm: &NuColorMap,
|
||||||
theme: &TableTheme,
|
|
||||||
deep: Option<usize>,
|
deep: Option<usize>,
|
||||||
flatten: bool,
|
flatten: bool,
|
||||||
flatten_sep: &str,
|
flatten_sep: &str,
|
||||||
|
@ -1289,7 +1275,6 @@ fn convert_to_table2_entry(
|
||||||
config,
|
config,
|
||||||
*span,
|
*span,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep.map(|i| i - 1),
|
deep.map(|i| i - 1),
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -1297,9 +1282,17 @@ fn convert_to_table2_entry(
|
||||||
);
|
);
|
||||||
|
|
||||||
let inner_table = table.map(|table| {
|
let inner_table = table.map(|table| {
|
||||||
table.and_then(|table| {
|
table.and_then(|(table, with_header, with_index)| {
|
||||||
let alignments = Alignments::default();
|
let table_config = create_table_config(
|
||||||
table.draw_table(config, color_hm, alignments, theme, usize::MAX, false)
|
config,
|
||||||
|
color_hm,
|
||||||
|
table.count_rows(),
|
||||||
|
with_header,
|
||||||
|
with_index,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
table.draw(table_config, usize::MAX)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1329,7 +1322,6 @@ fn convert_to_table2_entry(
|
||||||
config,
|
config,
|
||||||
*span,
|
*span,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep.map(|i| i - 1),
|
deep.map(|i| i - 1),
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -1337,11 +1329,20 @@ fn convert_to_table2_entry(
|
||||||
);
|
);
|
||||||
|
|
||||||
let inner_table = table.map(|table| {
|
let inner_table = table.map(|table| {
|
||||||
table.and_then(|table| {
|
table.and_then(|(table, with_header, with_index)| {
|
||||||
let alignments = Alignments::default();
|
let table_config = create_table_config(
|
||||||
table.draw_table(config, color_hm, alignments, theme, usize::MAX, false)
|
config,
|
||||||
|
color_hm,
|
||||||
|
table.count_rows(),
|
||||||
|
with_header,
|
||||||
|
with_index,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
table.draw(table_config, usize::MAX)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Ok(Some(table)) = inner_table {
|
if let Ok(Some(table)) = inner_table {
|
||||||
(table, TextStyle::default())
|
(table, TextStyle::default())
|
||||||
} else {
|
} else {
|
||||||
|
@ -1445,9 +1446,10 @@ impl PagingTableCreator {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let theme = load_theme_from_config(&self.config);
|
|
||||||
let term_width = get_width_param(self.width_param);
|
let term_width = get_width_param(self.width_param);
|
||||||
let color_hm = get_color_config(&self.config);
|
let color_hm = get_color_config(&self.config);
|
||||||
|
let theme = load_theme_from_config(&self.config);
|
||||||
|
|
||||||
let table = convert_to_table2(
|
let table = convert_to_table2(
|
||||||
self.row_offset,
|
self.row_offset,
|
||||||
batch.iter(),
|
batch.iter(),
|
||||||
|
@ -1455,29 +1457,30 @@ impl PagingTableCreator {
|
||||||
&self.config,
|
&self.config,
|
||||||
self.head,
|
self.head,
|
||||||
&color_hm,
|
&color_hm,
|
||||||
&theme,
|
|
||||||
limit,
|
limit,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_separator.as_deref().unwrap_or(" "),
|
flatten_separator.as_deref().unwrap_or(" "),
|
||||||
term_width,
|
term_width,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut table = match table {
|
let (mut table, with_header, with_index) = match table {
|
||||||
Some(table) => table,
|
Some(table) => table,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
table.truncate(term_width, &theme);
|
table.truncate(term_width, &theme);
|
||||||
|
|
||||||
let table_s = table.clone().draw_table(
|
let table_config = create_table_config(
|
||||||
&self.config,
|
&self.config,
|
||||||
&color_hm,
|
&color_hm,
|
||||||
Alignments::default(),
|
table.count_rows(),
|
||||||
&theme,
|
with_header,
|
||||||
term_width,
|
with_index,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let table_s = table.clone().draw(table_config.clone(), term_width);
|
||||||
|
|
||||||
let table = match table_s {
|
let table = match table_s {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
// check whether we need to expand table or not,
|
// check whether we need to expand table or not,
|
||||||
|
@ -1489,14 +1492,8 @@ impl PagingTableCreator {
|
||||||
let used_percent = width as f32 / term_width as f32;
|
let used_percent = width as f32 / term_width as f32;
|
||||||
|
|
||||||
if width < term_width && used_percent > EXPAND_TREASHHOLD {
|
if width < term_width && used_percent > EXPAND_TREASHHOLD {
|
||||||
table.draw_table(
|
let table_config = table_config.expand();
|
||||||
&self.config,
|
table.draw(table_config, term_width)
|
||||||
&color_hm,
|
|
||||||
Alignments::default(),
|
|
||||||
&theme,
|
|
||||||
term_width,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Some(s)
|
Some(s)
|
||||||
}
|
}
|
||||||
|
@ -1538,7 +1535,6 @@ impl PagingTableCreator {
|
||||||
fn build_general(&self, batch: &[Value]) -> Result<Option<String>, ShellError> {
|
fn build_general(&self, batch: &[Value]) -> Result<Option<String>, ShellError> {
|
||||||
let term_width = get_width_param(self.width_param);
|
let term_width = get_width_param(self.width_param);
|
||||||
let color_hm = get_color_config(&self.config);
|
let color_hm = get_color_config(&self.config);
|
||||||
let theme = load_theme_from_config(&self.config);
|
|
||||||
|
|
||||||
let table = convert_to_table(
|
let table = convert_to_table(
|
||||||
self.row_offset,
|
self.row_offset,
|
||||||
|
@ -1546,24 +1542,25 @@ impl PagingTableCreator {
|
||||||
self.ctrlc.clone(),
|
self.ctrlc.clone(),
|
||||||
&self.config,
|
&self.config,
|
||||||
self.head,
|
self.head,
|
||||||
term_width,
|
|
||||||
&color_hm,
|
&color_hm,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let table = match table {
|
let (table, with_header, with_index) = match table {
|
||||||
Some(table) => table,
|
Some(table) => table,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let table = table.draw_table(
|
let table_config = create_table_config(
|
||||||
&self.config,
|
&self.config,
|
||||||
&color_hm,
|
&color_hm,
|
||||||
Alignments::default(),
|
table.count_rows(),
|
||||||
&theme,
|
with_index,
|
||||||
term_width,
|
with_header,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let table = table.draw(table_config, term_width);
|
||||||
|
|
||||||
Ok(table)
|
Ok(table)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1617,8 +1614,12 @@ impl Iterator for PagingTableCreator {
|
||||||
|
|
||||||
match table {
|
match table {
|
||||||
Ok(Some(table)) => {
|
Ok(Some(table)) => {
|
||||||
|
let table =
|
||||||
|
strip_output_color(Some(table), &self.config).expect("must never happen");
|
||||||
|
|
||||||
let mut bytes = table.as_bytes().to_vec();
|
let mut bytes = table.as_bytes().to_vec();
|
||||||
bytes.push(b'\n'); // tabled tables don't come with a newline on the end
|
bytes.push(b'\n'); // nu-table tables don't come with a newline on the end
|
||||||
|
|
||||||
Some(Ok(bytes))
|
Some(Ok(bytes))
|
||||||
}
|
}
|
||||||
Err(err) => Some(Err(err)),
|
Err(err) => Some(Err(err)),
|
||||||
|
@ -1696,3 +1697,59 @@ enum TableView {
|
||||||
flatten_separator: Option<String>,
|
flatten_separator: Option<String>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn strip_output_color(output: Option<String>, config: &Config) -> Option<String> {
|
||||||
|
match output {
|
||||||
|
Some(output) => {
|
||||||
|
// the atty is for when people do ls from vim, there should be no coloring there
|
||||||
|
if !config.use_ansi_coloring || !atty::is(atty::Stream::Stdout) {
|
||||||
|
// Draw the table without ansi colors
|
||||||
|
Some(nu_utils::strip_ansi_string_likely(output))
|
||||||
|
} else {
|
||||||
|
// Draw the table with ansi colors
|
||||||
|
Some(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_table_config(
|
||||||
|
config: &Config,
|
||||||
|
color_hm: &HashMap<String, nu_ansi_term::Style>,
|
||||||
|
count_records: usize,
|
||||||
|
with_header: bool,
|
||||||
|
with_index: bool,
|
||||||
|
expand: bool,
|
||||||
|
) -> TableConfig {
|
||||||
|
let theme = load_theme_from_config(config);
|
||||||
|
let append_footer = with_footer(config, with_header, count_records);
|
||||||
|
|
||||||
|
let mut table_cfg = TableConfig::new(theme, with_header, with_index, append_footer);
|
||||||
|
|
||||||
|
let sep_color = lookup_separator_color(color_hm);
|
||||||
|
if let Some(color) = sep_color {
|
||||||
|
table_cfg = table_cfg.splitline_style(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if expand {
|
||||||
|
table_cfg = table_cfg.expand();
|
||||||
|
}
|
||||||
|
|
||||||
|
table_cfg.trim(config.trim_strategy.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_separator_color(
|
||||||
|
color_hm: &HashMap<String, nu_ansi_term::Style>,
|
||||||
|
) -> Option<nu_ansi_term::Style> {
|
||||||
|
color_hm.get("separator").cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_footer(config: &Config, with_header: bool, count_records: usize) -> bool {
|
||||||
|
with_header && need_footer(config, count_records as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn need_footer(config: &Config, count_records: u64) -> bool {
|
||||||
|
matches!(config.footer_mode, FooterMode::RowCount(limit) if count_records > limit)
|
||||||
|
|| matches!(config.footer_mode, FooterMode::Always)
|
||||||
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,8 @@
|
||||||
use nu_color_config::{get_color_config, style_primitive};
|
use nu_color_config::{get_color_config, style_primitive};
|
||||||
use nu_engine::column::get_columns;
|
use nu_engine::column::get_columns;
|
||||||
|
use nu_protocol::FooterMode;
|
||||||
use nu_protocol::{ast::PathMember, Config, ShellError, Span, TableIndexMode, Value};
|
use nu_protocol::{ast::PathMember, Config, ShellError, Span, TableIndexMode, Value};
|
||||||
use nu_table::{string_width, Alignment, Alignments, Table as NuTable, TableTheme, TextStyle};
|
use nu_table::{string_width, Alignment, Table as NuTable, TableConfig, TableTheme, TextStyle};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{
|
use std::{
|
||||||
cmp::max,
|
cmp::max,
|
||||||
|
@ -21,10 +22,8 @@ pub fn try_build_table(
|
||||||
color_hm: &NuStyleTable,
|
color_hm: &NuStyleTable,
|
||||||
value: Value,
|
value: Value,
|
||||||
) -> String {
|
) -> String {
|
||||||
let theme = load_theme_from_config(config);
|
|
||||||
|
|
||||||
match value {
|
match value {
|
||||||
Value::List { vals, span } => try_build_list(vals, &ctrlc, config, span, color_hm, theme),
|
Value::List { vals, span } => try_build_list(vals, &ctrlc, config, span, color_hm),
|
||||||
Value::Record { cols, vals, span } => {
|
Value::Record { cols, vals, span } => {
|
||||||
try_build_map(cols, vals, span, ctrlc, config, color_hm)
|
try_build_map(cols, vals, span, ctrlc, config, color_hm)
|
||||||
}
|
}
|
||||||
|
@ -65,7 +64,6 @@ fn try_build_list(
|
||||||
config: &NuConfig,
|
config: &NuConfig,
|
||||||
span: Span,
|
span: Span,
|
||||||
color_hm: &HashMap<String, nu_ansi_term::Style>,
|
color_hm: &HashMap<String, nu_ansi_term::Style>,
|
||||||
theme: TableTheme,
|
|
||||||
) -> String {
|
) -> String {
|
||||||
let table = convert_to_table2(
|
let table = convert_to_table2(
|
||||||
0,
|
0,
|
||||||
|
@ -74,23 +72,24 @@ fn try_build_list(
|
||||||
config,
|
config,
|
||||||
span,
|
span,
|
||||||
color_hm,
|
color_hm,
|
||||||
&theme,
|
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
"",
|
"",
|
||||||
usize::MAX,
|
usize::MAX,
|
||||||
);
|
);
|
||||||
match table {
|
match table {
|
||||||
Ok(Some(table)) => {
|
Ok(Some((table, with_header, with_index))) => {
|
||||||
let val = table.draw_table(
|
let table_config = create_table_config(
|
||||||
config,
|
config,
|
||||||
color_hm,
|
color_hm,
|
||||||
Alignments::default(),
|
table.count_rows(),
|
||||||
&theme,
|
with_header,
|
||||||
usize::MAX,
|
with_index,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let val = table.draw(table_config, usize::MAX);
|
||||||
|
|
||||||
match val {
|
match val {
|
||||||
Some(result) => result,
|
Some(result) => result,
|
||||||
None => value_to_styled_string(&Value::List { vals, span }, config, color_hm).0,
|
None => value_to_styled_string(&Value::List { vals, span }, config, color_hm).0,
|
||||||
|
@ -104,7 +103,7 @@ fn try_build_list(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn build_expanded_table(
|
fn build_expanded_table(
|
||||||
cols: Vec<String>,
|
cols: Vec<String>,
|
||||||
vals: Vec<Value>,
|
vals: Vec<Value>,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
@ -115,16 +114,18 @@ pub fn build_expanded_table(
|
||||||
flatten: bool,
|
flatten: bool,
|
||||||
flatten_sep: &str,
|
flatten_sep: &str,
|
||||||
) -> Result<Option<String>, ShellError> {
|
) -> Result<Option<String>, ShellError> {
|
||||||
let theme = load_theme_from_config(config);
|
|
||||||
let color_hm = get_color_config(config);
|
let color_hm = get_color_config(config);
|
||||||
let alignments = Alignments::default();
|
let theme = load_theme_from_config(config);
|
||||||
|
|
||||||
// calculate the width of a key part + the rest of table so we know the rest of the table width available for value.
|
// calculate the width of a key part + the rest of table so we know the rest of the table width available for value.
|
||||||
let key_width = cols.iter().map(|col| string_width(col)).max().unwrap_or(0);
|
let key_width = cols.iter().map(|col| string_width(col)).max().unwrap_or(0);
|
||||||
let key = NuTable::create_cell(" ".repeat(key_width), TextStyle::default());
|
let key = NuTable::create_cell(" ".repeat(key_width), TextStyle::default());
|
||||||
let key_table = NuTable::new(vec![vec![key]], (1, 2), term_width, false, false);
|
let key_table = NuTable::new(vec![vec![key]], (1, 2));
|
||||||
let key_width = key_table
|
let key_width = key_table
|
||||||
.draw_table(config, &color_hm, alignments, &theme, usize::MAX, false)
|
.draw(
|
||||||
|
create_table_config(config, &color_hm, 1, false, false, false),
|
||||||
|
usize::MAX,
|
||||||
|
)
|
||||||
.map(|table| string_width(&table))
|
.map(|table| string_width(&table))
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
@ -161,7 +162,6 @@ pub fn build_expanded_table(
|
||||||
config,
|
config,
|
||||||
span,
|
span,
|
||||||
&color_hm,
|
&color_hm,
|
||||||
&theme,
|
|
||||||
deep,
|
deep,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -169,21 +169,23 @@ pub fn build_expanded_table(
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
match table {
|
match table {
|
||||||
Some(mut table) => {
|
Some((mut table, with_header, with_index)) => {
|
||||||
// controll width via removing table columns.
|
// controll width via removing table columns.
|
||||||
let theme = load_theme_from_config(config);
|
let theme = load_theme_from_config(config);
|
||||||
table.truncate(remaining_width, &theme);
|
table.truncate(remaining_width, &theme);
|
||||||
|
|
||||||
is_expanded = true;
|
is_expanded = true;
|
||||||
|
|
||||||
let val = table.draw_table(
|
let table_config = create_table_config(
|
||||||
config,
|
config,
|
||||||
&color_hm,
|
&color_hm,
|
||||||
alignments,
|
table.count_rows(),
|
||||||
&theme,
|
with_header,
|
||||||
remaining_width,
|
with_index,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let val = table.draw(table_config, remaining_width);
|
||||||
match val {
|
match val {
|
||||||
Some(result) => result,
|
Some(result) => result,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
|
@ -247,12 +249,12 @@ pub fn build_expanded_table(
|
||||||
data.push(row);
|
data.push(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
let data_len = data.len();
|
let table_config = create_table_config(config, &color_hm, data.len(), false, false, false);
|
||||||
let table = NuTable::new(data, (data_len, 2), term_width, false, false);
|
|
||||||
|
|
||||||
let table_s = table
|
let data_len = data.len();
|
||||||
.clone()
|
let table = NuTable::new(data, (data_len, 2));
|
||||||
.draw_table(config, &color_hm, alignments, &theme, term_width, false);
|
|
||||||
|
let table_s = table.clone().draw(table_config.clone(), term_width);
|
||||||
|
|
||||||
let table = match table_s {
|
let table = match table_s {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
|
@ -265,7 +267,8 @@ pub fn build_expanded_table(
|
||||||
let used_percent = width as f32 / term_width as f32;
|
let used_percent = width as f32 / term_width as f32;
|
||||||
|
|
||||||
if width < term_width && used_percent > EXPAND_TREASHHOLD {
|
if width < term_width && used_percent > EXPAND_TREASHHOLD {
|
||||||
table.draw_table(config, &color_hm, alignments, &theme, term_width, true)
|
let table_config = table_config.expand();
|
||||||
|
table.draw(table_config, term_width)
|
||||||
} else {
|
} else {
|
||||||
Some(s)
|
Some(s)
|
||||||
}
|
}
|
||||||
|
@ -285,12 +288,11 @@ fn convert_to_table2<'a>(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
head: Span,
|
head: Span,
|
||||||
color_hm: &NuColorMap,
|
color_hm: &NuColorMap,
|
||||||
theme: &TableTheme,
|
|
||||||
deep: Option<usize>,
|
deep: Option<usize>,
|
||||||
flatten: bool,
|
flatten: bool,
|
||||||
flatten_sep: &str,
|
flatten_sep: &str,
|
||||||
available_width: usize,
|
available_width: usize,
|
||||||
) -> Result<Option<NuTable>, ShellError> {
|
) -> Result<Option<(NuTable, bool, bool)>, ShellError> {
|
||||||
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;
|
||||||
|
@ -338,8 +340,6 @@ fn convert_to_table2<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (row, item) in input.clone().into_iter().enumerate() {
|
for (row, item) in input.clone().into_iter().enumerate() {
|
||||||
let row = if with_header { row + 1 } else { row };
|
|
||||||
|
|
||||||
if let Some(ctrlc) = &ctrlc {
|
if let Some(ctrlc) = &ctrlc {
|
||||||
if ctrlc.load(Ordering::SeqCst) {
|
if ctrlc.load(Ordering::SeqCst) {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
|
@ -361,6 +361,8 @@ fn convert_to_table2<'a>(
|
||||||
column_width = max(column_width, width);
|
column_width = max(column_width, width);
|
||||||
|
|
||||||
let value = NuTable::create_cell(value.0, value.1);
|
let value = NuTable::create_cell(value.0, value.1);
|
||||||
|
|
||||||
|
let row = if with_header { row + 1 } else { row };
|
||||||
data[row].push(value);
|
data[row].push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +390,6 @@ fn convert_to_table2<'a>(
|
||||||
config,
|
config,
|
||||||
&ctrlc,
|
&ctrlc,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep,
|
deep,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -401,9 +402,10 @@ fn convert_to_table2<'a>(
|
||||||
|
|
||||||
let count_columns = if with_index { 2 } else { 1 };
|
let count_columns = if with_index { 2 } else { 1 };
|
||||||
let size = (data.len(), count_columns);
|
let size = (data.len(), count_columns);
|
||||||
let table = NuTable::new(data, size, usize::MAX, with_header, with_index);
|
|
||||||
|
|
||||||
return Ok(Some(table));
|
let table = NuTable::new(data, size);
|
||||||
|
|
||||||
|
return Ok(Some((table, with_header, with_index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut widths = Vec::new();
|
let mut widths = Vec::new();
|
||||||
|
@ -449,7 +451,6 @@ fn convert_to_table2<'a>(
|
||||||
config,
|
config,
|
||||||
&ctrlc,
|
&ctrlc,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep,
|
deep,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -566,9 +567,9 @@ fn convert_to_table2<'a>(
|
||||||
let count_rows = data.len();
|
let count_rows = data.len();
|
||||||
let size = (count_rows, count_columns);
|
let size = (count_rows, count_columns);
|
||||||
|
|
||||||
let table = NuTable::new(data, size, usize::MAX, with_header, with_index);
|
let table = NuTable::new(data, size);
|
||||||
|
|
||||||
Ok(Some(table))
|
Ok(Some((table, with_header, with_index)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_index_value(item: &Value, config: &Config) -> Option<String> {
|
fn lookup_index_value(item: &Value, config: &Config) -> Option<String> {
|
||||||
|
@ -614,7 +615,6 @@ fn create_table2_entry(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
ctrlc: &Option<Arc<AtomicBool>>,
|
ctrlc: &Option<Arc<AtomicBool>>,
|
||||||
color_hm: &NuColorMap,
|
color_hm: &NuColorMap,
|
||||||
theme: &TableTheme,
|
|
||||||
deep: Option<usize>,
|
deep: Option<usize>,
|
||||||
flatten: bool,
|
flatten: bool,
|
||||||
flatten_sep: &str,
|
flatten_sep: &str,
|
||||||
|
@ -632,7 +632,6 @@ fn create_table2_entry(
|
||||||
config,
|
config,
|
||||||
ctrlc,
|
ctrlc,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep,
|
deep,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -646,7 +645,6 @@ fn create_table2_entry(
|
||||||
config,
|
config,
|
||||||
ctrlc,
|
ctrlc,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep,
|
deep,
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -670,7 +668,6 @@ fn convert_to_table2_entry(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
ctrlc: &Option<Arc<AtomicBool>>,
|
ctrlc: &Option<Arc<AtomicBool>>,
|
||||||
color_hm: &NuColorMap,
|
color_hm: &NuColorMap,
|
||||||
theme: &TableTheme,
|
|
||||||
deep: Option<usize>,
|
deep: Option<usize>,
|
||||||
flatten: bool,
|
flatten: bool,
|
||||||
flatten_sep: &str,
|
flatten_sep: &str,
|
||||||
|
@ -693,7 +690,6 @@ fn convert_to_table2_entry(
|
||||||
config,
|
config,
|
||||||
*span,
|
*span,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep.map(|i| i - 1),
|
deep.map(|i| i - 1),
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -701,9 +697,17 @@ fn convert_to_table2_entry(
|
||||||
);
|
);
|
||||||
|
|
||||||
let inner_table = table.map(|table| {
|
let inner_table = table.map(|table| {
|
||||||
table.and_then(|table| {
|
table.and_then(|(table, with_header, with_index)| {
|
||||||
let alignments = Alignments::default();
|
let table_config = create_table_config(
|
||||||
table.draw_table(config, color_hm, alignments, theme, usize::MAX, false)
|
config,
|
||||||
|
color_hm,
|
||||||
|
table.count_rows(),
|
||||||
|
with_header,
|
||||||
|
with_index,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
table.draw(table_config, usize::MAX)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -733,7 +737,6 @@ fn convert_to_table2_entry(
|
||||||
config,
|
config,
|
||||||
*span,
|
*span,
|
||||||
color_hm,
|
color_hm,
|
||||||
theme,
|
|
||||||
deep.map(|i| i - 1),
|
deep.map(|i| i - 1),
|
||||||
flatten,
|
flatten,
|
||||||
flatten_sep,
|
flatten_sep,
|
||||||
|
@ -741,11 +744,20 @@ fn convert_to_table2_entry(
|
||||||
);
|
);
|
||||||
|
|
||||||
let inner_table = table.map(|table| {
|
let inner_table = table.map(|table| {
|
||||||
table.and_then(|table| {
|
table.and_then(|(table, with_header, with_index)| {
|
||||||
let alignments = Alignments::default();
|
let table_config = create_table_config(
|
||||||
table.draw_table(config, color_hm, alignments, theme, usize::MAX, false)
|
config,
|
||||||
|
color_hm,
|
||||||
|
table.count_rows(),
|
||||||
|
with_header,
|
||||||
|
with_index,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
table.draw(table_config, usize::MAX)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Ok(Some(table)) = inner_table {
|
if let Ok(Some(table)) = inner_table {
|
||||||
(table, TextStyle::default())
|
(table, TextStyle::default())
|
||||||
} else {
|
} else {
|
||||||
|
@ -842,3 +854,43 @@ fn load_theme_from_config(config: &Config) -> TableTheme {
|
||||||
_ => nu_table::TableTheme::rounded(),
|
_ => nu_table::TableTheme::rounded(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_table_config(
|
||||||
|
config: &Config,
|
||||||
|
color_hm: &HashMap<String, nu_ansi_term::Style>,
|
||||||
|
count_records: usize,
|
||||||
|
with_header: bool,
|
||||||
|
with_index: bool,
|
||||||
|
expand: bool,
|
||||||
|
) -> TableConfig {
|
||||||
|
let theme = load_theme_from_config(config);
|
||||||
|
let append_footer = with_footer(config, with_header, count_records);
|
||||||
|
|
||||||
|
let mut table_cfg = TableConfig::new(theme, with_header, with_index, append_footer);
|
||||||
|
|
||||||
|
let sep_color = lookup_separator_color(color_hm);
|
||||||
|
if let Some(color) = sep_color {
|
||||||
|
table_cfg = table_cfg.splitline_style(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if expand {
|
||||||
|
table_cfg = table_cfg.expand();
|
||||||
|
}
|
||||||
|
|
||||||
|
table_cfg.trim(config.trim_strategy.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_separator_color(
|
||||||
|
color_hm: &HashMap<String, nu_ansi_term::Style>,
|
||||||
|
) -> Option<nu_ansi_term::Style> {
|
||||||
|
color_hm.get("separator").cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_footer(config: &Config, with_header: bool, count_records: usize) -> bool {
|
||||||
|
with_header && need_footer(config, count_records as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn need_footer(config: &Config, count_records: u64) -> bool {
|
||||||
|
matches!(config.footer_mode, FooterMode::RowCount(limit) if count_records > limit)
|
||||||
|
|| matches!(config.footer_mode, FooterMode::Always)
|
||||||
|
}
|
||||||
|
|
|
@ -185,6 +185,18 @@ pub enum TrimStrategy {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TrimStrategy {
|
||||||
|
pub fn wrap(dont_split_words: bool) -> Self {
|
||||||
|
Self::Wrap {
|
||||||
|
try_to_keep_words: dont_split_words,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn truncate(suffix: Option<String>) -> Self {
|
||||||
|
Self::Truncate { suffix }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct ExploreConfig {
|
pub struct ExploreConfig {
|
||||||
pub color_config: HashMap<String, Value>,
|
pub color_config: HashMap<String, Value>,
|
||||||
|
|
|
@ -11,7 +11,6 @@ version = "0.72.2"
|
||||||
nu-ansi-term = "0.46.0"
|
nu-ansi-term = "0.46.0"
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.72.2" }
|
nu-protocol = { path = "../nu-protocol", version = "0.72.2" }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.72.2" }
|
nu-utils = { path = "../nu-utils", version = "0.72.2" }
|
||||||
atty = "0.2.14"
|
|
||||||
tabled = { version = "0.10.0", features = ["color"], default-features = false }
|
tabled = { version = "0.10.0", features = ["color"], default-features = false }
|
||||||
json_to_table = { version = "0.2.0", features = ["color"] }
|
json_to_table = { version = "0.3.1", features = ["color"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
use nu_protocol::Config;
|
use nu_table::{Table, TableConfig, TableTheme, TextStyle};
|
||||||
use nu_table::{Alignments, Table, TableTheme, TextStyle};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use tabled::papergrid::records::{cell_info::CellInfo, tcell::TCell};
|
use tabled::papergrid::records::{cell_info::CellInfo, tcell::TCell};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -19,30 +17,28 @@ fn main() {
|
||||||
|
|
||||||
// The mocked up table data
|
// The mocked up table data
|
||||||
let (table_headers, row_data) = make_table_data();
|
let (table_headers, row_data) = make_table_data();
|
||||||
|
|
||||||
// The table headers
|
// The table headers
|
||||||
let headers = vec_of_str_to_vec_of_styledstr(&table_headers, true);
|
let headers = vec_of_str_to_vec_of_styledstr(&table_headers, true);
|
||||||
|
|
||||||
// The table rows
|
// The table rows
|
||||||
let rows = vec_of_str_to_vec_of_styledstr(&row_data, false);
|
let rows = vec_of_str_to_vec_of_styledstr(&row_data, false);
|
||||||
|
|
||||||
// The table itself
|
// The table itself
|
||||||
let count_cols = std::cmp::max(rows.len(), headers.len());
|
let count_cols = std::cmp::max(rows.len(), headers.len());
|
||||||
let mut rows = vec![rows; 3];
|
let mut rows = vec![rows; 3];
|
||||||
rows.insert(0, headers);
|
rows.insert(0, headers);
|
||||||
let table = Table::new(rows, (3, count_cols), width, true, false);
|
|
||||||
// FIXME: Config isn't available from here so just put these here to compile
|
let theme = TableTheme::rounded();
|
||||||
let color_hm: HashMap<String, nu_ansi_term::Style> = HashMap::new();
|
let table_cfg = TableConfig::new(theme, true, false, false);
|
||||||
// get the default config
|
|
||||||
let config = Config::default();
|
let table = Table::new(rows, (3, count_cols));
|
||||||
|
|
||||||
// Capture the table as a string
|
// Capture the table as a string
|
||||||
let output_table = table
|
let output_table = table
|
||||||
.draw_table(
|
.draw(table_cfg, width)
|
||||||
&config,
|
|
||||||
&color_hm,
|
|
||||||
Alignments::default(),
|
|
||||||
&TableTheme::rounded(),
|
|
||||||
width,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.unwrap_or_else(|| format!("Couldn't fit table into {} columns!", width));
|
.unwrap_or_else(|| format!("Couldn't fit table into {} columns!", width));
|
||||||
|
|
||||||
// Draw the table
|
// Draw the table
|
||||||
println!("{}", output_table)
|
println!("{}", output_table)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,54 +2,10 @@ mod nu_protocol_table;
|
||||||
mod table;
|
mod table;
|
||||||
mod table_theme;
|
mod table_theme;
|
||||||
mod textstyle;
|
mod textstyle;
|
||||||
|
mod util;
|
||||||
|
|
||||||
pub use nu_protocol_table::NuTable;
|
pub use nu_protocol_table::NuTable;
|
||||||
pub use table::{Alignments, Table};
|
pub use table::{Alignments, Table, TableConfig};
|
||||||
pub use table_theme::TableTheme;
|
pub use table_theme::TableTheme;
|
||||||
pub use textstyle::{Alignment, TextStyle};
|
pub use textstyle::{Alignment, TextStyle};
|
||||||
|
pub use util::*;
|
||||||
use tabled::{Padding, Style, Width};
|
|
||||||
|
|
||||||
pub fn string_width(text: &str) -> usize {
|
|
||||||
tabled::papergrid::util::string_width_multiline_tab(text, 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wrap_string(text: &str, width: usize) -> String {
|
|
||||||
// well... it's not effitient to build a table to wrap a string,
|
|
||||||
// but ... it's better than a copy paste
|
|
||||||
tabled::builder::Builder::from_iter([[text]])
|
|
||||||
.build()
|
|
||||||
.with(Padding::zero())
|
|
||||||
.with(Style::empty())
|
|
||||||
.with(Width::wrap(width))
|
|
||||||
.to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn string_truncate(text: &str, width: usize) -> String {
|
|
||||||
// todo: change me...
|
|
||||||
|
|
||||||
match text.lines().next() {
|
|
||||||
Some(first_line) => tabled::builder::Builder::from_iter([[first_line]])
|
|
||||||
.build()
|
|
||||||
.with(tabled::Style::empty())
|
|
||||||
.with(tabled::Padding::zero())
|
|
||||||
.with(tabled::Width::truncate(width))
|
|
||||||
.to_string(),
|
|
||||||
None => String::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn string_wrap(text: &str, width: usize) -> String {
|
|
||||||
// todo: change me...
|
|
||||||
|
|
||||||
if text.is_empty() {
|
|
||||||
return String::new();
|
|
||||||
}
|
|
||||||
|
|
||||||
tabled::builder::Builder::from_iter([[text]])
|
|
||||||
.build()
|
|
||||||
.with(tabled::Style::empty())
|
|
||||||
.with(tabled::Padding::zero())
|
|
||||||
.with(tabled::Width::wrap(width))
|
|
||||||
.to_string()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use nu_protocol::{Config, Span, Value};
|
use nu_protocol::{Config, Span, Value};
|
||||||
use tabled::{color::Color, papergrid::records::Records, Table};
|
use tabled::{
|
||||||
|
color::Color, formatting::AlignmentStrategy, object::Segment, papergrid::records::Records,
|
||||||
|
Alignment, Modify, Table,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{table::TrimStrategyModifier, TableTheme};
|
use crate::{table::TrimStrategyModifier, Alignments, TableTheme};
|
||||||
|
|
||||||
/// NuTable has a recursive table representation of nu_prorocol::Value.
|
/// NuTable has a recursive table representation of nu_prorocol::Value.
|
||||||
///
|
///
|
||||||
|
@ -215,4 +218,10 @@ fn load_theme<R>(
|
||||||
table.with(color);
|
table.with(color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.with(
|
||||||
|
Modify::new(Segment::all())
|
||||||
|
.with(Alignment::Horizontal(Alignments::default().data))
|
||||||
|
.with(AlignmentStrategy::PerLine),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{collections::HashMap, fmt::Display};
|
use std::{cmp::min, collections::HashMap, fmt::Display};
|
||||||
|
|
||||||
use nu_protocol::{Config, FooterMode, TrimStrategy};
|
use nu_ansi_term::Style;
|
||||||
|
use nu_protocol::TrimStrategy;
|
||||||
use tabled::{
|
use tabled::{
|
||||||
alignment::AlignmentHorizontal,
|
alignment::AlignmentHorizontal,
|
||||||
builder::Builder,
|
builder::Builder,
|
||||||
|
@ -12,8 +13,11 @@ use tabled::{
|
||||||
records::{
|
records::{
|
||||||
cell_info::CellInfo, tcell::TCell, vec_records::VecRecords, Records, RecordsMut,
|
cell_info::CellInfo, tcell::TCell, vec_records::VecRecords, Records, RecordsMut,
|
||||||
},
|
},
|
||||||
|
util::string_width_multiline,
|
||||||
width::CfgWidthFunction,
|
width::CfgWidthFunction,
|
||||||
|
Estimate,
|
||||||
},
|
},
|
||||||
|
peaker::Peaker,
|
||||||
Alignment, Modify, ModifyObject, TableOption, Width,
|
Alignment, Modify, ModifyObject, TableOption, Width,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,9 +27,6 @@ use crate::{table_theme::TableTheme, TextStyle};
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
data: Data,
|
data: Data,
|
||||||
is_empty: bool,
|
|
||||||
with_header: bool,
|
|
||||||
with_index: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Data = VecRecords<TCell<CellInfo<'static>, TextStyle>>;
|
type Data = VecRecords<TCell<CellInfo<'static>, TextStyle>>;
|
||||||
|
@ -34,33 +35,22 @@ impl Table {
|
||||||
/// Creates a [Table] instance.
|
/// Creates a [Table] instance.
|
||||||
///
|
///
|
||||||
/// If `headers.is_empty` then no headers will be rendered.
|
/// If `headers.is_empty` then no headers will be rendered.
|
||||||
pub fn new(
|
pub fn new(data: Vec<Vec<TCell<CellInfo<'static>, TextStyle>>>, size: (usize, usize)) -> Table {
|
||||||
mut data: Vec<Vec<TCell<CellInfo<'static>, TextStyle>>>,
|
|
||||||
size: (usize, usize),
|
|
||||||
termwidth: usize,
|
|
||||||
with_header: bool,
|
|
||||||
with_index: bool,
|
|
||||||
) -> Table {
|
|
||||||
// it's not guaranted that data will have all rows with the same number of columns.
|
// it's not guaranted that data will have all rows with the same number of columns.
|
||||||
// but VecRecords::with_hint require this constrain.
|
// but VecRecords::with_hint require this constrain.
|
||||||
for row in &mut data {
|
//
|
||||||
if row.len() < size.1 {
|
// so we do a check to make it certainly true
|
||||||
row.extend(
|
|
||||||
std::iter::repeat(Self::create_cell(String::default(), TextStyle::default()))
|
|
||||||
.take(size.1 - row.len()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut data = VecRecords::with_hint(data, size.1);
|
let mut data = data;
|
||||||
let is_empty = maybe_truncate_columns(&mut data, size.1, termwidth);
|
make_data_consistent(&mut data, size);
|
||||||
|
|
||||||
Table {
|
let data = VecRecords::with_hint(data, size.1);
|
||||||
data,
|
|
||||||
is_empty,
|
Table { data }
|
||||||
with_header,
|
}
|
||||||
with_index,
|
|
||||||
}
|
pub fn count_rows(&self) -> usize {
|
||||||
|
self.data.count_rows()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_cell(
|
pub fn create_cell(
|
||||||
|
@ -70,29 +60,15 @@ impl Table {
|
||||||
TCell::new(CellInfo::new(text.into(), CfgWidthFunction::new(4)), style)
|
TCell::new(CellInfo::new(text.into(), CfgWidthFunction::new(4)), style)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
|
||||||
self.is_empty
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size(&self) -> (usize, usize) {
|
|
||||||
(self.data.count_rows(), self.data.count_columns())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_with_index(&self) -> bool {
|
|
||||||
self.with_index
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn truncate(&mut self, width: usize, theme: &TableTheme) -> bool {
|
pub fn truncate(&mut self, width: usize, theme: &TableTheme) -> bool {
|
||||||
let mut truncated = false;
|
let mut truncated = false;
|
||||||
while self.data.count_rows() > 0 && self.data.count_columns() > 0 {
|
while self.data.count_rows() > 0 && self.data.count_columns() > 0 {
|
||||||
let mut table = Builder::custom(self.data.clone()).build();
|
let total;
|
||||||
load_theme(&mut table, &HashMap::new(), theme, false, false);
|
{
|
||||||
let total = table.total_width();
|
let mut table = Builder::custom(self.data.clone()).build();
|
||||||
|
load_theme(&mut table, theme, false, false, None);
|
||||||
// println!("{}", table);
|
total = table.total_width();
|
||||||
// println!("width={:?} total={:?}", width, total);
|
}
|
||||||
|
|
||||||
drop(table);
|
|
||||||
|
|
||||||
if total > width {
|
if total > width {
|
||||||
truncated = true;
|
truncated = true;
|
||||||
|
@ -117,19 +93,69 @@ impl Table {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draws a trable on a String.
|
/// Converts a table to a String.
|
||||||
///
|
///
|
||||||
/// It returns None in case where table cannot be fit to a terminal width.
|
/// It returns None in case where table cannot be fit to a terminal width.
|
||||||
pub fn draw_table(
|
pub fn draw(self, config: TableConfig, termwidth: usize) -> Option<String> {
|
||||||
self,
|
build_table(self.data, config, termwidth)
|
||||||
config: &Config,
|
}
|
||||||
color_hm: &HashMap<String, nu_ansi_term::Style>,
|
}
|
||||||
alignments: Alignments,
|
|
||||||
theme: &TableTheme,
|
fn make_data_consistent(data: &mut Vec<Vec<TCell<CellInfo, TextStyle>>>, size: (usize, usize)) {
|
||||||
termwidth: usize,
|
for row in data {
|
||||||
expand: bool,
|
if row.len() < size.1 {
|
||||||
) -> Option<String> {
|
row.extend(
|
||||||
draw_table(self, config, color_hm, alignments, theme, termwidth, expand)
|
std::iter::repeat(Table::create_cell(String::default(), TextStyle::default()))
|
||||||
|
.take(size.1 - row.len()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TableConfig {
|
||||||
|
theme: TableTheme,
|
||||||
|
alignments: Alignments,
|
||||||
|
trim: TrimStrategy,
|
||||||
|
split_color: Option<Style>,
|
||||||
|
expand: bool,
|
||||||
|
with_index: bool,
|
||||||
|
with_header: bool,
|
||||||
|
with_footer: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TableConfig {
|
||||||
|
pub fn new(
|
||||||
|
theme: TableTheme,
|
||||||
|
with_header: bool,
|
||||||
|
with_index: bool,
|
||||||
|
append_footer: bool,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
theme,
|
||||||
|
with_header,
|
||||||
|
with_index,
|
||||||
|
with_footer: append_footer,
|
||||||
|
expand: false,
|
||||||
|
alignments: Alignments::default(),
|
||||||
|
trim: TrimStrategy::truncate(None),
|
||||||
|
split_color: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expand(mut self) -> Self {
|
||||||
|
self.expand = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trim(mut self, strategy: TrimStrategy) -> Self {
|
||||||
|
self.trim = strategy;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn splitline_style(mut self, color: Style) -> Self {
|
||||||
|
self.split_color = Some(color);
|
||||||
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,65 +176,63 @@ impl Default for Alignments {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_table(
|
fn build_table(mut data: Data, cfg: TableConfig, termwidth: usize) -> Option<String> {
|
||||||
mut table: Table,
|
let priority = TruncationPriority::Content;
|
||||||
config: &Config,
|
let is_empty = maybe_truncate_columns(&mut data, &cfg.theme, termwidth, priority);
|
||||||
color_hm: &HashMap<String, nu_ansi_term::Style>,
|
|
||||||
alignments: Alignments,
|
if is_empty {
|
||||||
theme: &TableTheme,
|
|
||||||
termwidth: usize,
|
|
||||||
expand: bool,
|
|
||||||
) -> Option<String> {
|
|
||||||
if table.is_empty {
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let with_header = table.with_header;
|
if cfg.with_footer {
|
||||||
let with_footer = with_header && need_footer(config, (table.data).size().0 as u64);
|
data.duplicate_row(0);
|
||||||
let with_index = table.with_index;
|
|
||||||
|
|
||||||
if with_footer {
|
|
||||||
table.data.duplicate_row(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut table = Builder::custom(table.data).build();
|
draw_table(
|
||||||
load_theme(&mut table, color_hm, theme, with_footer, with_header);
|
data,
|
||||||
|
&cfg.theme,
|
||||||
|
cfg.alignments,
|
||||||
|
cfg.with_index,
|
||||||
|
cfg.with_header,
|
||||||
|
cfg.with_footer,
|
||||||
|
cfg.expand,
|
||||||
|
cfg.split_color,
|
||||||
|
&cfg.trim,
|
||||||
|
termwidth,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn draw_table(
|
||||||
|
data: Data,
|
||||||
|
theme: &TableTheme,
|
||||||
|
alignments: Alignments,
|
||||||
|
with_index: bool,
|
||||||
|
with_header: bool,
|
||||||
|
with_footer: bool,
|
||||||
|
expand: bool,
|
||||||
|
split_color: Option<Style>,
|
||||||
|
trim_strategy: &TrimStrategy,
|
||||||
|
termwidth: usize,
|
||||||
|
) -> Option<String> {
|
||||||
|
let mut table = Builder::custom(data).build();
|
||||||
|
load_theme(&mut table, theme, with_footer, with_header, split_color);
|
||||||
align_table(&mut table, alignments, with_index, with_header, with_footer);
|
align_table(&mut table, alignments, with_index, with_header, with_footer);
|
||||||
|
|
||||||
if expand {
|
if expand {
|
||||||
table.with(Width::increase(termwidth));
|
table.with(Width::increase(termwidth));
|
||||||
}
|
}
|
||||||
|
|
||||||
table_trim_columns(&mut table, termwidth, &config.trim_strategy);
|
table_trim_columns(&mut table, termwidth, trim_strategy);
|
||||||
|
|
||||||
let table = print_table(table, config);
|
let text = table.to_string();
|
||||||
if table_width(&table) > termwidth {
|
if string_width_multiline(&text) > termwidth {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(table)
|
Some(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_table(table: tabled::Table<Data>, config: &Config) -> String {
|
|
||||||
let output = table.to_string();
|
|
||||||
|
|
||||||
// the atty is for when people do ls from vim, there should be no coloring there
|
|
||||||
if !config.use_ansi_coloring || !atty::is(atty::Stream::Stdout) {
|
|
||||||
// Draw the table without ansi colors
|
|
||||||
nu_utils::strip_ansi_string_likely(output)
|
|
||||||
} else {
|
|
||||||
// Draw the table with ansi colors
|
|
||||||
output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn table_width(table: &str) -> usize {
|
|
||||||
table
|
|
||||||
.lines()
|
|
||||||
.next()
|
|
||||||
.map_or(0, papergrid::util::string_width)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn align_table(
|
fn align_table(
|
||||||
table: &mut tabled::Table<Data>,
|
table: &mut tabled::Table<Data>,
|
||||||
alignments: Alignments,
|
alignments: Alignments,
|
||||||
|
@ -268,10 +292,10 @@ fn override_alignments(
|
||||||
|
|
||||||
fn load_theme<R>(
|
fn load_theme<R>(
|
||||||
table: &mut tabled::Table<R>,
|
table: &mut tabled::Table<R>,
|
||||||
color_hm: &HashMap<String, nu_ansi_term::Style>,
|
|
||||||
theme: &TableTheme,
|
theme: &TableTheme,
|
||||||
with_footer: bool,
|
with_footer: bool,
|
||||||
with_header: bool,
|
with_header: bool,
|
||||||
|
separator_color: Option<Style>,
|
||||||
) where
|
) where
|
||||||
R: Records,
|
R: Records,
|
||||||
{
|
{
|
||||||
|
@ -282,7 +306,7 @@ fn load_theme<R>(
|
||||||
|
|
||||||
table.with(theme);
|
table.with(theme);
|
||||||
|
|
||||||
if let Some(color) = color_hm.get("separator") {
|
if let Some(color) = separator_color {
|
||||||
let color = color.paint(" ").to_string();
|
let color = color.paint(" ").to_string();
|
||||||
if let Ok(color) = Color::try_from(color) {
|
if let Ok(color) = Color::try_from(color) {
|
||||||
table.with(color);
|
table.with(color);
|
||||||
|
@ -298,11 +322,6 @@ fn load_theme<R>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn need_footer(config: &Config, count_records: u64) -> bool {
|
|
||||||
matches!(config.footer_mode, FooterMode::RowCount(limit) if count_records > limit)
|
|
||||||
|| matches!(config.footer_mode, FooterMode::Always)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FooterStyle;
|
struct FooterStyle;
|
||||||
|
|
||||||
impl<R> TableOption<R> for FooterStyle
|
impl<R> TableOption<R> for FooterStyle
|
||||||
|
@ -352,7 +371,7 @@ where
|
||||||
fn change(&mut self, table: &mut tabled::Table<R>) {
|
fn change(&mut self, table: &mut tabled::Table<R>) {
|
||||||
match self.trim_strategy {
|
match self.trim_strategy {
|
||||||
TrimStrategy::Wrap { try_to_keep_words } => {
|
TrimStrategy::Wrap { try_to_keep_words } => {
|
||||||
let mut w = Width::wrap(self.termwidth).priority::<tabled::peaker::PriorityMax>();
|
let mut w = Width::wrap(self.termwidth).priority::<PriorityMax>();
|
||||||
if *try_to_keep_words {
|
if *try_to_keep_words {
|
||||||
w = w.keep_words();
|
w = w.keep_words();
|
||||||
}
|
}
|
||||||
|
@ -360,8 +379,7 @@ where
|
||||||
w.change(table)
|
w.change(table)
|
||||||
}
|
}
|
||||||
TrimStrategy::Truncate { suffix } => {
|
TrimStrategy::Truncate { suffix } => {
|
||||||
let mut w =
|
let mut w = Width::truncate(self.termwidth).priority::<PriorityMax>();
|
||||||
Width::truncate(self.termwidth).priority::<tabled::peaker::PriorityMax>();
|
|
||||||
if let Some(suffix) = suffix {
|
if let Some(suffix) = suffix {
|
||||||
w = w.suffix(suffix).suffix_try_color(true);
|
w = w.suffix(suffix).suffix_try_color(true);
|
||||||
}
|
}
|
||||||
|
@ -372,20 +390,188 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_truncate_columns(data: &mut Data, length: usize, termwidth: usize) -> bool {
|
enum TruncationPriority {
|
||||||
// Make sure we have enough space for the columns we have
|
// VERSION where we are showing AS LITTLE COLUMNS AS POSSIBLE but WITH AS MUCH CONTENT AS POSSIBLE.
|
||||||
let max_num_of_columns = termwidth / 10;
|
Content,
|
||||||
if max_num_of_columns == 0 {
|
// VERSION where we are showing AS MANY COLUMNS AS POSSIBLE but as a side affect they MIGHT CONTAIN AS LITTLE CONTENT AS POSSIBLE
|
||||||
|
//
|
||||||
|
// not used so far.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
Columns,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn maybe_truncate_columns(
|
||||||
|
data: &mut Data,
|
||||||
|
theme: &TableTheme,
|
||||||
|
termwidth: usize,
|
||||||
|
priority: TruncationPriority,
|
||||||
|
) -> bool {
|
||||||
|
if data.count_columns() == 0 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have too many columns, truncate the table
|
match priority {
|
||||||
if max_num_of_columns < length {
|
TruncationPriority::Content => truncate_columns_by_content(data, theme, termwidth),
|
||||||
data.truncate(max_num_of_columns);
|
TruncationPriority::Columns => truncate_columns_by_columns(data, theme, termwidth),
|
||||||
data.push(Table::create_cell(
|
}
|
||||||
String::from("..."),
|
}
|
||||||
TextStyle::default(),
|
|
||||||
));
|
// VERSION where we are showing AS LITTLE COLUMNS AS POSSIBLE but WITH AS MUCH CONTENT AS POSSIBLE.
|
||||||
|
fn truncate_columns_by_content(data: &mut Data, theme: &TableTheme, termwidth: usize) -> bool {
|
||||||
|
const MIN_ACCEPTABLE_WIDTH: usize = 3;
|
||||||
|
const TRAILING_COLUMN_WIDTH: usize = 5;
|
||||||
|
const TRAILING_COLUMN_STR: &str = "...";
|
||||||
|
|
||||||
|
let config;
|
||||||
|
let total;
|
||||||
|
{
|
||||||
|
let mut table = Builder::custom(&*data).build();
|
||||||
|
load_theme(&mut table, theme, false, false, None);
|
||||||
|
total = table.total_width();
|
||||||
|
config = table.get_config().clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
if total <= termwidth {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut width_ctrl = tabled::papergrid::width::WidthEstimator::default();
|
||||||
|
width_ctrl.estimate(&*data, &config);
|
||||||
|
let widths = Vec::from(width_ctrl);
|
||||||
|
|
||||||
|
let borders = config.get_borders();
|
||||||
|
let vertical_border_i = borders.has_vertical() as usize;
|
||||||
|
|
||||||
|
let mut width = borders.has_left() as usize + borders.has_right() as usize;
|
||||||
|
let mut truncate_pos = 0;
|
||||||
|
for column_width in widths {
|
||||||
|
width += column_width;
|
||||||
|
width += vertical_border_i;
|
||||||
|
|
||||||
|
if width >= termwidth {
|
||||||
|
// check whether we CAN limit the column width
|
||||||
|
width -= column_width;
|
||||||
|
width += MIN_ACCEPTABLE_WIDTH;
|
||||||
|
|
||||||
|
if width <= termwidth {
|
||||||
|
truncate_pos += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
truncate_pos += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we don't need any truncation then (is it possible?)
|
||||||
|
if truncate_pos + 1 == data.count_columns() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if truncate_pos == 0 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.truncate(truncate_pos);
|
||||||
|
|
||||||
|
// Append columns with a trailing column
|
||||||
|
|
||||||
|
let min_width = borders.has_left() as usize
|
||||||
|
+ borders.has_right() as usize
|
||||||
|
+ data.count_columns() * MIN_ACCEPTABLE_WIDTH
|
||||||
|
+ (data.count_columns() - 1) * vertical_border_i;
|
||||||
|
|
||||||
|
let diff = termwidth - min_width;
|
||||||
|
let can_be_squeezed = diff > TRAILING_COLUMN_WIDTH + vertical_border_i;
|
||||||
|
|
||||||
|
if can_be_squeezed {
|
||||||
|
let cell = Table::create_cell(String::from(TRAILING_COLUMN_STR), TextStyle::default());
|
||||||
|
data.push(cell);
|
||||||
|
} else {
|
||||||
|
if data.count_columns() == 1 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.truncate(data.count_columns() - 1);
|
||||||
|
|
||||||
|
let cell = Table::create_cell(String::from(TRAILING_COLUMN_STR), TextStyle::default());
|
||||||
|
data.push(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn truncate_columns_by_columns(data: &mut Data, theme: &TableTheme, termwidth: usize) -> bool {
|
||||||
|
const MIN_ACCEPTABLE_WIDTH: usize = 3;
|
||||||
|
const TRAILING_COLUMN_WIDTH: usize = 3;
|
||||||
|
const TRAILING_COLUMN_PADDING: usize = 2;
|
||||||
|
const TRAILING_COLUMN_STR: &str = "...";
|
||||||
|
|
||||||
|
let config;
|
||||||
|
let total;
|
||||||
|
{
|
||||||
|
let mut table = Builder::custom(&*data).build();
|
||||||
|
load_theme(&mut table, theme, false, false, None);
|
||||||
|
total = table.total_width();
|
||||||
|
config = table.get_config().clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
if total <= termwidth {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut width_ctrl = tabled::papergrid::width::WidthEstimator::default();
|
||||||
|
width_ctrl.estimate(&*data, &config);
|
||||||
|
let widths = Vec::from(width_ctrl);
|
||||||
|
let widths_total = widths.iter().sum::<usize>();
|
||||||
|
|
||||||
|
let min_widths = widths
|
||||||
|
.iter()
|
||||||
|
.map(|w| min(*w, MIN_ACCEPTABLE_WIDTH))
|
||||||
|
.sum::<usize>();
|
||||||
|
let mut min_total = total - widths_total + min_widths;
|
||||||
|
|
||||||
|
if min_total <= termwidth {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while data.count_columns() > 0 {
|
||||||
|
let column = data.count_columns() - 1;
|
||||||
|
|
||||||
|
data.truncate(column);
|
||||||
|
|
||||||
|
let width = widths[column];
|
||||||
|
let min_width = min(width, MIN_ACCEPTABLE_WIDTH);
|
||||||
|
|
||||||
|
min_total -= min_width;
|
||||||
|
if config.get_borders().has_vertical() {
|
||||||
|
min_total -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if min_total <= termwidth {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.count_columns() == 0 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append columns with a trailing column
|
||||||
|
|
||||||
|
let diff = termwidth - min_total;
|
||||||
|
if diff > TRAILING_COLUMN_WIDTH + TRAILING_COLUMN_PADDING {
|
||||||
|
let cell = Table::create_cell(String::from(TRAILING_COLUMN_STR), TextStyle::default());
|
||||||
|
data.push(cell);
|
||||||
|
} else {
|
||||||
|
if data.count_columns() == 1 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.truncate(data.count_columns() - 1);
|
||||||
|
|
||||||
|
let cell = Table::create_cell(String::from(TRAILING_COLUMN_STR), TextStyle::default());
|
||||||
|
data.push(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
|
@ -410,3 +596,27 @@ impl papergrid::Color for TextStyle {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The same as [`tabled::peaker::PriorityMax`] but prioritizes left columns first in case of equal width.
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct PriorityMax;
|
||||||
|
|
||||||
|
impl Peaker for PriorityMax {
|
||||||
|
fn create() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peak(&mut self, _: &[usize], widths: &[usize]) -> Option<usize> {
|
||||||
|
let col = (0..widths.len()).rev().max_by_key(|&i| widths[i]);
|
||||||
|
match col {
|
||||||
|
Some(col) => {
|
||||||
|
if widths[col] == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
54
crates/nu-table/src/util.rs
Normal file
54
crates/nu-table/src/util.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
use tabled::{builder::Builder, Padding, Style, Width};
|
||||||
|
|
||||||
|
pub fn string_width(text: &str) -> usize {
|
||||||
|
tabled::papergrid::util::string_width_multiline_tab(text, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wrap_string(text: &str, width: usize) -> String {
|
||||||
|
// todo: change me...
|
||||||
|
//
|
||||||
|
// well... it's not effitient to build a table to wrap a string,
|
||||||
|
// but ... it's better than a copy paste (is it?)
|
||||||
|
|
||||||
|
if text.is_empty() {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder::from_iter([[text]])
|
||||||
|
.build()
|
||||||
|
.with(Padding::zero())
|
||||||
|
.with(Style::empty())
|
||||||
|
.with(Width::wrap(width))
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn string_truncate(text: &str, width: usize) -> String {
|
||||||
|
// todo: change me...
|
||||||
|
|
||||||
|
let line = match text.lines().next() {
|
||||||
|
Some(first_line) => first_line,
|
||||||
|
None => return String::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Builder::from_iter([[line]])
|
||||||
|
.build()
|
||||||
|
.with(Style::empty())
|
||||||
|
.with(Padding::zero())
|
||||||
|
.with(Width::truncate(width))
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn string_wrap(text: &str, width: usize) -> String {
|
||||||
|
// todo: change me...
|
||||||
|
|
||||||
|
if text.is_empty() {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder::from_iter([[text]])
|
||||||
|
.build()
|
||||||
|
.with(Style::empty())
|
||||||
|
.with(Padding::zero())
|
||||||
|
.with(Width::wrap(width))
|
||||||
|
.to_string()
|
||||||
|
}
|
68
crates/nu-table/tests/common.rs
Normal file
68
crates/nu-table/tests/common.rs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
use nu_table::{string_width, Table, TableConfig, TextStyle};
|
||||||
|
use tabled::papergrid::records::{cell_info::CellInfo, tcell::TCell};
|
||||||
|
|
||||||
|
pub type VecCells = Vec<Vec<TCell<CellInfo<'static>, TextStyle>>>;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct TestCase {
|
||||||
|
cfg: TableConfig,
|
||||||
|
termwidth: usize,
|
||||||
|
expected: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestCase {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new(cfg: TableConfig, termwidth: usize, expected: Option<String>) -> Self {
|
||||||
|
Self {
|
||||||
|
cfg,
|
||||||
|
termwidth,
|
||||||
|
expected,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn test_table<I>(data: VecCells, tests: I)
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = TestCase>,
|
||||||
|
{
|
||||||
|
for (i, test) in tests.into_iter().enumerate() {
|
||||||
|
let actual = create_table(data.clone(), test.cfg.clone(), test.termwidth);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
actual, test.expected,
|
||||||
|
"\nfail i={:?} termwidth={}",
|
||||||
|
i, test.termwidth
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(table) = actual {
|
||||||
|
assert!(string_width(&table) <= test.termwidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_table(data: VecCells, config: TableConfig, termwidth: usize) -> Option<String> {
|
||||||
|
let mut size = (0, 0);
|
||||||
|
for row in &data {
|
||||||
|
size.0 += 1;
|
||||||
|
size.1 = std::cmp::max(size.1, row.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
let table = Table::new(data, size);
|
||||||
|
table.draw(config, termwidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_row(count_columns: usize) -> Vec<TCell<CellInfo<'static>, TextStyle>> {
|
||||||
|
let mut row = Vec::with_capacity(count_columns);
|
||||||
|
|
||||||
|
for i in 0..count_columns {
|
||||||
|
row.push(Table::create_cell(i.to_string(), TextStyle::default()));
|
||||||
|
}
|
||||||
|
|
||||||
|
row
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn styled_str(s: &str) -> TCell<CellInfo<'static>, TextStyle> {
|
||||||
|
Table::create_cell(s.to_string(), TextStyle::default())
|
||||||
|
}
|
|
@ -1,211 +1,199 @@
|
||||||
use std::{collections::HashMap, usize};
|
mod common;
|
||||||
|
|
||||||
use nu_protocol::{Config, TrimStrategy};
|
use nu_protocol::TrimStrategy;
|
||||||
use nu_table::{Alignments, Table, TableTheme as theme, TextStyle};
|
use nu_table::{Table, TableConfig, TableTheme as theme};
|
||||||
use tabled::papergrid::records::{cell_info::CellInfo, tcell::TCell};
|
|
||||||
|
use common::{create_row, styled_str, test_table, TestCase, VecCells};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn data_and_header_has_different_size() {
|
fn data_and_header_has_different_size() {
|
||||||
let table = Table::new(
|
let table = Table::new(vec![create_row(3), create_row(5), create_row(5)], (3, 5));
|
||||||
vec![row(3), row(5), row(5)],
|
|
||||||
(3, 5),
|
let table = table.draw(
|
||||||
|
TableConfig::new(theme::heavy(), true, false, false),
|
||||||
usize::MAX,
|
usize::MAX,
|
||||||
true,
|
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let table = draw_table(table, usize::MAX, &Config::default());
|
assert_eq!(
|
||||||
|
table.as_deref(),
|
||||||
let expected = "┏━━━┳━━━┳━━━┳━━━┳━━━┓\n\
|
Some(
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ ┃ ┃\n\
|
"┏━━━┳━━━┳━━━┳━━━┳━━━┓\n\
|
||||||
┣━━━╋━━━╋━━━╋━━━╋━━━┫\n\
|
┃ 0 ┃ 1 ┃ 2 ┃ ┃ ┃\n\
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃\n\
|
┣━━━╋━━━╋━━━╋━━━╋━━━┫\n\
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃\n\
|
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃\n\
|
||||||
┗━━━┻━━━┻━━━┻━━━┻━━━┛";
|
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃\n\
|
||||||
|
┗━━━┻━━━┻━━━┻━━━┻━━━┛"
|
||||||
assert_eq!(table.as_deref(), Some(expected));
|
)
|
||||||
|
|
||||||
let table = Table::new(
|
|
||||||
vec![row(5), row(3), row(3)],
|
|
||||||
(3, 5),
|
|
||||||
usize::MAX,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
let table = draw_table(table, usize::MAX, &Config::default());
|
|
||||||
|
|
||||||
let expected = "┏━━━┳━━━┳━━━┳━━━┳━━━┓\n\
|
let table = Table::new(vec![create_row(5), create_row(3), create_row(3)], (3, 5));
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃\n\
|
|
||||||
┣━━━╋━━━╋━━━╋━━━╋━━━┫\n\
|
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ ┃ ┃\n\
|
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ ┃ ┃\n\
|
|
||||||
┗━━━┻━━━┻━━━┻━━━┻━━━┛";
|
|
||||||
|
|
||||||
assert_eq!(table.as_deref(), Some(expected));
|
let table = table.draw(
|
||||||
|
TableConfig::new(theme::heavy(), true, false, false),
|
||||||
|
usize::MAX,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
table.as_deref(),
|
||||||
|
Some(
|
||||||
|
"┏━━━┳━━━┳━━━┳━━━┳━━━┓\n\
|
||||||
|
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃\n\
|
||||||
|
┣━━━╋━━━╋━━━╋━━━╋━━━┫\n\
|
||||||
|
┃ 0 ┃ 1 ┃ 2 ┃ ┃ ┃\n\
|
||||||
|
┃ 0 ┃ 1 ┃ 2 ┃ ┃ ┃\n\
|
||||||
|
┗━━━┻━━━┻━━━┻━━━┻━━━┛"
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn termwidth_too_small() {
|
fn termwidth_too_small() {
|
||||||
let cfg = Config::default();
|
let test_loop = |config: TableConfig| {
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
let table = Table::new(vec![row(3), row(3), row(5)], (3, 5), i, true, false);
|
let table = Table::new(vec![create_row(3), create_row(3), create_row(5)], (3, 5));
|
||||||
assert!(draw_table(table, i, &cfg).is_none());
|
let table = table.draw(config.clone(), i);
|
||||||
}
|
|
||||||
|
|
||||||
let table = Table::new(vec![row(3), row(3), row(5)], (3, 5), 11, true, false);
|
assert!(table.is_none());
|
||||||
assert!(draw_table(table, 11, &cfg).is_some());
|
}
|
||||||
|
|
||||||
let cfg = Config {
|
|
||||||
trim_strategy: TrimStrategy::Truncate { suffix: None },
|
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for i in 0..10 {
|
let base_config = TableConfig::new(theme::heavy(), true, false, false);
|
||||||
let table = Table::new(vec![row(3), row(3), row(5)], (3, 5), i, true, false);
|
|
||||||
assert!(draw_table(table, i, &cfg).is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
let table = Table::new(vec![row(3), row(3), row(5)], (3, 5), 11, true, false);
|
let config = base_config.clone();
|
||||||
assert!(draw_table(table, 11, &cfg).is_some());
|
test_loop(config);
|
||||||
|
|
||||||
|
let config = base_config.clone().trim(TrimStrategy::truncate(None));
|
||||||
|
test_loop(config);
|
||||||
|
|
||||||
|
let config = base_config
|
||||||
|
.clone()
|
||||||
|
.trim(TrimStrategy::truncate(Some(String::from("**"))));
|
||||||
|
test_loop(config);
|
||||||
|
|
||||||
|
let config = base_config
|
||||||
|
.clone()
|
||||||
|
.trim(TrimStrategy::truncate(Some(String::from(""))));
|
||||||
|
test_loop(config);
|
||||||
|
|
||||||
|
let config = base_config.clone().trim(TrimStrategy::wrap(false));
|
||||||
|
test_loop(config);
|
||||||
|
|
||||||
|
let config = base_config.trim(TrimStrategy::wrap(true));
|
||||||
|
test_loop(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wrap_test() {
|
fn wrap_test() {
|
||||||
let cfg = Config {
|
let tests = [
|
||||||
trim_strategy: TrimStrategy::Wrap {
|
(0, None),
|
||||||
try_to_keep_words: false,
|
(1, None),
|
||||||
},
|
(2, None),
|
||||||
..Default::default()
|
(3, None),
|
||||||
};
|
(4, None),
|
||||||
|
(5, None),
|
||||||
|
(6, None),
|
||||||
|
(7, None),
|
||||||
|
(8, None),
|
||||||
|
(9, None),
|
||||||
|
(10, None),
|
||||||
|
(11, None),
|
||||||
|
(12, Some("┏━━━━┳━━━━━┓\n┃ 12 ┃ ... ┃\n┃ 3 ┃ ┃\n┃ 45 ┃ ┃\n┃ 67 ┃ ┃\n┃ 8 ┃ ┃\n┣━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━┻━━━━━┛")),
|
||||||
|
(13, Some("┏━━━━━┳━━━━━┓\n┃ 123 ┃ ... ┃\n┃ 45 ┃ ┃\n┃ 678 ┃ ┃\n┣━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━┻━━━━━┛")),
|
||||||
|
(21, Some("┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┃ 4567 ┃ w eq ┃ ┃\n┃ 8 ┃ we ┃ ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛")),
|
||||||
|
(29, Some("┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ ... ┃\n┃ 8 ┃ we ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛")),
|
||||||
|
(49, Some("┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw eqwe ┃ xxx xx xx x xx ┃ ... ┃\n┃ ┃ ┃ x xx xx ┃ ┃\n┣━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┻━━━━━┛")),
|
||||||
|
];
|
||||||
|
|
||||||
for i in 0..10 {
|
test_trim(&tests, TrimStrategy::wrap(false));
|
||||||
assert!(draw_table(table_with_data(i), i, &cfg).is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(draw_table(table_with_data(10), 10, &cfg).unwrap(), "┏━━━━┳━━━┓\n┃ 12 ┃ . ┃\n┃ 3 ┃ . ┃\n┃ 45 ┃ . ┃\n┃ 67 ┃ ┃\n┃ 8 ┃ ┃\n┣━━━━╋━━━┫\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┗━━━━┻━━━┛");
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(21), 21, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┃ 4567 ┃ w eq ┃ ┃\n┃ 8 ┃ we ┃ ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(29), 29, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ ... ┃\n┃ 8 ┃ we ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(49), 49, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ xxx xx ┃ qqq qqq ┃ ... ┃\n┃ 8 ┃ we ┃ xx x xx ┃ qqqq q ┃ ┃\n┃ ┃ ┃ x xx x ┃ qq qq ┃ ┃\n┃ ┃ ┃ x ┃ ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wrap_keep_words_test() {
|
fn wrap_keep_words_test() {
|
||||||
let cfg = Config {
|
let tests = [
|
||||||
trim_strategy: TrimStrategy::Wrap {
|
(0, None),
|
||||||
try_to_keep_words: true,
|
(1, None),
|
||||||
},
|
(2, None),
|
||||||
..Default::default()
|
(3, None),
|
||||||
};
|
(4, None),
|
||||||
|
(5, None),
|
||||||
|
(6, None),
|
||||||
|
(7, None),
|
||||||
|
(8, None),
|
||||||
|
(9, None),
|
||||||
|
(10, None),
|
||||||
|
(11, None),
|
||||||
|
(12, Some("┏━━━━┳━━━━━┓\n┃ 12 ┃ ... ┃\n┃ 3 ┃ ┃\n┃ 45 ┃ ┃\n┃ 67 ┃ ┃\n┃ 8 ┃ ┃\n┣━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━┻━━━━━┛")),
|
||||||
|
(13, Some("┏━━━━━┳━━━━━┓\n┃ 123 ┃ ... ┃\n┃ ┃ ┃\n┃ 456 ┃ ┃\n┃ 78 ┃ ┃\n┣━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━┻━━━━━┛")),
|
||||||
|
(21, Some("┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┃ 4567 ┃ w ┃ ┃\n┃ 8 ┃ eqwe ┃ ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛")),
|
||||||
|
(29, Some("┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 ┃ qweqw ┃ ... ┃\n┃ 45678 ┃ eqwe ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛")),
|
||||||
|
(49, Some("┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw eqwe ┃ xxx xx xx x xx ┃ ... ┃\n┃ ┃ ┃ x xx xx ┃ ┃\n┣━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┻━━━━━┛")),
|
||||||
|
];
|
||||||
|
|
||||||
for i in 0..10 {
|
test_trim(&tests, TrimStrategy::wrap(true));
|
||||||
assert!(draw_table(table_with_data(i), i, &cfg).is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(draw_table(table_with_data(10), 10, &cfg).unwrap(), "┏━━━━┳━━━┓\n┃ 12 ┃ . ┃\n┃ 3 ┃ . ┃\n┃ 45 ┃ . ┃\n┃ 67 ┃ ┃\n┃ 8 ┃ ┃\n┣━━━━╋━━━┫\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┗━━━━┻━━━┛");
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(21), 21, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┃ 4567 ┃ w ┃ ┃\n┃ 8 ┃ eqwe ┃ ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(29), 29, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 ┃ qweqw ┃ ... ┃\n┃ 45678 ┃ eqwe ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(49), 49, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 ┃ qweqw ┃ xxx xx ┃ qqq qqq ┃ ... ┃\n┃ 45678 ┃ eqwe ┃ xx x xx ┃ qqqq ┃ ┃\n┃ ┃ ┃ x xx ┃ qqq qq ┃ ┃\n┃ ┃ ┃ xx ┃ ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn truncate_test() {
|
fn truncate_test() {
|
||||||
let cfg = Config {
|
let tests = [
|
||||||
trim_strategy: TrimStrategy::Truncate { suffix: None },
|
(0, None),
|
||||||
..Default::default()
|
(1, None),
|
||||||
};
|
(2, None),
|
||||||
|
(3, None),
|
||||||
|
(4, None),
|
||||||
|
(5, None),
|
||||||
|
(6, None),
|
||||||
|
(7, None),
|
||||||
|
(8, None),
|
||||||
|
(9, None),
|
||||||
|
(10, None),
|
||||||
|
(11, None),
|
||||||
|
(12, Some("┏━━━━┳━━━━━┓\n┃ 12 ┃ ... ┃\n┣━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━┻━━━━━┛")),
|
||||||
|
(13, Some("┏━━━━━┳━━━━━┓\n┃ 123 ┃ ... ┃\n┣━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━┻━━━━━┛")),
|
||||||
|
(21, Some("┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛")),
|
||||||
|
(29, Some("┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ ... ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛")),
|
||||||
|
(49, Some("┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw eqwe ┃ xxx xx xx x xx ┃ ... ┃\n┣━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┻━━━━━┛")),
|
||||||
|
];
|
||||||
|
|
||||||
for i in 0..10 {
|
test_trim(&tests, TrimStrategy::truncate(None));
|
||||||
assert!(draw_table(table_with_data(i), i, &cfg).is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(10), 10, &cfg).unwrap(),
|
|
||||||
"┏━━━━┳━━━┓\n┃ 12 ┃ . ┃\n┣━━━━╋━━━┫\n┃ 0 ┃ . ┃\n┃ 0 ┃ . ┃\n┗━━━━┻━━━┛"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(21), 21, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(29), 29, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ ... ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(49), 49, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ xxx xx ┃ qqq qqq ┃ ... ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn truncate_with_suffix_test() {
|
fn truncate_with_suffix_test() {
|
||||||
let cfg = Config {
|
let tests = [
|
||||||
trim_strategy: TrimStrategy::Truncate {
|
(0, None),
|
||||||
suffix: Some(String::from("...")),
|
(1, None),
|
||||||
},
|
(2, None),
|
||||||
..Default::default()
|
(3, None),
|
||||||
};
|
(4, None),
|
||||||
|
(5, None),
|
||||||
|
(6, None),
|
||||||
|
(7, None),
|
||||||
|
(8, None),
|
||||||
|
(9, None),
|
||||||
|
(10, None),
|
||||||
|
(11, None),
|
||||||
|
(12, Some("┏━━━━┳━━━━━┓\n┃ .. ┃ ... ┃\n┣━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━┻━━━━━┛")),
|
||||||
|
(13, Some("┏━━━━━┳━━━━━┓\n┃ ... ┃ ... ┃\n┣━━━━━╋━━━━━┫\n┃ 0 ┃ ... ┃\n┃ 0 ┃ ... ┃\n┗━━━━━┻━━━━━┛")),
|
||||||
|
(21, Some("┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 1... ┃ q... ┃ ... ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛")),
|
||||||
|
(29, Some("┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 4... ┃ qweqw... ┃ ... ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛")),
|
||||||
|
(49, Some("┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━┓\n┃ 123 45678 ┃ qweqw eqwe ┃ xxx xx xx x... ┃ ... ┃\n┣━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ ... ┃\n┗━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┻━━━━━┛")),
|
||||||
|
];
|
||||||
|
|
||||||
for i in 0..10 {
|
test_trim(&tests, TrimStrategy::truncate(Some(String::from("..."))));
|
||||||
assert!(draw_table(table_with_data(i), i, &cfg).is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(10), 10, &cfg).unwrap(),
|
|
||||||
"┏━━━━┳━━━┓\n┃ .. ┃ . ┃\n┣━━━━╋━━━┫\n┃ 0 ┃ . ┃\n┃ 0 ┃ . ┃\n┗━━━━┻━━━┛"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(21), 21, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 1... ┃ q... ┃ ... ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(29), 29, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 4... ┃ qweqw... ┃ ... ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
draw_table(table_with_data(49), 49, &cfg).unwrap(),
|
|
||||||
"┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 4... ┃ qweqw... ┃ xxx ... ┃ qqq ... ┃ ... ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┻━━━━━┛"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_table(table: Table, limit: usize, cfg: &Config) -> Option<String> {
|
fn test_trim(tests: &[(usize, Option<&str>)], trim: TrimStrategy) {
|
||||||
let styles = HashMap::default();
|
let config = TableConfig::new(nu_table::TableTheme::heavy(), true, false, false).trim(trim);
|
||||||
let alignments = Alignments::default();
|
let tests = tests.iter().map(|&(termwidth, expected)| {
|
||||||
table.draw_table(cfg, &styles, alignments, &theme::heavy(), limit, false)
|
TestCase::new(config.clone(), termwidth, expected.map(|s| s.to_string()))
|
||||||
|
});
|
||||||
|
|
||||||
|
let data = create_test_table0();
|
||||||
|
|
||||||
|
test_table(data, tests);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn row(count_columns: usize) -> Vec<TCell<CellInfo<'static>, TextStyle>> {
|
fn create_test_table0() -> VecCells {
|
||||||
let mut row = Vec::with_capacity(count_columns);
|
|
||||||
|
|
||||||
for i in 0..count_columns {
|
|
||||||
row.push(Table::create_cell(i.to_string(), TextStyle::default()));
|
|
||||||
}
|
|
||||||
|
|
||||||
row
|
|
||||||
}
|
|
||||||
|
|
||||||
fn styled_str(s: &str) -> TCell<CellInfo<'static>, TextStyle> {
|
|
||||||
Table::create_cell(s.to_string(), TextStyle::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn table_with_data(termwidth: usize) -> Table {
|
|
||||||
let header = vec![
|
let header = vec![
|
||||||
styled_str("123 45678"),
|
styled_str("123 45678"),
|
||||||
styled_str("qweqw eqwe"),
|
styled_str("qweqw eqwe"),
|
||||||
|
@ -213,7 +201,6 @@ fn table_with_data(termwidth: usize) -> Table {
|
||||||
styled_str("qqq qqq qqqq qqq qq"),
|
styled_str("qqq qqq qqqq qqq qq"),
|
||||||
styled_str("qw"),
|
styled_str("qw"),
|
||||||
];
|
];
|
||||||
let data = vec![header, row(5), row(5)];
|
|
||||||
|
|
||||||
Table::new(data, (3, 5), termwidth, true, false)
|
vec![header, create_row(5), create_row(5)]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
use std::collections::HashMap;
|
mod common;
|
||||||
|
|
||||||
use nu_protocol::Config;
|
use common::{create_row, create_table};
|
||||||
use nu_table::{Alignments, Table, TableTheme as theme, TextStyle};
|
use nu_table::{TableConfig, TableTheme as theme};
|
||||||
use tabled::papergrid::records::{cell_info::CellInfo, tcell::TCell};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_expand() {
|
fn test_expand() {
|
||||||
|
let table = create_table(
|
||||||
|
vec![create_row(4); 3],
|
||||||
|
TableConfig::new(theme::rounded(), true, false, false).expand(),
|
||||||
|
50,
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::rounded(), 50),
|
table.unwrap(),
|
||||||
"╭────────────┬───────────┬───────────┬───────────╮\n\
|
"╭────────────┬───────────┬───────────┬───────────╮\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
├────────────┼───────────┼───────────┼───────────┤\n\
|
├────────────┼───────────┼───────────┼───────────┤\n\
|
||||||
|
@ -16,31 +21,3 @@ fn test_expand() {
|
||||||
╰────────────┴───────────┴───────────┴───────────╯"
|
╰────────────┴───────────┴───────────┴───────────╯"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_table(
|
|
||||||
data: Vec<Vec<TCell<CellInfo<'static>, TextStyle>>>,
|
|
||||||
count_columns: usize,
|
|
||||||
with_header: bool,
|
|
||||||
theme: theme,
|
|
||||||
width: usize,
|
|
||||||
) -> String {
|
|
||||||
let size = (data.len(), count_columns);
|
|
||||||
let table = Table::new(data, size, width, with_header, false);
|
|
||||||
|
|
||||||
let cfg = Config::default();
|
|
||||||
let styles = HashMap::default();
|
|
||||||
let alignments = Alignments::default();
|
|
||||||
table
|
|
||||||
.draw_table(&cfg, &styles, alignments, &theme, width, true)
|
|
||||||
.expect("Unexpectdly got no table")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn row(count_columns: usize) -> Vec<TCell<CellInfo<'static>, TextStyle>> {
|
|
||||||
let mut row = Vec::with_capacity(count_columns);
|
|
||||||
|
|
||||||
for i in 0..count_columns {
|
|
||||||
row.push(Table::create_cell(i.to_string(), TextStyle::default()));
|
|
||||||
}
|
|
||||||
|
|
||||||
row
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use std::collections::HashMap;
|
mod common;
|
||||||
|
|
||||||
use nu_protocol::Config;
|
use nu_table::{TableConfig, TableTheme as theme};
|
||||||
use nu_table::{Alignments, Table, TableTheme as theme, TextStyle};
|
|
||||||
use tabled::papergrid::records::{cell_info::CellInfo, tcell::TCell};
|
use common::{create_row as row, VecCells};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rounded() {
|
fn test_rounded() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::rounded()),
|
create_table(vec![row(4); 3], true, theme::rounded()),
|
||||||
"╭───┬───┬───┬───╮\n\
|
"╭───┬───┬───┬───╮\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
├───┼───┼───┼───┤\n\
|
├───┼───┼───┼───┤\n\
|
||||||
|
@ -17,7 +17,7 @@ fn test_rounded() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::rounded()),
|
create_table(vec![row(4); 2], true, theme::rounded()),
|
||||||
"╭───┬───┬───┬───╮\n\
|
"╭───┬───┬───┬───╮\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
├───┼───┼───┼───┤\n\
|
├───┼───┼───┼───┤\n\
|
||||||
|
@ -26,34 +26,37 @@ fn test_rounded() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, true, theme::rounded()),
|
create_table(vec![row(4); 1], true, theme::rounded()),
|
||||||
"╭───┬───┬───┬───╮\n\
|
"╭───┬───┬───┬───╮\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
╰───┴───┴───┴───╯"
|
╰───┴───┴───┴───╯"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, false, theme::rounded()),
|
create_table(vec![row(4); 1], false, theme::rounded()),
|
||||||
"╭───┬───┬───┬───╮\n\
|
"╭───┬───┬───┬───╮\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
╰───┴───┴───┴───╯"
|
╰───┴───┴───┴───╯"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, false, theme::rounded()),
|
create_table(vec![row(4); 2], false, theme::rounded()),
|
||||||
"╭───┬───┬───┬───╮\n\
|
"╭───┬───┬───┬───╮\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
╰───┴───┴───┴───╯"
|
╰───┴───┴───┴───╯"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(draw_table(vec![row(4); 0], 4, false, theme::rounded()), "");
|
assert_eq!(
|
||||||
|
create_table_with_size(vec![row(4); 0], (0, 4), true, theme::rounded()),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::basic()),
|
create_table(vec![row(4); 3], true, theme::basic()),
|
||||||
"+---+---+---+---+\n\
|
"+---+---+---+---+\n\
|
||||||
| 0 | 1 | 2 | 3 |\n\
|
| 0 | 1 | 2 | 3 |\n\
|
||||||
+---+---+---+---+\n\
|
+---+---+---+---+\n\
|
||||||
|
@ -64,7 +67,7 @@ fn test_basic() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::basic()),
|
create_table(vec![row(4); 2], true, theme::basic()),
|
||||||
"+---+---+---+---+\n\
|
"+---+---+---+---+\n\
|
||||||
| 0 | 1 | 2 | 3 |\n\
|
| 0 | 1 | 2 | 3 |\n\
|
||||||
+---+---+---+---+\n\
|
+---+---+---+---+\n\
|
||||||
|
@ -73,21 +76,21 @@ fn test_basic() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, true, theme::basic()),
|
create_table(vec![row(4); 1], true, theme::basic()),
|
||||||
"+---+---+---+---+\n\
|
"+---+---+---+---+\n\
|
||||||
| 0 | 1 | 2 | 3 |\n\
|
| 0 | 1 | 2 | 3 |\n\
|
||||||
+---+---+---+---+"
|
+---+---+---+---+"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, false, theme::basic()),
|
create_table(vec![row(4); 1], false, theme::basic()),
|
||||||
"+---+---+---+---+\n\
|
"+---+---+---+---+\n\
|
||||||
| 0 | 1 | 2 | 3 |\n\
|
| 0 | 1 | 2 | 3 |\n\
|
||||||
+---+---+---+---+"
|
+---+---+---+---+"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, false, theme::basic()),
|
create_table(vec![row(4); 2], false, theme::basic()),
|
||||||
"+---+---+---+---+\n\
|
"+---+---+---+---+\n\
|
||||||
| 0 | 1 | 2 | 3 |\n\
|
| 0 | 1 | 2 | 3 |\n\
|
||||||
+---+---+---+---+\n\
|
+---+---+---+---+\n\
|
||||||
|
@ -95,13 +98,16 @@ fn test_basic() {
|
||||||
+---+---+---+---+"
|
+---+---+---+---+"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(draw_table(vec![row(4); 0], 4, false, theme::basic()), "");
|
assert_eq!(
|
||||||
|
create_table_with_size(vec![row(4); 0], (0, 4), true, theme::basic()),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reinforced() {
|
fn test_reinforced() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::reinforced()),
|
create_table(vec![row(4); 3], true, theme::reinforced()),
|
||||||
"┏───┬───┬───┬───┓\n\
|
"┏───┬───┬───┬───┓\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
|
@ -110,7 +116,7 @@ fn test_reinforced() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::reinforced()),
|
create_table(vec![row(4); 2], true, theme::reinforced()),
|
||||||
"┏───┬───┬───┬───┓\n\
|
"┏───┬───┬───┬───┓\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
|
@ -118,21 +124,21 @@ fn test_reinforced() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, true, theme::reinforced()),
|
create_table(vec![row(4); 1], true, theme::reinforced()),
|
||||||
"┏───┬───┬───┬───┓\n\
|
"┏───┬───┬───┬───┓\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
┗───┴───┴───┴───┛"
|
┗───┴───┴───┴───┛"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, false, theme::reinforced()),
|
create_table(vec![row(4); 1], false, theme::reinforced()),
|
||||||
"┏───┬───┬───┬───┓\n\
|
"┏───┬───┬───┬───┓\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
┗───┴───┴───┴───┛"
|
┗───┴───┴───┴───┛"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, false, theme::reinforced()),
|
create_table(vec![row(4); 2], false, theme::reinforced()),
|
||||||
"┏───┬───┬───┬───┓\n\
|
"┏───┬───┬───┬───┓\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
|
@ -140,7 +146,7 @@ fn test_reinforced() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 0], 2, false, theme::reinforced()),
|
create_table_with_size(vec![row(4); 0], (0, 4), true, theme::reinforced()),
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -148,7 +154,7 @@ fn test_reinforced() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_compact() {
|
fn test_compact() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::compact()),
|
create_table(vec![row(4); 3], true, theme::compact()),
|
||||||
concat!(
|
concat!(
|
||||||
"───┬───┬───┬───\n",
|
"───┬───┬───┬───\n",
|
||||||
" 0 │ 1 │ 2 │ 3 \n",
|
" 0 │ 1 │ 2 │ 3 \n",
|
||||||
|
@ -160,7 +166,7 @@ fn test_compact() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::compact()),
|
create_table(vec![row(4); 2], true, theme::compact()),
|
||||||
concat!(
|
concat!(
|
||||||
"───┬───┬───┬───\n",
|
"───┬───┬───┬───\n",
|
||||||
" 0 │ 1 │ 2 │ 3 \n",
|
" 0 │ 1 │ 2 │ 3 \n",
|
||||||
|
@ -171,17 +177,17 @@ fn test_compact() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, true, theme::compact()),
|
create_table(vec![row(4); 1], true, theme::compact()),
|
||||||
concat!("───┬───┬───┬───\n", " 0 │ 1 │ 2 │ 3 \n", "───┴───┴───┴───",)
|
concat!("───┬───┬───┬───\n", " 0 │ 1 │ 2 │ 3 \n", "───┴───┴───┴───",)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, false, theme::compact()),
|
create_table(vec![row(4); 1], false, theme::compact()),
|
||||||
concat!("───┬───┬───┬───\n", " 0 │ 1 │ 2 │ 3 \n", "───┴───┴───┴───",)
|
concat!("───┬───┬───┬───\n", " 0 │ 1 │ 2 │ 3 \n", "───┴───┴───┴───",)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, false, theme::compact()),
|
create_table(vec![row(4); 2], false, theme::compact()),
|
||||||
concat!(
|
concat!(
|
||||||
"───┬───┬───┬───\n",
|
"───┬───┬───┬───\n",
|
||||||
" 0 │ 1 │ 2 │ 3 \n",
|
" 0 │ 1 │ 2 │ 3 \n",
|
||||||
|
@ -190,13 +196,16 @@ fn test_compact() {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(draw_table(vec![row(4); 0], 4, false, theme::compact()), "");
|
assert_eq!(
|
||||||
|
create_table_with_size(vec![row(4); 0], (0, 4), true, theme::compact()),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_compact_double() {
|
fn test_compact_double() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::compact_double()),
|
create_table(vec![row(4); 3], true, theme::compact_double()),
|
||||||
concat!(
|
concat!(
|
||||||
"═══╦═══╦═══╦═══\n",
|
"═══╦═══╦═══╦═══\n",
|
||||||
" 0 ║ 1 ║ 2 ║ 3 \n",
|
" 0 ║ 1 ║ 2 ║ 3 \n",
|
||||||
|
@ -208,7 +217,7 @@ fn test_compact_double() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::compact_double()),
|
create_table(vec![row(4); 2], true, theme::compact_double()),
|
||||||
concat!(
|
concat!(
|
||||||
"═══╦═══╦═══╦═══\n",
|
"═══╦═══╦═══╦═══\n",
|
||||||
" 0 ║ 1 ║ 2 ║ 3 \n",
|
" 0 ║ 1 ║ 2 ║ 3 \n",
|
||||||
|
@ -219,17 +228,17 @@ fn test_compact_double() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, true, theme::compact_double()),
|
create_table(vec![row(4); 1], true, theme::compact_double()),
|
||||||
concat!("═══╦═══╦═══╦═══\n", " 0 ║ 1 ║ 2 ║ 3 \n", "═══╩═══╩═══╩═══",)
|
concat!("═══╦═══╦═══╦═══\n", " 0 ║ 1 ║ 2 ║ 3 \n", "═══╩═══╩═══╩═══",)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, false, theme::compact_double()),
|
create_table(vec![row(4); 1], false, theme::compact_double()),
|
||||||
concat!("═══╦═══╦═══╦═══\n", " 0 ║ 1 ║ 2 ║ 3 \n", "═══╩═══╩═══╩═══",)
|
concat!("═══╦═══╦═══╦═══\n", " 0 ║ 1 ║ 2 ║ 3 \n", "═══╩═══╩═══╩═══",)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, false, theme::compact_double()),
|
create_table(vec![row(4); 2], false, theme::compact_double()),
|
||||||
concat!(
|
concat!(
|
||||||
"═══╦═══╦═══╦═══\n",
|
"═══╦═══╦═══╦═══\n",
|
||||||
" 0 ║ 1 ║ 2 ║ 3 \n",
|
" 0 ║ 1 ║ 2 ║ 3 \n",
|
||||||
|
@ -239,7 +248,7 @@ fn test_compact_double() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 0], 4, false, theme::compact_double()),
|
create_table_with_size(vec![row(4); 0], (0, 4), true, theme::compact_double()),
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +256,7 @@ fn test_compact_double() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_heavy() {
|
fn test_heavy() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::heavy()),
|
create_table(vec![row(4); 3], true, theme::heavy()),
|
||||||
"┏━━━┳━━━┳━━━┳━━━┓\n\
|
"┏━━━┳━━━┳━━━┳━━━┓\n\
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
||||||
┣━━━╋━━━╋━━━╋━━━┫\n\
|
┣━━━╋━━━╋━━━╋━━━┫\n\
|
||||||
|
@ -257,7 +266,7 @@ fn test_heavy() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::heavy()),
|
create_table(vec![row(4); 2], true, theme::heavy()),
|
||||||
"┏━━━┳━━━┳━━━┳━━━┓\n\
|
"┏━━━┳━━━┳━━━┳━━━┓\n\
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
||||||
┣━━━╋━━━╋━━━╋━━━┫\n\
|
┣━━━╋━━━╋━━━╋━━━┫\n\
|
||||||
|
@ -266,34 +275,37 @@ fn test_heavy() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, true, theme::heavy()),
|
create_table(vec![row(4); 1], true, theme::heavy()),
|
||||||
"┏━━━┳━━━┳━━━┳━━━┓\n\
|
"┏━━━┳━━━┳━━━┳━━━┓\n\
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
||||||
┗━━━┻━━━┻━━━┻━━━┛"
|
┗━━━┻━━━┻━━━┻━━━┛"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, false, theme::heavy()),
|
create_table(vec![row(4); 1], false, theme::heavy()),
|
||||||
"┏━━━┳━━━┳━━━┳━━━┓\n\
|
"┏━━━┳━━━┳━━━┳━━━┓\n\
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
||||||
┗━━━┻━━━┻━━━┻━━━┛"
|
┗━━━┻━━━┻━━━┻━━━┛"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, false, theme::heavy()),
|
create_table(vec![row(4); 2], false, theme::heavy()),
|
||||||
"┏━━━┳━━━┳━━━┳━━━┓\n\
|
"┏━━━┳━━━┳━━━┳━━━┓\n\
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
||||||
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\
|
||||||
┗━━━┻━━━┻━━━┻━━━┛"
|
┗━━━┻━━━┻━━━┻━━━┛"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(draw_table(vec![row(4); 0], 4, false, theme::heavy()), "");
|
assert_eq!(
|
||||||
|
create_table_with_size(vec![row(4); 0], (0, 4), true, theme::heavy()),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_light() {
|
fn test_light() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::light()),
|
create_table(vec![row(4); 3], true, theme::light()),
|
||||||
concat!(
|
concat!(
|
||||||
" 0 1 2 3 \n",
|
" 0 1 2 3 \n",
|
||||||
"───────────────\n",
|
"───────────────\n",
|
||||||
|
@ -303,62 +315,68 @@ fn test_light() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::light()),
|
create_table(vec![row(4); 2], true, theme::light()),
|
||||||
concat!(" 0 1 2 3 \n", "───────────────\n", " 0 1 2 3 ")
|
concat!(" 0 1 2 3 \n", "───────────────\n", " 0 1 2 3 ")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, true, theme::light()),
|
create_table(vec![row(4); 1], true, theme::light()),
|
||||||
concat!(" 0 1 2 3 ")
|
concat!(" 0 1 2 3 ")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, false, theme::light()),
|
create_table(vec![row(4); 1], false, theme::light()),
|
||||||
concat!(" 0 1 2 3 ")
|
concat!(" 0 1 2 3 ")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, false, theme::light()),
|
create_table(vec![row(4); 2], false, theme::light()),
|
||||||
concat!(" 0 1 2 3 \n", " 0 1 2 3 ")
|
concat!(" 0 1 2 3 \n", " 0 1 2 3 ")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(draw_table(vec![row(4); 0], 4, true, theme::light()), "");
|
assert_eq!(
|
||||||
|
create_table_with_size(vec![row(4); 0], (0, 4), true, theme::light()),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_none() {
|
fn test_none() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::none()),
|
create_table(vec![row(4); 3], true, theme::none()),
|
||||||
concat!(" 0 1 2 3 \n", " 0 1 2 3 \n", " 0 1 2 3 ")
|
concat!(" 0 1 2 3 \n", " 0 1 2 3 \n", " 0 1 2 3 ")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::none()),
|
create_table(vec![row(4); 2], true, theme::none()),
|
||||||
concat!(" 0 1 2 3 \n", " 0 1 2 3 ")
|
concat!(" 0 1 2 3 \n", " 0 1 2 3 ")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, true, theme::none()),
|
create_table(vec![row(4); 1], true, theme::none()),
|
||||||
concat!(" 0 1 2 3 ")
|
concat!(" 0 1 2 3 ")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, false, theme::none()),
|
create_table(vec![row(4); 1], false, theme::none()),
|
||||||
concat!(" 0 1 2 3 ")
|
concat!(" 0 1 2 3 ")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::none()),
|
create_table(vec![row(4); 2], true, theme::none()),
|
||||||
concat!(" 0 1 2 3 \n", " 0 1 2 3 ")
|
concat!(" 0 1 2 3 \n", " 0 1 2 3 ")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(draw_table(vec![row(4); 0], 4, true, theme::none()), "");
|
assert_eq!(
|
||||||
|
create_table_with_size(vec![row(4); 0], (0, 4), true, theme::none()),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_thin() {
|
fn test_thin() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::thin()),
|
create_table(vec![row(4); 3], true, theme::thin()),
|
||||||
"┌───┬───┬───┬───┐\n\
|
"┌───┬───┬───┬───┐\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
├───┼───┼───┼───┤\n\
|
├───┼───┼───┼───┤\n\
|
||||||
|
@ -369,7 +387,7 @@ fn test_thin() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::thin()),
|
create_table(vec![row(4); 2], true, theme::thin()),
|
||||||
"┌───┬───┬───┬───┐\n\
|
"┌───┬───┬───┬───┐\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
├───┼───┼───┼───┤\n\
|
├───┼───┼───┼───┤\n\
|
||||||
|
@ -378,21 +396,21 @@ fn test_thin() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, true, theme::thin()),
|
create_table(vec![row(4); 1], true, theme::thin()),
|
||||||
"┌───┬───┬───┬───┐\n\
|
"┌───┬───┬───┬───┐\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
└───┴───┴───┴───┘"
|
└───┴───┴───┴───┘"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, false, theme::thin()),
|
create_table(vec![row(4); 1], false, theme::thin()),
|
||||||
"┌───┬───┬───┬───┐\n\
|
"┌───┬───┬───┬───┐\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
└───┴───┴───┴───┘"
|
└───┴───┴───┴───┘"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, false, theme::thin()),
|
create_table(vec![row(4); 2], false, theme::thin()),
|
||||||
"┌───┬───┬───┬───┐\n\
|
"┌───┬───┬───┬───┐\n\
|
||||||
│ 0 │ 1 │ 2 │ 3 │\n\
|
│ 0 │ 1 │ 2 │ 3 │\n\
|
||||||
├───┼───┼───┼───┤\n\
|
├───┼───┼───┼───┤\n\
|
||||||
|
@ -400,13 +418,16 @@ fn test_thin() {
|
||||||
└───┴───┴───┴───┘"
|
└───┴───┴───┴───┘"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(draw_table(vec![row(4); 0], 4, true, theme::thin()), "");
|
assert_eq!(
|
||||||
|
create_table_with_size(vec![row(4); 0], (0, 4), true, theme::thin()),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_with_love() {
|
fn test_with_love() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 3], 4, true, theme::with_love()),
|
create_table(vec![row(4); 3], true, theme::with_love()),
|
||||||
concat!(
|
concat!(
|
||||||
"❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n",
|
"❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n",
|
||||||
" 0 ❤ 1 ❤ 2 ❤ 3 \n",
|
" 0 ❤ 1 ❤ 2 ❤ 3 \n",
|
||||||
|
@ -418,7 +439,7 @@ fn test_with_love() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, true, theme::with_love()),
|
create_table(vec![row(4); 2], true, theme::with_love()),
|
||||||
concat!(
|
concat!(
|
||||||
"❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n",
|
"❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n",
|
||||||
" 0 ❤ 1 ❤ 2 ❤ 3 \n",
|
" 0 ❤ 1 ❤ 2 ❤ 3 \n",
|
||||||
|
@ -429,17 +450,17 @@ fn test_with_love() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, true, theme::with_love()),
|
create_table(vec![row(4); 1], true, theme::with_love()),
|
||||||
concat!("❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n", " 0 ❤ 1 ❤ 2 ❤ 3 \n", "❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤",)
|
concat!("❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n", " 0 ❤ 1 ❤ 2 ❤ 3 \n", "❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤",)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 1], 4, false, theme::with_love()),
|
create_table(vec![row(4); 1], false, theme::with_love()),
|
||||||
concat!("❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n", " 0 ❤ 1 ❤ 2 ❤ 3 \n", "❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤",)
|
concat!("❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n", " 0 ❤ 1 ❤ 2 ❤ 3 \n", "❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤",)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draw_table(vec![row(4); 2], 4, false, theme::with_love()),
|
create_table(vec![row(4); 2], false, theme::with_love()),
|
||||||
concat!(
|
concat!(
|
||||||
"❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n",
|
"❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n",
|
||||||
" 0 ❤ 1 ❤ 2 ❤ 3 \n",
|
" 0 ❤ 1 ❤ 2 ❤ 3 \n",
|
||||||
|
@ -448,32 +469,30 @@ fn test_with_love() {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(draw_table(vec![row(4); 0], 4, true, theme::with_love()), "");
|
assert_eq!(
|
||||||
|
create_table_with_size(vec![row(4); 0], (0, 4), true, theme::with_love()),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_table(
|
fn create_table(data: VecCells, with_header: bool, theme: theme) -> String {
|
||||||
data: Vec<Vec<TCell<CellInfo<'static>, TextStyle>>>,
|
let config = TableConfig::new(theme, with_header, false, false);
|
||||||
count_columns: usize,
|
let out = common::create_table(data, config, usize::MAX);
|
||||||
|
|
||||||
|
out.expect("not expected to get None")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_table_with_size(
|
||||||
|
data: VecCells,
|
||||||
|
size: (usize, usize),
|
||||||
with_header: bool,
|
with_header: bool,
|
||||||
theme: theme,
|
theme: theme,
|
||||||
) -> String {
|
) -> String {
|
||||||
let size = (data.len(), count_columns);
|
let config = TableConfig::new(theme, with_header, false, false);
|
||||||
let table = Table::new(data, size, usize::MAX, with_header, false);
|
|
||||||
|
let table = nu_table::Table::new(data, size);
|
||||||
|
|
||||||
let cfg = Config::default();
|
|
||||||
let styles = HashMap::default();
|
|
||||||
let alignments = Alignments::default();
|
|
||||||
table
|
table
|
||||||
.draw_table(&cfg, &styles, alignments, &theme, std::usize::MAX, false)
|
.draw(config, usize::MAX)
|
||||||
.expect("Unexpectdly got no table")
|
.expect("not expected to get None")
|
||||||
}
|
|
||||||
|
|
||||||
fn row(count_columns: usize) -> Vec<TCell<CellInfo<'static>, TextStyle>> {
|
|
||||||
let mut row = Vec::with_capacity(count_columns);
|
|
||||||
|
|
||||||
for i in 0..count_columns {
|
|
||||||
row.push(Table::create_cell(i.to_string(), TextStyle::default()));
|
|
||||||
}
|
|
||||||
|
|
||||||
row
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue