From ec7d159c837fee5f436769dc695ca6417173307a Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Sat, 17 Aug 2019 08:03:29 +1200 Subject: [PATCH] Switch to constraint solving the table --- src/format/table.rs | 73 +++++++++++++++++++++++++++++++++++++-------- src/object/base.rs | 9 +++--- 2 files changed, 65 insertions(+), 17 deletions(-) diff --git a/src/format/table.rs b/src/format/table.rs index 6321d7189..ec641bff0 100644 --- a/src/format/table.rs +++ b/src/format/table.rs @@ -72,13 +72,14 @@ impl TableView { current_row_max = entries[row][head].len(); } } - max_per_column.push(current_row_max); + max_per_column.push(std::cmp::max(current_row_max, headers[head].len())); } - let termwidth = textwrap::termwidth() - 9; + // Different platforms want different amounts of buffer, not sure why + let termwidth = std::cmp::max(textwrap::termwidth(), 20); // Make sure we have enough space for the columns we have - let max_num_of_columns = termwidth / 7; + let max_num_of_columns = termwidth / 10; // If we have too many columns, truncate the table if max_num_of_columns < headers.len() { @@ -93,29 +94,77 @@ impl TableView { } } - // Measure how big our columns need to be - let max_naive_column_width = termwidth / headers.len(); + // Measure how big our columns need to be (accounting for separators also) + let max_naive_column_width = (termwidth - 3 * (headers.len() - 1)) / headers.len(); + // Measure how much space we have once we subtract off the columns who are small enough let mut num_overages = 0; let mut underage_sum = 0; + let mut overage_separator_sum = 0; for idx in 0..headers.len() { if max_per_column[idx] > max_naive_column_width { num_overages += 1; + if idx != (headers.len() - 1) { + overage_separator_sum += 3; + } + if idx == 0 { + overage_separator_sum += 1; + } } else { underage_sum += max_per_column[idx]; + // if column isn't last, add 3 for its separator + if idx != (headers.len() - 1) { + underage_sum += 3; + } + if idx == 0 { + underage_sum += 1; + } } } + // This gives us the max column width + let max_column_width = if num_overages > 0 { + (termwidth - 1 - underage_sum - overage_separator_sum) / num_overages + } else { + 99999 + }; + + // This width isn't quite right, as we're rounding off some of our space + num_overages = 0; + overage_separator_sum = 0; + for idx in 0..headers.len() { + if max_per_column[idx] > max_naive_column_width { + if max_per_column[idx] <= max_column_width { + underage_sum += max_per_column[idx]; + // if column isn't last, add 3 for its separator + if idx != (headers.len() - 1) { + underage_sum += 3; + } + if idx == 0 { + underage_sum += 1; + } + } else { + // Column is still too large, so let's count it + num_overages += 1; + if idx != (headers.len() - 1) { + overage_separator_sum += 3; + } + if idx == 0 { + overage_separator_sum += 1; + } + } + } + } + // This should give us the final max column width + let max_column_width = if num_overages > 0 { + (termwidth - 1 - underage_sum - overage_separator_sum) / num_overages + } else { + 99999 + }; + // Wrap cells as needed for head in 0..headers.len() { if max_per_column[head] > max_naive_column_width { - let max_column_width = (termwidth - underage_sum) / num_overages; - //Account for the separator - let max_column_width = if max_column_width > 1 { - max_column_width - 2 - } else { - max_column_width - }; headers[head] = fill(&headers[head], max_column_width); for row in 0..entries.len() { entries[row][head] = fill(&entries[row][head], max_column_width); diff --git a/src/object/base.rs b/src/object/base.rs index 5dffe015d..9ad81b451 100644 --- a/src/object/base.rs +++ b/src/object/base.rs @@ -5,7 +5,6 @@ use crate::object::TaggedDictBuilder; use crate::parser::{hir, Operator}; use crate::prelude::*; use crate::Text; -use ansi_term::Color; use chrono::{DateTime, Utc}; use chrono_humanize::Humanize; use derive_new::new; @@ -87,15 +86,15 @@ impl Primitive { pub fn format(&self, field_name: Option<&String>) -> String { match self { - Primitive::Nothing => format!("{}", Color::Black.bold().paint("-")), - Primitive::BeginningOfStream => format!("{}", Color::Black.bold().paint("-")), - Primitive::EndOfStream => format!("{}", Color::Black.bold().paint("-")), + Primitive::Nothing => String::new(), + Primitive::BeginningOfStream => String::new(), + Primitive::EndOfStream => String::new(), Primitive::Path(p) => format!("{}", p.display()), Primitive::Bytes(b) => { let byte = byte_unit::Byte::from_bytes(*b as u128); if byte.get_bytes() == 0u128 { - return Color::Black.bold().paint("Empty".to_string()).to_string(); + return "".to_string(); } let byte = byte.get_appropriate_unit(false);