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 <fdncred@hotmail.com>
This commit is contained in:
Darren Schroeder 2020-05-21 11:30:58 -05:00 committed by GitHub
parent 97b9c078b1
commit 5de30d0ae5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 2 deletions

1
Cargo.lock generated
View file

@ -2342,6 +2342,7 @@ dependencies = [
"derive-new", "derive-new",
"getset", "getset",
"indexmap", "indexmap",
"itertools",
"log", "log",
"natural", "natural",
"nu-build", "nu-build",

View file

@ -84,6 +84,10 @@ pub fn autoview(context: RunnableContext) -> Result<OutputStream, ShellError> {
Some(val) => val.is_true(), Some(val) => val.is_true(),
_ => false, _ => 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! { Ok(OutputStream::new(async_stream! {
let (mut input_stream, context) = RunnableContextWithoutInput::convert(context); let (mut input_stream, context) = RunnableContextWithoutInput::convert(context);
@ -221,7 +225,14 @@ pub fn autoview(context: RunnableContext) -> Result<OutputStream, ShellError> {
yield Err(e); 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::<Vec<_>>().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::format::{FormatBuilder, LinePosition, LineSeparator};
use prettytable::{color, Attr, Cell, Row, Table}; use prettytable::{color, Attr, Cell, Row, Table};
use crate::data::value::{format_leaf, style_leaf}; use crate::data::value::{format_leaf, style_leaf};

View file

@ -29,6 +29,7 @@ query_interface = "0.3.5"
byte-unit = "3.0.3" byte-unit = "3.0.3"
natural = "0.5.0" natural = "0.5.0"
log = "0.4.8" log = "0.4.8"
itertools = "0.9.0"
# implement conversions # implement conversions
serde_yaml = "0.8" serde_yaml = "0.8"

View file

@ -15,10 +15,11 @@ use crate::value::dict::Dictionary;
use crate::value::iter::{RowValueIter, TableValueIter}; use crate::value::iter::{RowValueIter, TableValueIter};
use crate::value::primitive::Primitive; use crate::value::primitive::Primitive;
use crate::value::range::{Range, RangeInclusion}; use crate::value::range::{Range, RangeInclusion};
use crate::{ColumnPath, PathMember}; use crate::{ColumnPath, PathMember, UnspannedPathMember};
use bigdecimal::BigDecimal; use bigdecimal::BigDecimal;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use indexmap::IndexMap; use indexmap::IndexMap;
use itertools::Itertools;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_source::{AnchorLocation, HasSpan, Span, Spanned, Tag}; use nu_source::{AnchorLocation, HasSpan, Span, Spanned, Tag};
use num_bigint::BigInt; 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<String, ShellError> { pub fn format(&self, fmt: &str) -> Result<String, ShellError> {
match &self.value { match &self.value {
UntaggedValue::Primitive(Primitive::Date(dt)) => Ok(dt.format(fmt).to_string()), UntaggedValue::Primitive(Primitive::Date(dt)) => Ok(dt.format(fmt).to_string()),