mirror of
https://github.com/nushell/nushell
synced 2024-12-27 21:43:09 +00:00
Finish move to nu-table (#2025)
This commit is contained in:
parent
4e83363dd3
commit
89c737f456
6 changed files with 111 additions and 161 deletions
23
Cargo.lock
generated
23
Cargo.lock
generated
|
@ -1899,9 +1899,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "kstring"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6382df53100fd22e149030b6634720c94a151076db8d727b3274d7070975d609"
|
||||
checksum = "fbbc30beb80d56ddf6346e935c7abcba96329ee5c5a4cde8984a4e6b6f18b58e"
|
||||
dependencies = [
|
||||
"serde 1.0.110",
|
||||
]
|
||||
|
@ -2038,9 +2038,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "liquid-core"
|
||||
version = "0.20.1"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ea59709d9530bab4e9cc0ece12f20fe4999fdef90f7d89391b0fc9ff563b62b"
|
||||
checksum = "4dc58422728185d54cd044bba4d45a2ef2a7111a421f84d344f65629949de4f1"
|
||||
dependencies = [
|
||||
"anymap",
|
||||
"chrono",
|
||||
|
@ -2481,7 +2481,6 @@ dependencies = [
|
|||
"pin-utils",
|
||||
"pretty-hex",
|
||||
"pretty_env_logger",
|
||||
"prettytable-rs",
|
||||
"ptree",
|
||||
"query_interface",
|
||||
"quickcheck",
|
||||
|
@ -3235,20 +3234,6 @@ dependencies = [
|
|||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prettytable-rs"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fd04b170004fa2daccf418a7f8253aaf033c27760b5f225889024cf66d7ac2e"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"csv",
|
||||
"encode_unicode",
|
||||
"lazy_static 1.4.0",
|
||||
"term",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.2"
|
||||
|
|
|
@ -62,7 +62,6 @@ parking_lot = "0.10.2"
|
|||
pin-utils = "0.1.0"
|
||||
pretty-hex = "0.1.1"
|
||||
pretty_env_logger = "0.4.0"
|
||||
prettytable-rs = "0.8.0"
|
||||
ptree = {version = "0.2" }
|
||||
query_interface = "0.3.5"
|
||||
rand = "0.7"
|
||||
|
|
|
@ -6,10 +6,7 @@ use nu_errors::ShellError;
|
|||
use nu_protocol::{hir, hir::Expression, hir::Literal, hir::SpannedExpression};
|
||||
use nu_protocol::{Primitive, Scope, Signature, UntaggedValue, Value};
|
||||
use parking_lot::Mutex;
|
||||
use prettytable::format::{FormatBuilder, LinePosition, LineSeparator};
|
||||
use prettytable::{color, Attr, Cell, Row, Table};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use textwrap::fill;
|
||||
|
||||
pub struct Autoview;
|
||||
|
||||
|
@ -268,90 +265,28 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
|
|||
+ row.entries.iter().count() * 2)
|
||||
> textwrap::termwidth()) =>
|
||||
{
|
||||
let termwidth = std::cmp::max(textwrap::termwidth(), 20);
|
||||
|
||||
enum TableMode {
|
||||
Light,
|
||||
Normal,
|
||||
}
|
||||
|
||||
let mut table = Table::new();
|
||||
let table_mode = crate::data::config::config(Tag::unknown());
|
||||
|
||||
let table_mode = if let Some(s) = table_mode?.get("table_mode") {
|
||||
match s.as_string() {
|
||||
Ok(typ) if typ == "light" => TableMode::Light,
|
||||
_ => TableMode::Normal,
|
||||
}
|
||||
} else {
|
||||
TableMode::Normal
|
||||
};
|
||||
|
||||
match table_mode {
|
||||
TableMode::Light => {
|
||||
table.set_format(
|
||||
FormatBuilder::new()
|
||||
.separator(
|
||||
LinePosition::Title,
|
||||
LineSeparator::new('─', '─', ' ', ' '),
|
||||
)
|
||||
.separator(
|
||||
LinePosition::Bottom,
|
||||
LineSeparator::new(' ', ' ', ' ', ' '),
|
||||
)
|
||||
.padding(1, 1)
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
table.set_format(
|
||||
FormatBuilder::new()
|
||||
.column_separator('│')
|
||||
.separator(
|
||||
LinePosition::Top,
|
||||
LineSeparator::new('─', '┬', ' ', ' '),
|
||||
)
|
||||
.separator(
|
||||
LinePosition::Title,
|
||||
LineSeparator::new('─', '┼', ' ', ' '),
|
||||
)
|
||||
.separator(
|
||||
LinePosition::Bottom,
|
||||
LineSeparator::new('─', '┴', ' ', ' '),
|
||||
)
|
||||
.padding(1, 1)
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let mut max_key_len = 0;
|
||||
for (key, _) in row.entries.iter() {
|
||||
max_key_len = std::cmp::max(max_key_len, key.chars().count());
|
||||
}
|
||||
|
||||
if max_key_len > (termwidth / 2 - 1) {
|
||||
max_key_len = termwidth / 2 - 1;
|
||||
}
|
||||
|
||||
let max_val_len = termwidth - max_key_len - 5;
|
||||
|
||||
let mut entries = vec![];
|
||||
for (key, value) in row.entries.iter() {
|
||||
table.add_row(Row::new(vec![
|
||||
Cell::new(&fill(&key, max_key_len))
|
||||
.with_style(Attr::ForegroundColor(color::GREEN))
|
||||
.with_style(Attr::Bold),
|
||||
Cell::new(&fill(
|
||||
&format_leaf(value).plain_string(100_000),
|
||||
max_val_len,
|
||||
)),
|
||||
]));
|
||||
entries.push(vec![
|
||||
nu_table::StyledString::new(
|
||||
key.to_string(),
|
||||
nu_table::TextStyle {
|
||||
alignment: nu_table::Alignment::Left,
|
||||
color: Some(ansi_term::Color::Green),
|
||||
is_bold: true,
|
||||
},
|
||||
),
|
||||
nu_table::StyledString::new(
|
||||
format_leaf(value).plain_string(100_000),
|
||||
nu_table::TextStyle::basic(),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
table.printstd();
|
||||
let table =
|
||||
nu_table::Table::new(vec![], entries, nu_table::Theme::compact());
|
||||
|
||||
// table.print_term(&mut *context.host.lock().out_terminal().ok_or_else(|| ShellError::untagged_runtime_error("Could not open terminal for output"))?)
|
||||
// .map_err(|_| ShellError::untagged_runtime_error("Internal error: could not print to terminal (for unix systems check to make sure TERM is set)"))?;
|
||||
nu_table::draw_table(&table, textwrap::termwidth());
|
||||
}
|
||||
|
||||
Value {
|
||||
|
|
|
@ -56,7 +56,7 @@ fn str_to_color(s: String) -> Option<ansi_term::Color> {
|
|||
pub fn from_list(values: &[Value], starting_idx: usize) -> nu_table::Table {
|
||||
let config = crate::data::config::config(Tag::unknown());
|
||||
|
||||
let header_style = if let Ok(config) = config {
|
||||
let header_style = if let Ok(config) = &config {
|
||||
let header_align = config.get("header_align").map_or(Alignment::Left, |a| {
|
||||
a.as_string()
|
||||
.map_or(Alignment::Center, |a| match a.to_lowercase().as_str() {
|
||||
|
@ -97,6 +97,19 @@ pub fn from_list(values: &[Value], starting_idx: usize) -> nu_table::Table {
|
|||
.collect();
|
||||
let entries = values_to_entries(values, &mut headers, starting_idx);
|
||||
|
||||
if let Ok(config) = config {
|
||||
if let Some(style) = config.get("table_mode") {
|
||||
if let Ok(table_mode) = style.as_string() {
|
||||
if table_mode == "light" {
|
||||
return nu_table::Table {
|
||||
headers,
|
||||
data: entries,
|
||||
theme: Theme::light(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nu_table::Table {
|
||||
headers,
|
||||
data: entries,
|
||||
|
|
|
@ -81,6 +81,8 @@ pub struct Theme {
|
|||
|
||||
pub print_left_border: bool,
|
||||
pub print_right_border: bool,
|
||||
pub print_top_border: bool,
|
||||
pub print_bottom_border: bool,
|
||||
}
|
||||
|
||||
impl Theme {
|
||||
|
@ -108,6 +110,8 @@ impl Theme {
|
|||
|
||||
print_left_border: true,
|
||||
print_right_border: true,
|
||||
print_top_border: true,
|
||||
print_bottom_border: true,
|
||||
}
|
||||
}
|
||||
#[allow(unused)]
|
||||
|
@ -136,6 +140,8 @@ impl Theme {
|
|||
|
||||
print_left_border: true,
|
||||
print_right_border: true,
|
||||
print_top_border: true,
|
||||
print_bottom_border: true,
|
||||
}
|
||||
}
|
||||
#[allow(unused)]
|
||||
|
@ -160,10 +166,12 @@ impl Theme {
|
|||
right_vertical: ' ',
|
||||
|
||||
separate_header: true,
|
||||
separate_rows: true,
|
||||
separate_rows: false,
|
||||
|
||||
print_left_border: true,
|
||||
print_right_border: true,
|
||||
print_top_border: false,
|
||||
print_bottom_border: true,
|
||||
}
|
||||
}
|
||||
#[allow(unused)]
|
||||
|
@ -191,6 +199,8 @@ impl Theme {
|
|||
|
||||
print_left_border: false,
|
||||
print_right_border: false,
|
||||
print_top_border: true,
|
||||
print_bottom_border: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -227,84 +237,77 @@ pub struct WrappedTable {
|
|||
}
|
||||
|
||||
impl WrappedTable {
|
||||
//TODO: optimize this
|
||||
fn print_separator(&self, separator_position: SeparatorPosition) {
|
||||
let column_count = self.column_widths.len();
|
||||
let mut output = String::new();
|
||||
|
||||
match separator_position {
|
||||
SeparatorPosition::Top => {
|
||||
for column in self.column_widths.iter().enumerate() {
|
||||
if column.0 == 0 && self.theme.print_left_border {
|
||||
print!("{}", self.theme.top_left);
|
||||
output.push(self.theme.top_left);
|
||||
}
|
||||
print!(
|
||||
"{}",
|
||||
std::iter::repeat(self.theme.top_horizontal)
|
||||
.take(*column.1)
|
||||
.collect::<String>()
|
||||
);
|
||||
|
||||
print!("{}{}", self.theme.top_horizontal, self.theme.top_horizontal);
|
||||
for _ in 0..*column.1 {
|
||||
output.push(self.theme.top_horizontal);
|
||||
}
|
||||
|
||||
output.push(self.theme.top_horizontal);
|
||||
output.push(self.theme.top_horizontal);
|
||||
if column.0 == column_count - 1 {
|
||||
if self.theme.print_right_border {
|
||||
print!("{}", self.theme.top_right);
|
||||
output.push(self.theme.top_right);
|
||||
}
|
||||
} else {
|
||||
print!("{}", self.theme.top_center);
|
||||
output.push(self.theme.top_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
SeparatorPosition::Middle => {
|
||||
for column in self.column_widths.iter().enumerate() {
|
||||
if column.0 == 0 && self.theme.print_left_border {
|
||||
print!("{}", self.theme.middle_left);
|
||||
output.push(self.theme.middle_left);
|
||||
}
|
||||
print!(
|
||||
"{}",
|
||||
std::iter::repeat(self.theme.middle_horizontal)
|
||||
.take(*column.1)
|
||||
.collect::<String>()
|
||||
);
|
||||
|
||||
print!(
|
||||
"{}{}",
|
||||
self.theme.middle_horizontal, self.theme.middle_horizontal
|
||||
);
|
||||
for _ in 0..*column.1 {
|
||||
output.push(self.theme.middle_horizontal);
|
||||
}
|
||||
|
||||
output.push(self.theme.middle_horizontal);
|
||||
output.push(self.theme.middle_horizontal);
|
||||
|
||||
if column.0 == column_count - 1 {
|
||||
if self.theme.print_right_border {
|
||||
print!("{}", self.theme.middle_right);
|
||||
output.push(self.theme.middle_right);
|
||||
}
|
||||
} else {
|
||||
print!("{}", self.theme.center);
|
||||
output.push(self.theme.center);
|
||||
}
|
||||
}
|
||||
}
|
||||
SeparatorPosition::Bottom => {
|
||||
for column in self.column_widths.iter().enumerate() {
|
||||
if column.0 == 0 && self.theme.print_left_border {
|
||||
print!("{}", self.theme.bottom_left);
|
||||
output.push(self.theme.bottom_left);
|
||||
}
|
||||
print!(
|
||||
"{}",
|
||||
std::iter::repeat(self.theme.bottom_horizontal)
|
||||
.take(*column.1)
|
||||
.collect::<String>()
|
||||
);
|
||||
for _ in 0..*column.1 {
|
||||
output.push(self.theme.bottom_horizontal);
|
||||
}
|
||||
output.push(self.theme.bottom_horizontal);
|
||||
output.push(self.theme.bottom_horizontal);
|
||||
|
||||
print!(
|
||||
"{}{}",
|
||||
self.theme.bottom_horizontal, self.theme.bottom_horizontal
|
||||
);
|
||||
if column.0 == column_count - 1 {
|
||||
if self.theme.print_right_border {
|
||||
print!("{}", self.theme.bottom_right);
|
||||
output.push(self.theme.bottom_right);
|
||||
}
|
||||
} else {
|
||||
print!("{}", self.theme.bottom_center);
|
||||
output.push(self.theme.bottom_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("{}", output);
|
||||
}
|
||||
|
||||
fn print_cell_contents(&self, cells: &[WrappedCell]) {
|
||||
|
@ -399,10 +402,13 @@ impl WrappedTable {
|
|||
return;
|
||||
}
|
||||
|
||||
self.print_separator(SeparatorPosition::Top);
|
||||
println!();
|
||||
if self.theme.print_top_border {
|
||||
self.print_separator(SeparatorPosition::Top);
|
||||
}
|
||||
|
||||
self.print_cell_contents(&self.headers);
|
||||
if !self.headers.is_empty() {
|
||||
self.print_cell_contents(&self.headers);
|
||||
}
|
||||
|
||||
let mut first_row = true;
|
||||
|
||||
|
@ -410,21 +416,21 @@ impl WrappedTable {
|
|||
if !first_row {
|
||||
if self.theme.separate_rows {
|
||||
self.print_separator(SeparatorPosition::Middle);
|
||||
println!();
|
||||
}
|
||||
} else {
|
||||
first_row = false;
|
||||
|
||||
if self.theme.separate_header {
|
||||
if self.theme.separate_header && !self.headers.is_empty() {
|
||||
self.print_separator(SeparatorPosition::Middle);
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
self.print_cell_contents(row);
|
||||
}
|
||||
self.print_separator(SeparatorPosition::Bottom);
|
||||
println!();
|
||||
|
||||
if self.theme.print_bottom_border {
|
||||
self.print_separator(SeparatorPosition::Bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -499,6 +505,17 @@ pub fn draw_table(table: &Table, termwidth: usize) {
|
|||
// maybe_truncate_columns(&mut headers, &mut entries, termwidth);
|
||||
let headers_len = table.headers.len();
|
||||
|
||||
// fix the length of the table if there are no headers:
|
||||
let headers_len = if headers_len == 0 {
|
||||
if !table.data.is_empty() && !table.data[0].is_empty() {
|
||||
table.data[0].len()
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
headers_len
|
||||
};
|
||||
|
||||
// Measure how big our columns need to be (accounting for separators also)
|
||||
let max_naive_column_width = (termwidth - 3 * (headers_len - 1)) / headers_len;
|
||||
|
||||
|
@ -518,18 +535,23 @@ pub fn draw_table(table: &Table, termwidth: usize) {
|
|||
// This should give us the final max column width
|
||||
let max_column_width = column_space.max_width(termwidth);
|
||||
|
||||
let wrapped_table = wrap_cells(
|
||||
processed_table,
|
||||
// max_per_column,
|
||||
// max_naive_column_width,
|
||||
max_column_width,
|
||||
);
|
||||
let wrapped_table = wrap_cells(processed_table, max_column_width);
|
||||
|
||||
wrapped_table.new_print_table();
|
||||
}
|
||||
|
||||
fn wrap_cells(processed_table: ProcessedTable, max_column_width: usize) -> WrappedTable {
|
||||
let mut column_widths = vec![0; processed_table.headers.len()];
|
||||
let mut column_widths = vec![
|
||||
0;
|
||||
std::cmp::max(
|
||||
processed_table.headers.len(),
|
||||
if !processed_table.data.is_empty() {
|
||||
processed_table.data[0].len()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
)
|
||||
];
|
||||
let mut output_headers = vec![];
|
||||
for header in processed_table.headers.into_iter().enumerate() {
|
||||
let wrapped = wrap(
|
||||
|
|
|
@ -134,11 +134,7 @@ pub fn view_text_value(value: &Value) {
|
|||
_ => (),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("Couldn't find bat section in config");
|
||||
}
|
||||
} else {
|
||||
println!("Error reading config!");
|
||||
}
|
||||
|
||||
let value_anchor = value.anchor();
|
||||
|
|
Loading…
Reference in a new issue