From 5de30d0ae5eedefc097810dadd548982d3932640 Mon Sep 17 00:00:00 2001 From: Darren Schroeder Date: Thu, 21 May 2020 11:30:58 -0500 Subject: [PATCH] Tweak auto-rotate for single row output (#1861) * added helper to convert data to strings added ability to auto-rotate single row output if row will be greater than terminal width * Added pivot_to_fit config value * Added ColumnPath to convert_to_string helper * Figured out I had to run `cargo fmt --all -- --check` Co-authored-by: Darren Schroeder --- Cargo.lock | 1 + crates/nu-cli/src/commands/autoview.rs | 13 ++++++++++- crates/nu-protocol/Cargo.toml | 1 + crates/nu-protocol/src/value.rs | 32 +++++++++++++++++++++++++- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2126fe9241..618dceb1d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2342,6 +2342,7 @@ dependencies = [ "derive-new", "getset", "indexmap", + "itertools", "log", "natural", "nu-build", diff --git a/crates/nu-cli/src/commands/autoview.rs b/crates/nu-cli/src/commands/autoview.rs index ab4e56425d..fe082187f6 100644 --- a/crates/nu-cli/src/commands/autoview.rs +++ b/crates/nu-cli/src/commands/autoview.rs @@ -84,6 +84,10 @@ pub fn autoview(context: RunnableContext) -> Result { Some(val) => val.is_true(), _ => false, }; + let pivot_to_fit = match config::config(Tag::unknown())?.get("pivot_to_fit") { + Some(val) => val.is_true(), + _ => false, + }; Ok(OutputStream::new(async_stream! { let (mut input_stream, context) = RunnableContextWithoutInput::convert(context); @@ -221,7 +225,14 @@ pub fn autoview(context: RunnableContext) -> Result { yield Err(e); } - Value { value: UntaggedValue::Row(row), ..} if !no_auto_pivot => { + Value { value: UntaggedValue::Row(row), ..} if !no_auto_pivot + || (pivot_to_fit && // Or if the row character count + number of headers * 2 (for padding) > terminal width + (row.entries.iter().map(|(k,v)| v.convert_to_string()) + .collect::>().iter() + .fold(0, |acc, len| acc + len.len()) + + + (row.entries.iter().map(|(k,_)| k.chars()).count() * 2)) + > textwrap::termwidth()) => { use prettytable::format::{FormatBuilder, LinePosition, LineSeparator}; use prettytable::{color, Attr, Cell, Row, Table}; use crate::data::value::{format_leaf, style_leaf}; diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml index d490a081e5..0b413769d3 100644 --- a/crates/nu-protocol/Cargo.toml +++ b/crates/nu-protocol/Cargo.toml @@ -29,6 +29,7 @@ query_interface = "0.3.5" byte-unit = "3.0.3" natural = "0.5.0" log = "0.4.8" +itertools = "0.9.0" # implement conversions serde_yaml = "0.8" diff --git a/crates/nu-protocol/src/value.rs b/crates/nu-protocol/src/value.rs index b55c126dbf..c0403982df 100644 --- a/crates/nu-protocol/src/value.rs +++ b/crates/nu-protocol/src/value.rs @@ -15,10 +15,11 @@ use crate::value::dict::Dictionary; use crate::value::iter::{RowValueIter, TableValueIter}; use crate::value::primitive::Primitive; use crate::value::range::{Range, RangeInclusion}; -use crate::{ColumnPath, PathMember}; +use crate::{ColumnPath, PathMember, UnspannedPathMember}; use bigdecimal::BigDecimal; use chrono::{DateTime, Utc}; use indexmap::IndexMap; +use itertools::Itertools; use nu_errors::ShellError; use nu_source::{AnchorLocation, HasSpan, Span, Spanned, Tag}; use num_bigint::BigInt; @@ -274,6 +275,35 @@ impl Value { } } + pub fn convert_to_string(&self) -> String { + match &self.value { + UntaggedValue::Primitive(Primitive::String(s)) => s.clone(), + UntaggedValue::Primitive(Primitive::Date(dt)) => dt.format("%Y-%b-%d").to_string(), + UntaggedValue::Primitive(Primitive::Boolean(x)) => format!("{}", x), + UntaggedValue::Primitive(Primitive::Decimal(x)) => format!("{}", x), + UntaggedValue::Primitive(Primitive::Int(x)) => format!("{}", x), + UntaggedValue::Primitive(Primitive::Bytes(x)) => format!("{}", x), + UntaggedValue::Primitive(Primitive::Path(x)) => format!("{}", x.display()), + UntaggedValue::Primitive(Primitive::ColumnPath(path)) => { + let joined = path + .iter() + .map(|member| match &member.unspanned { + UnspannedPathMember::String(name) => name.to_string(), + UnspannedPathMember::Int(n) => format!("{}", n), + }) + .join("."); + + if joined.contains(' ') { + format!("\"{}\"", joined) + } else { + joined + } + } + + _ => String::from(""), + } + } + pub fn format(&self, fmt: &str) -> Result { match &self.value { UntaggedValue::Primitive(Primitive::Date(dt)) => Ok(dt.format(fmt).to_string()),