Merge pull request #297 from jonathandturner/table_constraint_solve

Switch to constraint solving the table
This commit is contained in:
Jonathan Turner 2019-08-17 08:21:29 +12:00 committed by GitHub
commit 37000c7c31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 17 deletions

View File

@ -72,13 +72,14 @@ impl TableView {
current_row_max = entries[row][head].len(); 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 // 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 we have too many columns, truncate the table
if max_num_of_columns < headers.len() { if max_num_of_columns < headers.len() {
@ -93,29 +94,77 @@ impl TableView {
} }
} }
// Measure how big our columns need to be // Measure how big our columns need to be (accounting for separators also)
let max_naive_column_width = termwidth / headers.len(); 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 num_overages = 0;
let mut underage_sum = 0; let mut underage_sum = 0;
let mut overage_separator_sum = 0;
for idx in 0..headers.len() { for idx in 0..headers.len() {
if max_per_column[idx] > max_naive_column_width { if max_per_column[idx] > max_naive_column_width {
num_overages += 1; num_overages += 1;
if idx != (headers.len() - 1) {
overage_separator_sum += 3;
}
if idx == 0 {
overage_separator_sum += 1;
}
} else { } else {
underage_sum += max_per_column[idx]; 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 // Wrap cells as needed
for head in 0..headers.len() { for head in 0..headers.len() {
if max_per_column[head] > max_naive_column_width { 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); headers[head] = fill(&headers[head], max_column_width);
for row in 0..entries.len() { for row in 0..entries.len() {
entries[row][head] = fill(&entries[row][head], max_column_width); entries[row][head] = fill(&entries[row][head], max_column_width);

View File

@ -5,7 +5,6 @@ use crate::object::TaggedDictBuilder;
use crate::parser::{hir, Operator}; use crate::parser::{hir, Operator};
use crate::prelude::*; use crate::prelude::*;
use crate::Text; use crate::Text;
use ansi_term::Color;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use chrono_humanize::Humanize; use chrono_humanize::Humanize;
use derive_new::new; use derive_new::new;
@ -87,15 +86,15 @@ impl Primitive {
pub fn format(&self, field_name: Option<&String>) -> String { pub fn format(&self, field_name: Option<&String>) -> String {
match self { match self {
Primitive::Nothing => format!("{}", Color::Black.bold().paint("-")), Primitive::Nothing => String::new(),
Primitive::BeginningOfStream => format!("{}", Color::Black.bold().paint("-")), Primitive::BeginningOfStream => String::new(),
Primitive::EndOfStream => format!("{}", Color::Black.bold().paint("-")), Primitive::EndOfStream => String::new(),
Primitive::Path(p) => format!("{}", p.display()), Primitive::Path(p) => format!("{}", p.display()),
Primitive::Bytes(b) => { Primitive::Bytes(b) => {
let byte = byte_unit::Byte::from_bytes(*b as u128); let byte = byte_unit::Byte::from_bytes(*b as u128);
if byte.get_bytes() == 0u128 { if byte.get_bytes() == 0u128 {
return Color::Black.bold().paint("Empty".to_string()).to_string(); return "<empty>".to_string();
} }
let byte = byte.get_appropriate_unit(false); let byte = byte.get_appropriate_unit(false);