mirror of
https://github.com/nushell/nushell.git
synced 2025-08-16 02:38:37 +02:00
Bump tabled
dependency to 0.11 (#8922)
close? #8060 Quite a bit of refactoring took place. I believe a few improvements to collapse/expand were made. I've tried to track any performance regressions and seems like it is fine. I've noticed something different now with default configuration path or something in this regard? So I might missed something while testing because of this. Requires some oversight. --------- Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
This commit is contained in:
@ -28,7 +28,6 @@ nu-table = { path = "../nu-table", version = "0.79.1" }
|
||||
nu-term-grid = { path = "../nu-term-grid", version = "0.79.1" }
|
||||
nu-utils = { path = "../nu-utils", version = "0.79.1" }
|
||||
num-format = { version = "0.4.3" }
|
||||
|
||||
nu-ansi-term = "0.47.0"
|
||||
|
||||
# Potential dependencies for extras
|
||||
@ -89,7 +88,7 @@ percent-encoding = "2.2.0"
|
||||
rusqlite = { version = "0.28.0", features = ["bundled"], optional = true }
|
||||
sqlparser = { version = "0.32.0", features = ["serde"], optional = true }
|
||||
sysinfo = "0.28.2"
|
||||
tabled = "0.10.0"
|
||||
tabled = "0.12.0"
|
||||
terminal_size = "0.2.1"
|
||||
thiserror = "1.0.31"
|
||||
titlecase = "2.0.0"
|
||||
|
@ -1,123 +1,193 @@
|
||||
use nu_protocol::Value;
|
||||
use nu_table::{string_width, string_wrap};
|
||||
use tabled::{
|
||||
builder::Builder,
|
||||
peaker::PriorityMax,
|
||||
width::{MinWidth, Wrap},
|
||||
Style,
|
||||
grid::config::ColoredConfig,
|
||||
settings::{peaker::PriorityMax, width::Wrap, Settings, Style},
|
||||
Table,
|
||||
};
|
||||
|
||||
use self::{
|
||||
global_horizontal_char::SetHorizontalCharOnFirstRow, peak2::Peak2,
|
||||
table_column_width::get_first_cell_width, truncate_table::TruncateTable,
|
||||
width_increase::IncWidth,
|
||||
use crate::debug::inspect_table::{
|
||||
global_horizontal_char::SetHorizontalChar, set_widths::SetWidths,
|
||||
};
|
||||
|
||||
pub fn build_table(value: Value, description: String, termsize: usize) -> String {
|
||||
let (head, mut data) = util::collect_input(value);
|
||||
let count_columns = head.len();
|
||||
data.insert(0, head);
|
||||
|
||||
let mut val_table = Builder::from(data).build();
|
||||
let val_table_width = val_table.total_width();
|
||||
let mut desc = description;
|
||||
let mut desc_width = string_width(&desc);
|
||||
let mut desc_table_width = get_total_width_2_column_table(11, desc_width);
|
||||
|
||||
let desc = vec![vec![String::from("description"), description]];
|
||||
let cfg = Table::default().with(Style::modern()).get_config().clone();
|
||||
let mut widths = get_data_widths(&data, count_columns);
|
||||
truncate_data(&mut data, &mut widths, &cfg, termsize);
|
||||
|
||||
let mut desc_table = Builder::from(desc).build();
|
||||
let desc_table_width = desc_table.total_width();
|
||||
let val_table_width = get_total_width2(&widths, &cfg);
|
||||
if val_table_width < desc_table_width {
|
||||
increase_widths(&mut widths, desc_table_width - val_table_width);
|
||||
increase_data_width(&mut data, &widths);
|
||||
}
|
||||
|
||||
if val_table_width > desc_table_width {
|
||||
increase_string_width(&mut desc, val_table_width);
|
||||
}
|
||||
|
||||
if desc_table_width > termsize {
|
||||
let delete_width = desc_table_width - termsize;
|
||||
if delete_width >= desc_width {
|
||||
// we can't fit in a description; we consider it's no point in showing then?
|
||||
return String::new();
|
||||
}
|
||||
|
||||
desc_width -= delete_width;
|
||||
desc = string_wrap(&desc, desc_width, false);
|
||||
desc_table_width = termsize;
|
||||
}
|
||||
|
||||
add_padding_to_widths(&mut widths);
|
||||
|
||||
#[allow(clippy::manual_clamp)]
|
||||
let width = val_table_width.max(desc_table_width).min(termsize);
|
||||
|
||||
desc_table
|
||||
.with(Style::rounded().off_bottom())
|
||||
.with(Wrap::new(width).priority::<PriorityMax>())
|
||||
.with(MinWidth::new(width).priority::<Peak2>());
|
||||
let mut desc_table = Table::from_iter([[String::from("description"), desc]]);
|
||||
desc_table.with(Style::rounded().remove_bottom().remove_horizontals());
|
||||
|
||||
val_table
|
||||
.with(Style::rounded().top_left_corner('├').top_right_corner('┤'))
|
||||
.with(TruncateTable(width))
|
||||
.with(Wrap::new(width).priority::<PriorityMax>())
|
||||
.with(IncWidth(width));
|
||||
|
||||
// we use only 1, cause left border considered 0 position
|
||||
let count_split_lines = 1;
|
||||
let desc_width = get_first_cell_width(&mut desc_table) + count_split_lines;
|
||||
|
||||
val_table.with(SetHorizontalCharOnFirstRow::new('┼', '┴', desc_width));
|
||||
let mut val_table = Table::from_iter(data);
|
||||
val_table.with(
|
||||
Settings::default()
|
||||
.with(Style::rounded().corner_top_left('├').corner_top_right('┤'))
|
||||
.with(SetWidths(widths))
|
||||
.with(Wrap::new(width).priority::<PriorityMax>())
|
||||
.with(SetHorizontalChar::new('┼', '┴', 11 + 2 + 1)),
|
||||
);
|
||||
|
||||
format!("{desc_table}\n{val_table}")
|
||||
}
|
||||
|
||||
mod truncate_table {
|
||||
use tabled::{
|
||||
papergrid::{
|
||||
records::{Records, RecordsMut, Resizable},
|
||||
width::{CfgWidthFunction, WidthEstimator},
|
||||
Estimate,
|
||||
},
|
||||
TableOption,
|
||||
};
|
||||
|
||||
pub struct TruncateTable(pub usize);
|
||||
|
||||
impl<R> TableOption<R> for TruncateTable
|
||||
where
|
||||
R: Records + RecordsMut<String> + Resizable,
|
||||
{
|
||||
fn change(&mut self, table: &mut tabled::Table<R>) {
|
||||
let width = table.total_width();
|
||||
if width <= self.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let count_columns = table.get_records().count_columns();
|
||||
if count_columns < 1 {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut evaluator = WidthEstimator::default();
|
||||
evaluator.estimate(table.get_records(), table.get_config());
|
||||
let columns_width: Vec<_> = evaluator.into();
|
||||
|
||||
const SPLIT_LINE_WIDTH: usize = 1;
|
||||
let mut width = 0;
|
||||
let mut i = 0;
|
||||
for w in columns_width {
|
||||
width += w + SPLIT_LINE_WIDTH;
|
||||
|
||||
if width >= self.0 {
|
||||
break;
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if i == 0 && count_columns > 0 {
|
||||
i = 1;
|
||||
} else if i + 1 == count_columns {
|
||||
// we want to left at least 1 column
|
||||
i -= 1;
|
||||
}
|
||||
|
||||
let count_columns = table.get_records().count_columns();
|
||||
let y = count_columns - i;
|
||||
|
||||
let mut column = count_columns;
|
||||
for _ in 0..y {
|
||||
column -= 1;
|
||||
table.get_records_mut().remove_column(column);
|
||||
}
|
||||
|
||||
table.get_records_mut().push_column();
|
||||
|
||||
let width_ctrl = CfgWidthFunction::from_cfg(table.get_config());
|
||||
let last_column = table.get_records().count_columns() - 1;
|
||||
for row in 0..table.get_records().count_rows() {
|
||||
table
|
||||
.get_records_mut()
|
||||
.set((row, last_column), String::from("‥"), &width_ctrl)
|
||||
}
|
||||
fn get_data_widths(data: &[Vec<String>], count_columns: usize) -> Vec<usize> {
|
||||
let mut widths = vec![0; count_columns];
|
||||
for row in data {
|
||||
for col in 0..count_columns {
|
||||
let text = &row[col];
|
||||
let width = string_width(text);
|
||||
widths[col] = std::cmp::max(widths[col], width);
|
||||
}
|
||||
}
|
||||
|
||||
widths
|
||||
}
|
||||
|
||||
fn add_padding_to_widths(widths: &mut [usize]) {
|
||||
for width in widths {
|
||||
*width += 2;
|
||||
}
|
||||
}
|
||||
|
||||
fn increase_widths(widths: &mut [usize], need: usize) {
|
||||
let all = need / widths.len();
|
||||
let mut rest = need - all * widths.len();
|
||||
|
||||
for width in widths {
|
||||
*width += all;
|
||||
|
||||
if rest > 0 {
|
||||
*width += 1;
|
||||
rest -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn increase_data_width(data: &mut Vec<Vec<String>>, widths: &[usize]) {
|
||||
for row in data {
|
||||
for (col, max_width) in widths.iter().enumerate() {
|
||||
let text = &mut row[col];
|
||||
increase_string_width(text, *max_width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn increase_string_width(text: &mut String, total: usize) {
|
||||
let width = string_width(text);
|
||||
let rest = total - width;
|
||||
|
||||
if rest > 0 {
|
||||
text.extend(std::iter::repeat(' ').take(rest));
|
||||
}
|
||||
}
|
||||
|
||||
fn get_total_width_2_column_table(col1: usize, col2: usize) -> usize {
|
||||
const PAD: usize = 1;
|
||||
const SPLIT_LINE: usize = 1;
|
||||
SPLIT_LINE + PAD + col1 + PAD + SPLIT_LINE + PAD + col2 + PAD + SPLIT_LINE
|
||||
}
|
||||
|
||||
fn truncate_data(
|
||||
data: &mut Vec<Vec<String>>,
|
||||
widths: &mut Vec<usize>,
|
||||
cfg: &ColoredConfig,
|
||||
expected_width: usize,
|
||||
) {
|
||||
const SPLIT_LINE_WIDTH: usize = 1;
|
||||
const PAD: usize = 2;
|
||||
|
||||
let total_width = get_total_width2(widths, cfg);
|
||||
if total_width <= expected_width {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut width = 0;
|
||||
let mut peak_count = 0;
|
||||
for column_width in widths.iter() {
|
||||
let next_width = width + *column_width + SPLIT_LINE_WIDTH + PAD;
|
||||
if next_width >= expected_width {
|
||||
break;
|
||||
}
|
||||
|
||||
width = next_width;
|
||||
peak_count += 1;
|
||||
}
|
||||
|
||||
debug_assert!(peak_count < widths.len());
|
||||
|
||||
let left_space = expected_width - width;
|
||||
let has_space_for_truncation_column = left_space > PAD;
|
||||
if !has_space_for_truncation_column {
|
||||
peak_count -= 1;
|
||||
}
|
||||
|
||||
remove_columns(data, peak_count);
|
||||
widths.drain(peak_count..);
|
||||
push_empty_column(data);
|
||||
widths.push(1);
|
||||
}
|
||||
|
||||
fn remove_columns(data: &mut Vec<Vec<String>>, peak_count: usize) {
|
||||
if peak_count == 0 {
|
||||
for row in data {
|
||||
row.clear();
|
||||
}
|
||||
} else {
|
||||
for row in data {
|
||||
row.drain(peak_count..);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_total_width2(widths: &[usize], cfg: &ColoredConfig) -> usize {
|
||||
let pad = 2;
|
||||
let total = widths.iter().sum::<usize>() + pad * widths.len();
|
||||
let countv = cfg.count_vertical(widths.len());
|
||||
let margin = cfg.get_margin();
|
||||
|
||||
total + countv + margin.left.size + margin.right.size
|
||||
}
|
||||
|
||||
fn push_empty_column(data: &mut Vec<Vec<String>>) {
|
||||
let empty_cell = String::from("‥");
|
||||
for row in data {
|
||||
row.push(empty_cell.clone());
|
||||
}
|
||||
}
|
||||
|
||||
mod util {
|
||||
@ -223,135 +293,74 @@ mod util {
|
||||
}
|
||||
}
|
||||
|
||||
mod style_no_left_right_1st {
|
||||
use tabled::{papergrid::records::Records, Table, TableOption};
|
||||
|
||||
struct StyleOffLeftRightFirstLine;
|
||||
|
||||
impl<R> TableOption<R> for StyleOffLeftRightFirstLine
|
||||
where
|
||||
R: Records,
|
||||
{
|
||||
fn change(&mut self, table: &mut Table<R>) {
|
||||
let shape = table.shape();
|
||||
let cfg = table.get_config_mut();
|
||||
|
||||
let mut b = cfg.get_border((0, 0), shape);
|
||||
b.left = Some(' ');
|
||||
cfg.set_border((0, 0), b);
|
||||
|
||||
let mut b = cfg.get_border((0, shape.1 - 1), shape);
|
||||
b.right = Some(' ');
|
||||
cfg.set_border((0, 0), b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod peak2 {
|
||||
use tabled::peaker::Peaker;
|
||||
|
||||
pub struct Peak2;
|
||||
|
||||
impl Peaker for Peak2 {
|
||||
fn create() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
fn peak(&mut self, _: &[usize], _: &[usize]) -> Option<usize> {
|
||||
Some(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod table_column_width {
|
||||
use tabled::{
|
||||
papergrid::{records::Records, width::CfgWidthFunction},
|
||||
Table,
|
||||
};
|
||||
|
||||
pub fn get_first_cell_width<R: Records>(table: &mut Table<R>) -> usize {
|
||||
let mut opt = GetFirstCellWidth(0);
|
||||
table.with(&mut opt);
|
||||
opt.0
|
||||
}
|
||||
|
||||
struct GetFirstCellWidth(pub usize);
|
||||
|
||||
impl<R: Records> tabled::TableOption<R> for GetFirstCellWidth {
|
||||
fn change(&mut self, table: &mut tabled::Table<R>) {
|
||||
let w = table
|
||||
.get_records()
|
||||
.get_width((0, 0), CfgWidthFunction::default());
|
||||
let pad = table
|
||||
.get_config()
|
||||
.get_padding(tabled::papergrid::Entity::Cell(0, 0));
|
||||
let pad = pad.left.size + pad.right.size;
|
||||
|
||||
self.0 = w + pad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod global_horizontal_char {
|
||||
use tabled::{
|
||||
papergrid::{records::Records, width::WidthEstimator, Estimate, Offset::Begin},
|
||||
Table, TableOption,
|
||||
grid::{
|
||||
config::{ColoredConfig, Offset},
|
||||
dimension::{CompleteDimensionVecRecords, Dimension},
|
||||
records::{ExactRecords, Records},
|
||||
},
|
||||
settings::TableOption,
|
||||
};
|
||||
|
||||
pub struct SetHorizontalCharOnFirstRow {
|
||||
c1: char,
|
||||
c2: char,
|
||||
pos: usize,
|
||||
pub struct SetHorizontalChar {
|
||||
intersection: char,
|
||||
split: char,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl SetHorizontalCharOnFirstRow {
|
||||
pub fn new(c1: char, c2: char, pos: usize) -> Self {
|
||||
Self { c1, c2, pos }
|
||||
impl SetHorizontalChar {
|
||||
pub fn new(intersection: char, split: char, index: usize) -> Self {
|
||||
Self {
|
||||
intersection,
|
||||
split,
|
||||
index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> TableOption<R> for SetHorizontalCharOnFirstRow
|
||||
where
|
||||
R: Records,
|
||||
impl<R: Records + ExactRecords> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig>
|
||||
for SetHorizontalChar
|
||||
{
|
||||
fn change(&mut self, table: &mut Table<R>) {
|
||||
if table.is_empty() {
|
||||
fn change(
|
||||
self,
|
||||
records: &mut R,
|
||||
cfg: &mut ColoredConfig,
|
||||
dimension: &mut CompleteDimensionVecRecords<'_>,
|
||||
) {
|
||||
let count_columns = records.count_columns();
|
||||
let count_rows = records.count_rows();
|
||||
|
||||
if count_columns == 0 || count_rows == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let shape = table.shape();
|
||||
let widths = get_widths(dimension, records.count_columns());
|
||||
|
||||
let mut evaluator = WidthEstimator::default();
|
||||
evaluator.estimate(table.get_records(), table.get_config());
|
||||
let widths: Vec<_> = evaluator.into();
|
||||
|
||||
let has_vertical = table.get_config().has_vertical(0, shape.1);
|
||||
if has_vertical && self.pos == 0 {
|
||||
let mut border = table.get_config().get_border((0, 0), shape);
|
||||
border.left_top_corner = Some(self.c1);
|
||||
table.get_config_mut().set_border((0, 0), border);
|
||||
let has_vertical = cfg.has_vertical(0, count_columns);
|
||||
if has_vertical && self.index == 0 {
|
||||
let mut border = cfg.get_border((0, 0), (count_rows, count_columns));
|
||||
border.left_top_corner = Some(self.intersection);
|
||||
cfg.set_border((0, 0), border);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut i = 1;
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for (col, width) in widths.into_iter().enumerate() {
|
||||
if self.pos < i + width {
|
||||
let o = self.pos - i;
|
||||
table
|
||||
.get_config_mut()
|
||||
.override_horizontal_border((0, col), self.c2, Begin(o));
|
||||
if self.index < i + width {
|
||||
let o = self.index - i;
|
||||
cfg.set_horizontal_char((0, col), self.split, Offset::Begin(o));
|
||||
return;
|
||||
}
|
||||
|
||||
i += width;
|
||||
|
||||
let has_vertical = table.get_config().has_vertical(col, shape.1);
|
||||
let has_vertical = cfg.has_vertical(col, count_columns);
|
||||
if has_vertical {
|
||||
if self.pos == i {
|
||||
let mut border = table.get_config().get_border((0, col), shape);
|
||||
border.right_top_corner = Some(self.c1);
|
||||
table.get_config_mut().set_border((0, col), border);
|
||||
if self.index == i {
|
||||
let mut border = cfg.get_border((0, col), (count_rows, count_columns));
|
||||
border.right_top_corner = Some(self.intersection);
|
||||
cfg.set_border((0, col), border);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -360,96 +369,33 @@ mod global_horizontal_char {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod width_increase {
|
||||
use tabled::{
|
||||
object::Cell,
|
||||
papergrid::{
|
||||
records::{Records, RecordsMut},
|
||||
width::WidthEstimator,
|
||||
Entity, Estimate, GridConfig,
|
||||
},
|
||||
peaker::PriorityNone,
|
||||
Modify, Width,
|
||||
};
|
||||
|
||||
use tabled::{peaker::Peaker, Table, TableOption};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IncWidth(pub usize);
|
||||
|
||||
impl<R> TableOption<R> for IncWidth
|
||||
where
|
||||
R: Records + RecordsMut<String>,
|
||||
{
|
||||
fn change(&mut self, table: &mut Table<R>) {
|
||||
if table.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let (widths, total_width) =
|
||||
get_table_widths_with_total(table.get_records(), table.get_config());
|
||||
if total_width >= self.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let increase_list =
|
||||
get_increase_list(widths, self.0, total_width, PriorityNone::default());
|
||||
|
||||
for (col, width) in increase_list.into_iter().enumerate() {
|
||||
for row in 0..table.get_records().count_rows() {
|
||||
let pad = table.get_config().get_padding(Entity::Cell(row, col));
|
||||
let width = width - pad.left.size - pad.right.size;
|
||||
|
||||
table.with(Modify::new(Cell(row, col)).with(Width::increase(width)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_increase_list<F>(
|
||||
mut widths: Vec<usize>,
|
||||
total_width: usize,
|
||||
mut width: usize,
|
||||
mut peaker: F,
|
||||
) -> Vec<usize>
|
||||
where
|
||||
F: Peaker,
|
||||
{
|
||||
while width != total_width {
|
||||
let col = match peaker.peak(&[], &widths) {
|
||||
Some(col) => col,
|
||||
None => break,
|
||||
};
|
||||
|
||||
widths[col] += 1;
|
||||
width += 1;
|
||||
fn get_widths(dims: &CompleteDimensionVecRecords<'_>, count_columns: usize) -> Vec<usize> {
|
||||
let mut widths = vec![0; count_columns];
|
||||
for (col, width) in widths.iter_mut().enumerate() {
|
||||
*width = dims.get_width(col);
|
||||
}
|
||||
|
||||
widths
|
||||
}
|
||||
}
|
||||
|
||||
fn get_table_widths_with_total<R>(records: R, cfg: &GridConfig) -> (Vec<usize>, usize)
|
||||
where
|
||||
R: Records,
|
||||
{
|
||||
let mut evaluator = WidthEstimator::default();
|
||||
evaluator.estimate(&records, cfg);
|
||||
let total_width = get_table_total_width(&records, cfg, &evaluator);
|
||||
let widths = evaluator.into();
|
||||
mod set_widths {
|
||||
use tabled::{
|
||||
grid::{config::ColoredConfig, dimension::CompleteDimensionVecRecords},
|
||||
settings::TableOption,
|
||||
};
|
||||
|
||||
(widths, total_width)
|
||||
}
|
||||
pub struct SetWidths(pub Vec<usize>);
|
||||
|
||||
pub(crate) fn get_table_total_width<W, R>(records: R, cfg: &GridConfig, ctrl: &W) -> usize
|
||||
where
|
||||
W: Estimate<R>,
|
||||
R: Records,
|
||||
{
|
||||
ctrl.total()
|
||||
+ cfg.count_vertical(records.count_columns())
|
||||
+ cfg.get_margin().left.size
|
||||
+ cfg.get_margin().right.size
|
||||
impl<R> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for SetWidths {
|
||||
fn change(
|
||||
self,
|
||||
_: &mut R,
|
||||
_: &mut ColoredConfig,
|
||||
dims: &mut CompleteDimensionVecRecords<'_>,
|
||||
) {
|
||||
dims.set_widths(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -154,11 +154,11 @@ fn table_collapse_none() {
|
||||
assert_eq!(
|
||||
actual.out,
|
||||
concat!(
|
||||
" a b c ",
|
||||
" 1 2 3 ",
|
||||
" 4 5 1 ",
|
||||
" 2 ",
|
||||
" 3 ",
|
||||
" a b c ",
|
||||
" 1 2 3 ",
|
||||
" 4 5 1 ",
|
||||
" 2 ",
|
||||
" 3 ",
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -232,11 +232,20 @@ fn table_collapse_hearts() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table_collapse_doesnot_support_width_control() {
|
||||
fn table_collapse_does_wrapping_for_long_strings() {
|
||||
let actual = nu!(
|
||||
r#"[[a]; [11111111111111111111111111111111111111111111111111111111111111111111111111111111]] | table --collapse"#
|
||||
);
|
||||
assert_eq!(actual.out, "Couldn't fit table into 80 columns!");
|
||||
assert_eq!(
|
||||
actual.out,
|
||||
"╭────────────────────────────────╮\
|
||||
│ a │\
|
||||
├────────────────────────────────┤\
|
||||
│ 111111111111111109312339230430 │\
|
||||
│ 179149313814687359833671239329 │\
|
||||
│ 01313323321729744896.0000 │\
|
||||
╰────────────────────────────────╯"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1795,6 +1804,526 @@ fn table_expande_with_no_header_internally_1() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collapse_big_0() {
|
||||
Playground::setup("test_expand_big_0", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContent(
|
||||
"sample.toml",
|
||||
r#"
|
||||
[package]
|
||||
authors = ["The Nushell Project Developers"]
|
||||
default-run = "nu"
|
||||
description = "A new type of shell"
|
||||
documentation = "https://www.nushell.sh/book/"
|
||||
edition = "2021"
|
||||
exclude = ["images"]
|
||||
homepage = "https://www.nushell.sh"
|
||||
license = "MIT"
|
||||
name = "nu"
|
||||
repository = "https://github.com/nushell/nushell"
|
||||
rust-version = "1.60"
|
||||
version = "0.74.1"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[package.metadata.binstall]
|
||||
pkg-url = "{ repo }/releases/download/{ version }/{ name }-{ version }-{ target }.{ archive-format }"
|
||||
pkg-fmt = "tgz"
|
||||
|
||||
[package.metadata.binstall.overrides.x86_64-pc-windows-msvc]
|
||||
pkg-fmt = "zip"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/nu-cli",
|
||||
"crates/nu-engine",
|
||||
"crates/nu-parser",
|
||||
"crates/nu-system",
|
||||
"crates/nu-command",
|
||||
"crates/nu-protocol",
|
||||
"crates/nu-plugin",
|
||||
"crates/nu_plugin_inc",
|
||||
"crates/nu_plugin_gstat",
|
||||
"crates/nu_plugin_example",
|
||||
"crates/nu_plugin_query",
|
||||
"crates/nu_plugin_custom_values",
|
||||
"crates/nu-utils",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
chrono = { version = "0.4.23", features = ["serde"] }
|
||||
crossterm = "0.24.0"
|
||||
ctrlc = "3.2.1"
|
||||
log = "0.4"
|
||||
miette = { version = "5.5.0", features = ["fancy-no-backtrace"] }
|
||||
nu-ansi-term = "0.46.0"
|
||||
nu-cli = { path = "./crates/nu-cli", version = "0.74.1" }
|
||||
nu-engine = { path = "./crates/nu-engine", version = "0.74.1" }
|
||||
reedline = { version = "0.14.0", features = ["bashisms", "sqlite"] }
|
||||
|
||||
rayon = "1.6.1"
|
||||
is_executable = "1.0.1"
|
||||
simplelog = "0.12.0"
|
||||
time = "0.3.12"
|
||||
|
||||
[target.'cfg(not(target_os = "windows"))'.dependencies]
|
||||
# Our dependencies don't use OpenSSL on Windows
|
||||
openssl = { version = "0.10.38", features = ["vendored"], optional = true }
|
||||
signal-hook = { version = "0.3.14", default-features = false }
|
||||
|
||||
|
||||
[target.'cfg(windows)'.build-dependencies]
|
||||
winres = "0.1"
|
||||
|
||||
[target.'cfg(target_family = "unix")'.dependencies]
|
||||
nix = { version = "0.25", default-features = false, features = ["signal", "process", "fs", "term"] }
|
||||
atty = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
nu-test-support = { path = "./crates/nu-test-support", version = "0.74.1" }
|
||||
tempfile = "3.2.0"
|
||||
assert_cmd = "2.0.2"
|
||||
criterion = "0.4"
|
||||
pretty_assertions = "1.0.0"
|
||||
serial_test = "0.10.0"
|
||||
hamcrest2 = "0.3.0"
|
||||
rstest = { version = "0.15.0", default-features = false }
|
||||
itertools = "0.10.3"
|
||||
|
||||
[features]
|
||||
plugin = [
|
||||
"nu-plugin",
|
||||
"nu-cli/plugin",
|
||||
"nu-parser/plugin",
|
||||
"nu-command/plugin",
|
||||
"nu-protocol/plugin",
|
||||
"nu-engine/plugin",
|
||||
]
|
||||
# extra used to be more useful but now it's the same as default. Leaving it in for backcompat with existing build scripts
|
||||
extra = ["default"]
|
||||
default = ["plugin", "which-support", "trash-support", "sqlite"]
|
||||
stable = ["default"]
|
||||
wasi = []
|
||||
|
||||
# Enable to statically link OpenSSL; otherwise the system version will be used. Not enabled by default because it takes a while to build
|
||||
static-link-openssl = ["dep:openssl"]
|
||||
|
||||
# Stable (Default)
|
||||
which-support = ["nu-command/which-support"]
|
||||
trash-support = ["nu-command/trash-support"]
|
||||
|
||||
# Main nu binary
|
||||
[[bin]]
|
||||
name = "nu"
|
||||
path = "src/main.rs"
|
||||
|
||||
# To use a development version of a dependency please use a global override here
|
||||
# changing versions in each sub-crate of the workspace is tedious
|
||||
[patch.crates-io]
|
||||
reedline = { git = "https://github.com/nushell/reedline.git", branch = "main" }
|
||||
|
||||
# Criterion benchmarking setup
|
||||
# Run all benchmarks with `cargo bench`
|
||||
# Run individual benchmarks like `cargo bench -- <regex>` e.g. `cargo bench -- parse`
|
||||
[[bench]]
|
||||
name = "benchmarks"
|
||||
harness = false
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
"open sample.toml | table --collapse"
|
||||
));
|
||||
|
||||
_print_lines(&actual.out, 80);
|
||||
|
||||
let expected = join_lines([
|
||||
"╭──────────────────┬─────────┬─────────────────────────────────────────────────╮",
|
||||
"│ bench │ harness │ name │",
|
||||
"│ ├─────────┼─────────────────────────────────────────────────┤",
|
||||
"│ │ false │ benchmarks │",
|
||||
"├──────────────────┼──────┬──┴─────────────────────────────────────────────────┤",
|
||||
"│ bin │ name │ path │",
|
||||
"│ ├──────┼────────────────────────────────────────────────────┤",
|
||||
"│ │ nu │ src/main.rs │",
|
||||
"├──────────────────┼──────┴────────┬──────────┬────────────────────────────────┤",
|
||||
"│ dependencies │ chrono │ features │ serde │",
|
||||
"│ │ ├──────────┼────────────────────────────────┤",
|
||||
"│ │ │ version │ 0.4.23 │",
|
||||
"│ ├───────────────┼──────────┴────────────────────────────────┤",
|
||||
"│ │ crossterm │ 0.24.0 │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ ctrlc │ 3.2.1 │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ is_executable │ 1.0.1 │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ log │ 0.4 │",
|
||||
"│ ├───────────────┼──────────┬────────────────────────────────┤",
|
||||
"│ │ miette │ features │ fancy-no-backtrace │",
|
||||
"│ │ ├──────────┼────────────────────────────────┤",
|
||||
"│ │ │ version │ 5.5.0 │",
|
||||
"│ ├───────────────┼──────────┴────────────────────────────────┤",
|
||||
"│ │ nu-ansi-term │ 0.46.0 │",
|
||||
"│ ├───────────────┼─────────┬─────────────────────────────────┤",
|
||||
"│ │ nu-cli │ path │ ./crates/nu-cli │",
|
||||
"│ │ ├─────────┼─────────────────────────────────┤",
|
||||
"│ │ │ version │ 0.74.1 │",
|
||||
"│ ├───────────────┼─────────┼─────────────────────────────────┤",
|
||||
"│ │ nu-engine │ path │ ./crates/nu-engine │",
|
||||
"│ │ ├─────────┼─────────────────────────────────┤",
|
||||
"│ │ │ version │ 0.74.1 │",
|
||||
"│ ├───────────────┼─────────┴─────────────────────────────────┤",
|
||||
"│ │ rayon │ 1.6.1 │",
|
||||
"│ ├───────────────┼──────────┬────────────────────────────────┤",
|
||||
"│ │ reedline │ features │ bashisms │",
|
||||
"│ │ │ ├────────────────────────────────┤",
|
||||
"│ │ │ │ sqlite │",
|
||||
"│ │ ├──────────┼────────────────────────────────┤",
|
||||
"│ │ │ version │ 0.14.0 │",
|
||||
"│ ├───────────────┼──────────┴────────────────────────────────┤",
|
||||
"│ │ simplelog │ 0.12.0 │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ time │ 0.3.12 │",
|
||||
"├──────────────────┼───────────────┴───┬───────────────────────────────────────┤",
|
||||
"│ dev-dependencies │ assert_cmd │ 2.0.2 │",
|
||||
"│ ├───────────────────┼───────────────────────────────────────┤",
|
||||
"│ │ criterion │ 0.4 │",
|
||||
"│ ├───────────────────┼───────────────────────────────────────┤",
|
||||
"│ │ hamcrest2 │ 0.3.0 │",
|
||||
"│ ├───────────────────┼───────────────────────────────────────┤",
|
||||
"│ │ itertools │ 0.10.3 │",
|
||||
"│ ├───────────────────┼─────────┬─────────────────────────────┤",
|
||||
"│ │ nu-test-support │ path │ ./crates/nu-test-support │",
|
||||
"│ │ ├─────────┼─────────────────────────────┤",
|
||||
"│ │ │ version │ 0.74.1 │",
|
||||
"│ ├───────────────────┼─────────┴─────────────────────────────┤",
|
||||
"│ │ pretty_assertions │ 1.0.0 │",
|
||||
"│ ├───────────────────┼──────────────────┬────────────────────┤",
|
||||
"│ │ rstest │ default-features │ false │",
|
||||
"│ │ ├──────────────────┼────────────────────┤",
|
||||
"│ │ │ version │ 0.15.0 │",
|
||||
"│ ├───────────────────┼──────────────────┴────────────────────┤",
|
||||
"│ │ serial_test │ 0.10.0 │",
|
||||
"│ ├───────────────────┼───────────────────────────────────────┤",
|
||||
"│ │ tempfile │ 3.2.0 │",
|
||||
"├──────────────────┼───────────────────┴─┬─────────────────────────────────────┤",
|
||||
"│ features │ default │ plugin │",
|
||||
"│ │ ├─────────────────────────────────────┤",
|
||||
"│ │ │ which-support │",
|
||||
"│ │ ├─────────────────────────────────────┤",
|
||||
"│ │ │ trash-support │",
|
||||
"│ │ ├─────────────────────────────────────┤",
|
||||
"│ │ │ sqlite │",
|
||||
"│ ├─────────────────────┼─────────────────────────────────────┤",
|
||||
"│ │ extra │ default │",
|
||||
"│ ├─────────────────────┼─────────────────────────────────────┤",
|
||||
"│ │ plugin │ nu-plugin │",
|
||||
"│ │ ├─────────────────────────────────────┤",
|
||||
"│ │ │ nu-cli/plugin │",
|
||||
"│ │ ├─────────────────────────────────────┤",
|
||||
"│ │ │ nu-parser/plugin │",
|
||||
"│ │ ├─────────────────────────────────────┤",
|
||||
"│ │ │ nu-command/plugin │",
|
||||
"│ │ ├─────────────────────────────────────┤",
|
||||
"│ │ │ nu-protocol/plugin │",
|
||||
"│ │ ├─────────────────────────────────────┤",
|
||||
"│ │ │ nu-engine/plugin │",
|
||||
"│ ├─────────────────────┼─────────────────────────────────────┤",
|
||||
"│ │ stable │ default │",
|
||||
"│ ├─────────────────────┼─────────────────────────────────────┤",
|
||||
"│ │ static-link-openssl │ dep:openssl │",
|
||||
"│ ├─────────────────────┼─────────────────────────────────────┤",
|
||||
"│ │ trash-support │ nu-command/trash-support │",
|
||||
"│ ├─────────────────────┼─────────────────────────────────────┤",
|
||||
"│ │ wasi │ │",
|
||||
"│ ├─────────────────────┼─────────────────────────────────────┤",
|
||||
"│ │ which-support │ nu-command/which-support │",
|
||||
"├──────────────────┼───────────────┬─────┴─────────────────────────────────────┤",
|
||||
"│ package │ authors │ The Nushell Project Developers │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ default-run │ nu │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ description │ A new type of shell │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ documentation │ https://www.nushell.sh/book/ │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ edition │ 2021 │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ exclude │ images │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ homepage │ https://www.nushell.sh │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ license │ MIT │",
|
||||
"│ ├───────────────┼──────────┬───────────┬────────────────────┤",
|
||||
"│ │ metadata │ binstall │ overrides │ ... │",
|
||||
"│ │ │ ├───────────┼────────────────────┤",
|
||||
"│ │ │ │ pkg-fmt │ tgz │",
|
||||
"│ │ │ ├───────────┼────────────────────┤",
|
||||
"│ │ │ │ pkg-url │ { repo }/releases/ │",
|
||||
"│ │ │ │ │ download/{ v │",
|
||||
"│ │ │ │ │ ersion │",
|
||||
"│ │ │ │ │ }/{ name }-{ vers │",
|
||||
"│ │ │ │ │ ion }- │",
|
||||
"│ │ │ │ │ { target }.{ │",
|
||||
"│ │ │ │ │ archive-format } │",
|
||||
"│ ├───────────────┼──────────┴───────────┴────────────────────┤",
|
||||
"│ │ name │ nu │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ repository │ https://github.com/nushell/nushell │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ rust-version │ 1.60 │",
|
||||
"│ ├───────────────┼───────────────────────────────────────────┤",
|
||||
"│ │ version │ 0.74.1 │",
|
||||
"├──────────────────┼───────────┬───┴──────┬────────┬───────────────────────────┤",
|
||||
"│ patch │ crates-io │ reedline │ branch │ main │",
|
||||
"│ │ │ ├────────┼───────────────────────────┤",
|
||||
"│ │ │ │ git │ https://github.com/nushel │",
|
||||
"│ │ │ │ │ l/reedline.git │",
|
||||
"├──────────────────┼───────────┴──────────┴────────┴─┬──────────────┬──────────┤",
|
||||
"│ target │ cfg(not(target_os = \"windows\")) │ dependencies │ ... │",
|
||||
"│ │ │ ├──────────┤",
|
||||
"│ │ │ │ ... │",
|
||||
"│ ├─────────────────────────────────┼──────────────┼──────────┤",
|
||||
"│ │ cfg(target_family = \"unix\") │ dependencies │ ... │",
|
||||
"│ │ │ ├──────────┤",
|
||||
"│ │ │ │ ... │",
|
||||
"│ ├─────────────────────────────────┼──────────────┴──────────┤",
|
||||
"│ │ cfg(windows) │ ... │",
|
||||
"├──────────────────┼─────────┬───────────────────────┴─────────────────────────┤",
|
||||
"│ workspace │ members │ crates/nu-cli │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-engine │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-parser │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-system │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-command │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-protocol │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-plugin │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu_plugin_inc │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu_plugin_gstat │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu_plugin_example │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu_plugin_query │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu_plugin_custom_values │",
|
||||
"│ │ ├─────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-utils │",
|
||||
"╰──────────────────┴─────────┴─────────────────────────────────────────────────╯",
|
||||
]);
|
||||
|
||||
assert_eq!(actual.out, expected);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
"open sample.toml | table --collapse --width=160"
|
||||
));
|
||||
|
||||
_print_lines(&actual.out, 111);
|
||||
|
||||
let expected = join_lines([
|
||||
"╭──────────────────┬─────────┬────────────────────────────────────────────────────────────────────────────────╮",
|
||||
"│ bench │ harness │ name │",
|
||||
"│ ├─────────┼────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ false │ benchmarks │",
|
||||
"├──────────────────┼──────┬──┴────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ bin │ name │ path │",
|
||||
"│ ├──────┼───────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ nu │ src/main.rs │",
|
||||
"├──────────────────┼──────┴────────┬──────────┬───────────────────────────────────────────────────────────────┤",
|
||||
"│ dependencies │ chrono │ features │ serde │",
|
||||
"│ │ ├──────────┼───────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ version │ 0.4.23 │",
|
||||
"│ ├───────────────┼──────────┴───────────────────────────────────────────────────────────────┤",
|
||||
"│ │ crossterm │ 0.24.0 │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ ctrlc │ 3.2.1 │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ is_executable │ 1.0.1 │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ log │ 0.4 │",
|
||||
"│ ├───────────────┼──────────┬───────────────────────────────────────────────────────────────┤",
|
||||
"│ │ miette │ features │ fancy-no-backtrace │",
|
||||
"│ │ ├──────────┼───────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ version │ 5.5.0 │",
|
||||
"│ ├───────────────┼──────────┴───────────────────────────────────────────────────────────────┤",
|
||||
"│ │ nu-ansi-term │ 0.46.0 │",
|
||||
"│ ├───────────────┼─────────┬────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ nu-cli │ path │ ./crates/nu-cli │",
|
||||
"│ │ ├─────────┼────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ version │ 0.74.1 │",
|
||||
"│ ├───────────────┼─────────┼────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ nu-engine │ path │ ./crates/nu-engine │",
|
||||
"│ │ ├─────────┼────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ version │ 0.74.1 │",
|
||||
"│ ├───────────────┼─────────┴────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ rayon │ 1.6.1 │",
|
||||
"│ ├───────────────┼──────────┬───────────────────────────────────────────────────────────────┤",
|
||||
"│ │ reedline │ features │ bashisms │",
|
||||
"│ │ │ ├───────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ │ sqlite │",
|
||||
"│ │ ├──────────┼───────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ version │ 0.14.0 │",
|
||||
"│ ├───────────────┼──────────┴───────────────────────────────────────────────────────────────┤",
|
||||
"│ │ simplelog │ 0.12.0 │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ time │ 0.3.12 │",
|
||||
"├──────────────────┼───────────────┴───┬──────────────────────────────────────────────────────────────────────┤",
|
||||
"│ dev-dependencies │ assert_cmd │ 2.0.2 │",
|
||||
"│ ├───────────────────┼──────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ criterion │ 0.4 │",
|
||||
"│ ├───────────────────┼──────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ hamcrest2 │ 0.3.0 │",
|
||||
"│ ├───────────────────┼──────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ itertools │ 0.10.3 │",
|
||||
"│ ├───────────────────┼─────────┬────────────────────────────────────────────────────────────┤",
|
||||
"│ │ nu-test-support │ path │ ./crates/nu-test-support │",
|
||||
"│ │ ├─────────┼────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ version │ 0.74.1 │",
|
||||
"│ ├───────────────────┼─────────┴────────────────────────────────────────────────────────────┤",
|
||||
"│ │ pretty_assertions │ 1.0.0 │",
|
||||
"│ ├───────────────────┼──────────────────┬───────────────────────────────────────────────────┤",
|
||||
"│ │ rstest │ default-features │ false │",
|
||||
"│ │ ├──────────────────┼───────────────────────────────────────────────────┤",
|
||||
"│ │ │ version │ 0.15.0 │",
|
||||
"│ ├───────────────────┼──────────────────┴───────────────────────────────────────────────────┤",
|
||||
"│ │ serial_test │ 0.10.0 │",
|
||||
"│ ├───────────────────┼──────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ tempfile │ 3.2.0 │",
|
||||
"├──────────────────┼───────────────────┴─┬────────────────────────────────────────────────────────────────────┤",
|
||||
"│ features │ default │ plugin │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ which-support │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ trash-support │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ sqlite │",
|
||||
"│ ├─────────────────────┼────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ extra │ default │",
|
||||
"│ ├─────────────────────┼────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ plugin │ nu-plugin │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ nu-cli/plugin │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ nu-parser/plugin │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ nu-command/plugin │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ nu-protocol/plugin │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ nu-engine/plugin │",
|
||||
"│ ├─────────────────────┼────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ stable │ default │",
|
||||
"│ ├─────────────────────┼────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ static-link-openssl │ dep:openssl │",
|
||||
"│ ├─────────────────────┼────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ trash-support │ nu-command/trash-support │",
|
||||
"│ ├─────────────────────┼────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ wasi │ │",
|
||||
"│ ├─────────────────────┼────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ which-support │ nu-command/which-support │",
|
||||
"├──────────────────┼───────────────┬─────┴────────────────────────────────────────────────────────────────────┤",
|
||||
"│ package │ authors │ The Nushell Project Developers │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ default-run │ nu │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ description │ A new type of shell │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ documentation │ https://www.nushell.sh/book/ │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ edition │ 2021 │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ exclude │ images │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ homepage │ https://www.nushell.sh │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ license │ MIT │",
|
||||
"│ ├───────────────┼──────────┬───────────┬────────────────────────┬─────────┬────────────────┤",
|
||||
"│ │ metadata │ binstall │ overrides │ x86_64-pc-windows-msvc │ pkg-fmt │ zip │",
|
||||
"│ │ │ ├───────────┼────────────────────────┴─────────┴────────────────┤",
|
||||
"│ │ │ │ pkg-fmt │ tgz │",
|
||||
"│ │ │ ├───────────┼───────────────────────────────────────────────────┤",
|
||||
"│ │ │ │ pkg-url │ { repo }/releases/download/{ v │",
|
||||
"│ │ │ │ │ ersion }/{ name }-{ version }- │",
|
||||
"│ │ │ │ │ { target }.{ archive-format } │",
|
||||
"│ ├───────────────┼──────────┴───────────┴───────────────────────────────────────────────────┤",
|
||||
"│ │ name │ nu │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ repository │ https://github.com/nushell/nushell │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ rust-version │ 1.60 │",
|
||||
"│ ├───────────────┼──────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ version │ 0.74.1 │",
|
||||
"├──────────────────┼───────────┬───┴──────┬────────┬──────────────────────────────────────────────────────────┤",
|
||||
"│ patch │ crates-io │ reedline │ branch │ main │",
|
||||
"│ │ │ ├────────┼──────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ │ git │ https://github.com/nushell/reedline.git │",
|
||||
"├──────────────────┼───────────┴──────────┴────────┴─┬──────────────┬─────────────┬──────────┬────────────────┤",
|
||||
"│ target │ cfg(not(target_os = \"windows\")) │ dependencies │ openssl │ features │ vendored │",
|
||||
"│ │ │ │ ├──────────┼────────────────┤",
|
||||
"│ │ │ │ │ optional │ true │",
|
||||
"│ │ │ │ ├──────────┼────────────────┤",
|
||||
"│ │ │ │ │ version │ 0.10.38 │",
|
||||
"│ │ │ ├─────────────┼──────────┴───────┬────────┤",
|
||||
"│ │ │ │ signal-hook │ default-features │ false │",
|
||||
"│ │ │ │ ├──────────────────┼────────┤",
|
||||
"│ │ │ │ │ version │ 0.3.14 │",
|
||||
"│ ├─────────────────────────────────┼──────────────┼──────┬──────┴──────────────────┴────────┤",
|
||||
"│ │ cfg(target_family = \"unix\") │ dependencies │ atty │ 0.2 │",
|
||||
"│ │ │ ├──────┼──────────────────┬───────────────┤",
|
||||
"│ │ │ │ nix │ default-features │ false │",
|
||||
"│ │ │ │ ├──────────────────┼───────────────┤",
|
||||
"│ │ │ │ │ features │ signal │",
|
||||
"│ │ │ │ │ ├───────────────┤",
|
||||
"│ │ │ │ │ │ process │",
|
||||
"│ │ │ │ │ ├───────────────┤",
|
||||
"│ │ │ │ │ │ fs │",
|
||||
"│ │ │ │ │ ├───────────────┤",
|
||||
"│ │ │ │ │ │ term │",
|
||||
"│ │ │ │ ├──────────────────┼───────────────┤",
|
||||
"│ │ │ │ │ version │ 0.25 │",
|
||||
"│ ├─────────────────────────────────┼──────────────┴─────┬┴───────┬──────────┴───────────────┤",
|
||||
"│ │ cfg(windows) │ build-dependencies │ winres │ 0.1 │",
|
||||
"├──────────────────┼─────────┬───────────────────────┴────────────────────┴────────┴──────────────────────────┤",
|
||||
"│ workspace │ members │ crates/nu-cli │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-engine │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-parser │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-system │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-command │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-protocol │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-plugin │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu_plugin_inc │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu_plugin_gstat │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu_plugin_example │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu_plugin_query │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu_plugin_custom_values │",
|
||||
"│ │ ├────────────────────────────────────────────────────────────────────────────────┤",
|
||||
"│ │ │ crates/nu-utils │",
|
||||
"╰──────────────────┴─────────┴────────────────────────────────────────────────────────────────────────────────╯",
|
||||
]);
|
||||
|
||||
assert_eq!(actual.out, expected);
|
||||
})
|
||||
}
|
||||
|
||||
fn join_lines(lines: impl IntoIterator<Item = impl AsRef<str>>) -> String {
|
||||
lines
|
||||
.into_iter()
|
||||
|
Reference in New Issue
Block a user