From 123b1856c8dfb64c73c83c18574944b8088fba80 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Tue, 13 Aug 2019 19:45:31 +1200 Subject: [PATCH 1/2] Attempt heuristic table --- Cargo.lock | 41 ++++++++++++++++++++++++++ Cargo.toml | 1 + src/commands/autoview.rs | 8 ------ src/errors.rs | 4 ++- src/format/table.rs | 62 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48c884cde7..1f506d446d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1994,6 +1994,7 @@ dependencies = [ "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "termsize 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml-query 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2064,6 +2065,11 @@ dependencies = [ "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "objc" version = "0.2.6" @@ -2652,6 +2658,14 @@ name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_users" version = "0.3.1" @@ -3173,6 +3187,17 @@ dependencies = [ "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "termion" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termios" version = "0.3.1" @@ -3181,6 +3206,18 @@ dependencies = [ "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "termsize" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -3959,6 +3996,7 @@ dependencies = [ "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" +"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" "checksum objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d" "checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" "checksum objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" @@ -4022,6 +4060,7 @@ dependencies = [ "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum readkey 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d98db94bb4f3e926c8d8186547cd9366d958d753aff5801214d93d38214e8f0f" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" "checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" @@ -4081,7 +4120,9 @@ dependencies = [ "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" +"checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330" "checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" +"checksum termsize 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5e86d824a8e90f342ad3ef4bd51ef7119a9b681b0cc9f8ee7b2852f02ccd2517" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" diff --git a/Cargo.toml b/Cargo.toml index 4d4a2d0ebf..cc6f155e52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,6 +84,7 @@ onig_sys = "=69.1.0" heim = {git = "https://github.com/heim-rs/heim.git"} which = "2.0.1" battery = "0.7.4" +termsize = "0.1" [dev-dependencies] pretty_assertions = "0.6.1" diff --git a/src/commands/autoview.rs b/src/commands/autoview.rs index 85471c4fff..f1842865ba 100644 --- a/src/commands/autoview.rs +++ b/src/commands/autoview.rs @@ -54,14 +54,6 @@ pub fn autoview( let table = context.expect_command("table"); let result = table.run(raw.with_input(input), &context.commands).await.unwrap(); result.collect::>().await; - //println!("TODO!") - // TODO - // let mut host = context.host.lock().unwrap(); - // for i in input.iter() { - // let view = GenericView::new(&i); - // handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host)); - // host.stdout(""); - // } } } })) diff --git a/src/errors.rs b/src/errors.rs index 18aa39bd5e..d5b0e48fc5 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -200,7 +200,9 @@ impl ShellError { } if let Ok(label) = expr { - diag = diag.with_label(label); + diag = diag.with_label( + Label::new_primary(label.span).with_message("unknown property"), + ); } diag diff --git a/src/format/table.rs b/src/format/table.rs index c6af90fdc9..26e1f4eb25 100644 --- a/src/format/table.rs +++ b/src/format/table.rs @@ -31,6 +31,8 @@ impl TableView { return None; } + let max_row: usize = termsize::get().map(|x| x.cols).unwrap() as usize; + let mut headers = TableView::merge_descriptors(values); if headers.len() == 0 { @@ -61,6 +63,66 @@ impl TableView { if values.len() > 1 { headers.insert(0, format!("#")); } + + // Trim if the row is too long + let mut max_up_to_now = 0; + let mut has_removed_column = false; + + let num_headers = headers.len(); + for i in 0..num_headers { + let mut max_entry = 0; + + if i == (num_headers - 1) { + let amount = max_row - std::cmp::min(max_row, max_up_to_now); + if headers[i].len() > amount { + headers[i] = headers[i].chars().take(amount).collect::(); + } + } else { + if headers[i].len() > (max_row / num_headers) { + headers[i] = headers[i] + .chars() + .take(std::cmp::max(max_row / headers.len(), 5)) + .collect::(); + } + } + + if headers[i].len() > max_entry { + max_entry = headers[i].len(); + } + + if has_removed_column { + for j in 0..entries.len() { + entries[j].pop(); + } + } else { + for j in 0..entries.len() { + // If we have too many columns, trim the extra ones + if (max_up_to_now + max_entry + 3) >= max_row { + has_removed_column = true; + } + + if i == (num_headers - 1) { + let amount = max_row - std::cmp::min(max_row, max_up_to_now); + if entries[j][i].len() > amount { + entries[j][i] = entries[j][i].chars().take(amount).collect::(); + } + } else { + if entries[j][i].len() > (max_row / num_headers) { + entries[j][i] = entries[j][i] + .chars() + .take(std::cmp::max(max_row / headers.len(), 5)) + .collect::(); + } + } + if entries[j][i].len() > max_entry { + max_entry = entries[j][i].len(); + } + } + + max_up_to_now += max_entry + 3; + } + } + Some(TableView { headers, entries }) } } From 156e72f6942560f6f45def7f6d79e6fb301ffe92 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Wed, 14 Aug 2019 04:33:59 +1200 Subject: [PATCH 2/2] Finish up heuristic for table printing --- src/commands/table.rs | 13 ++++++--- src/format/generic.rs | 2 +- src/format/table.rs | 63 ++++++++++++++++++++++++------------------- 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/commands/table.rs b/src/commands/table.rs index 9e8a4bfbcf..f4ea5be680 100644 --- a/src/commands/table.rs +++ b/src/commands/table.rs @@ -7,7 +7,9 @@ use futures_async_stream::async_stream_block; pub struct Table; #[derive(Deserialize)] -pub struct TableArgs {} +pub struct TableArgs { + full: bool, +} impl StaticCommand for Table { fn name(&self) -> &str { @@ -21,16 +23,19 @@ impl StaticCommand for Table { args.process(registry, table)?.run() } fn signature(&self) -> Signature { - Signature::build("table") + Signature::build("table").switch("full") } } -pub fn table(_args: TableArgs, context: RunnableContext) -> Result { +pub fn table( + TableArgs { full }: TableArgs, + context: RunnableContext, +) -> Result { let stream = async_stream_block! { let input: Vec> = context.input.into_vec().await; if input.len() > 0 { let mut host = context.host.lock().unwrap(); - let view = TableView::from_list(&input); + let view = TableView::from_list(&input, full); if let Some(view) = view { handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host)); } diff --git a/src/format/generic.rs b/src/format/generic.rs index 42971febc3..21465aafe3 100644 --- a/src/format/generic.rs +++ b/src/format/generic.rs @@ -14,7 +14,7 @@ impl RenderView for GenericView<'value> { match self.value { Value::Primitive(p) => Ok(host.stdout(&p.format(None))), Value::List(l) => { - let view = TableView::from_list(l); + let view = TableView::from_list(l, false); if let Some(view) = view { view.render_view(host)?; diff --git a/src/format/table.rs b/src/format/table.rs index 26e1f4eb25..341ed4ac03 100644 --- a/src/format/table.rs +++ b/src/format/table.rs @@ -26,7 +26,7 @@ impl TableView { ret } - pub fn from_list(values: &[Tagged]) -> Option { + pub fn from_list(values: &[Tagged], full: bool) -> Option { if values.len() == 0 { return None; } @@ -66,52 +66,54 @@ impl TableView { // Trim if the row is too long let mut max_up_to_now = 0; - let mut has_removed_column = false; let num_headers = headers.len(); + let mut had_to_trim_off_rows = false; + for i in 0..num_headers { let mut max_entry = 0; - if i == (num_headers - 1) { - let amount = max_row - std::cmp::min(max_row, max_up_to_now); - if headers[i].len() > amount { - headers[i] = headers[i].chars().take(amount).collect::(); - } - } else { - if headers[i].len() > (max_row / num_headers) { - headers[i] = headers[i] - .chars() - .take(std::cmp::max(max_row / headers.len(), 5)) - .collect::(); - } - } - - if headers[i].len() > max_entry { - max_entry = headers[i].len(); - } - - if has_removed_column { + if (max_up_to_now + 8) >= max_row && !full { + had_to_trim_off_rows = true; + headers.pop(); for j in 0..entries.len() { entries[j].pop(); } } else { - for j in 0..entries.len() { - // If we have too many columns, trim the extra ones - if (max_up_to_now + max_entry + 3) >= max_row { - has_removed_column = true; + if i == (num_headers - 1) { + let amount = max_row - std::cmp::min(max_row, max_up_to_now); + if headers[i].len() > amount && !full { + headers[i] = headers[i].chars().take(amount).collect::(); + headers[i].push_str("..."); } + } else { + if headers[i].len() > (max_row / num_headers) && !full { + headers[i] = headers[i] + .chars() + .take(std::cmp::max(max_row / headers.len(), 5)) + .collect::(); + headers[i].push_str("..."); + } + } + if headers[i].len() > max_entry { + max_entry = headers[i].len(); + } + + for j in 0..entries.len() { if i == (num_headers - 1) { let amount = max_row - std::cmp::min(max_row, max_up_to_now); - if entries[j][i].len() > amount { + if entries[j][i].len() > amount && !full { entries[j][i] = entries[j][i].chars().take(amount).collect::(); + entries[j][i].push_str("..."); } } else { - if entries[j][i].len() > (max_row / num_headers) { + if entries[j][i].len() > (max_row / num_headers) && !full { entries[j][i] = entries[j][i] .chars() .take(std::cmp::max(max_row / headers.len(), 5)) .collect::(); + entries[j][i].push_str("..."); } } if entries[j][i].len() > max_entry { @@ -123,6 +125,13 @@ impl TableView { } } + if had_to_trim_off_rows { + headers.push("...".to_string()); + for j in 0..entries.len() { + entries[j].push("...".to_string()); + } + } + Some(TableView { headers, entries }) } }