Finish up heuristic for table printing

This commit is contained in:
Jonathan Turner 2019-08-14 04:33:59 +12:00
parent 123b1856c8
commit 156e72f694
3 changed files with 46 additions and 32 deletions

View File

@ -7,7 +7,9 @@ use futures_async_stream::async_stream_block;
pub struct Table; pub struct Table;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct TableArgs {} pub struct TableArgs {
full: bool,
}
impl StaticCommand for Table { impl StaticCommand for Table {
fn name(&self) -> &str { fn name(&self) -> &str {
@ -21,16 +23,19 @@ impl StaticCommand for Table {
args.process(registry, table)?.run() args.process(registry, table)?.run()
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("table") Signature::build("table").switch("full")
} }
} }
pub fn table(_args: TableArgs, context: RunnableContext) -> Result<OutputStream, ShellError> { pub fn table(
TableArgs { full }: TableArgs,
context: RunnableContext,
) -> Result<OutputStream, ShellError> {
let stream = async_stream_block! { let stream = async_stream_block! {
let input: Vec<Tagged<Value>> = context.input.into_vec().await; let input: Vec<Tagged<Value>> = context.input.into_vec().await;
if input.len() > 0 { if input.len() > 0 {
let mut host = context.host.lock().unwrap(); 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 { if let Some(view) = view {
handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host)); handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
} }

View File

@ -14,7 +14,7 @@ impl RenderView for GenericView<'value> {
match self.value { match self.value {
Value::Primitive(p) => Ok(host.stdout(&p.format(None))), Value::Primitive(p) => Ok(host.stdout(&p.format(None))),
Value::List(l) => { Value::List(l) => {
let view = TableView::from_list(l); let view = TableView::from_list(l, false);
if let Some(view) = view { if let Some(view) = view {
view.render_view(host)?; view.render_view(host)?;

View File

@ -26,7 +26,7 @@ impl TableView {
ret ret
} }
pub fn from_list(values: &[Tagged<Value>]) -> Option<TableView> { pub fn from_list(values: &[Tagged<Value>], full: bool) -> Option<TableView> {
if values.len() == 0 { if values.len() == 0 {
return None; return None;
} }
@ -66,23 +66,33 @@ impl TableView {
// Trim if the row is too long // Trim if the row is too long
let mut max_up_to_now = 0; let mut max_up_to_now = 0;
let mut has_removed_column = false;
let num_headers = headers.len(); let num_headers = headers.len();
let mut had_to_trim_off_rows = false;
for i in 0..num_headers { for i in 0..num_headers {
let mut max_entry = 0; let mut max_entry = 0;
if i == (num_headers - 1) { if (max_up_to_now + 8) >= max_row && !full {
let amount = max_row - std::cmp::min(max_row, max_up_to_now); had_to_trim_off_rows = true;
if headers[i].len() > amount { headers.pop();
headers[i] = headers[i].chars().take(amount).collect::<String>(); for j in 0..entries.len() {
entries[j].pop();
} }
} else { } else {
if headers[i].len() > (max_row / num_headers) { 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::<String>();
headers[i].push_str("...");
}
} else {
if headers[i].len() > (max_row / num_headers) && !full {
headers[i] = headers[i] headers[i] = headers[i]
.chars() .chars()
.take(std::cmp::max(max_row / headers.len(), 5)) .take(std::cmp::max(max_row / headers.len(), 5))
.collect::<String>(); .collect::<String>();
headers[i].push_str("...");
} }
} }
@ -90,28 +100,20 @@ impl TableView {
max_entry = headers[i].len(); max_entry = headers[i].len();
} }
if has_removed_column {
for j in 0..entries.len() { 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) { if i == (num_headers - 1) {
let amount = max_row - std::cmp::min(max_row, max_up_to_now); 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::<String>(); entries[j][i] = entries[j][i].chars().take(amount).collect::<String>();
entries[j][i].push_str("...");
} }
} else { } 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] entries[j][i] = entries[j][i]
.chars() .chars()
.take(std::cmp::max(max_row / headers.len(), 5)) .take(std::cmp::max(max_row / headers.len(), 5))
.collect::<String>(); .collect::<String>();
entries[j][i].push_str("...");
} }
} }
if entries[j][i].len() > max_entry { 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 }) Some(TableView { headers, entries })
} }
} }