Finish move to nu-table (#2025)

This commit is contained in:
Jonathan Turner 2020-06-20 12:25:07 -07:00 committed by GitHub
parent 4e83363dd3
commit 89c737f456
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 111 additions and 161 deletions

23
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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 {

View File

@ -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,

View File

@ -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(

View File

@ -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();