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;
#[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<OutputStream, ShellError> {
pub fn table(
TableArgs { full }: TableArgs,
context: RunnableContext,
) -> Result<OutputStream, ShellError> {
let stream = async_stream_block! {
let input: Vec<Tagged<Value>> = 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));
}

View File

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

View File

@ -26,7 +26,7 @@ impl TableView {
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 {
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::<String>();
}
} else {
if headers[i].len() > (max_row / num_headers) {
headers[i] = headers[i]
.chars()
.take(std::cmp::max(max_row / headers.len(), 5))
.collect::<String>();
}
}
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::<String>();
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::<String>();
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::<String>();
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::<String>();
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 })
}
}