Fix wrap of carriage returns in cells (#2027)

* Fix carriage returns in cells

* Fix carriage returns in cells
This commit is contained in:
Jonathan Turner 2020-06-20 14:33:58 -07:00 committed by GitHub
parent 89c737f456
commit 480600c465
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 39 deletions

View File

@ -12,7 +12,11 @@ fn main() {
let t = Table::new( let t = Table::new(
vec![ vec![
StyledString::new("Test me".to_owned(), TextStyle::default_header()), StyledString::new("Test me".to_owned(), TextStyle::default_header()),
StyledString::new("Long column name".to_owned(), TextStyle::default_header()), StyledString::new(
"Long column \n name with carriage returns and a lot of text\n check it out"
.to_owned(),
TextStyle::default_header(),
),
StyledString::new("Another".to_owned(), TextStyle::default_header()), StyledString::new("Another".to_owned(), TextStyle::default_header()),
], ],
vec![msg; 2], vec![msg; 2],

View File

@ -224,7 +224,7 @@ pub struct ProcessedTable<'a> {
#[derive(Debug)] #[derive(Debug)]
pub struct ProcessedCell<'a> { pub struct ProcessedCell<'a> {
pub contents: Vec<Subline<'a>>, pub contents: Vec<Vec<Subline<'a>>>,
pub style: TextStyle, pub style: TextStyle,
} }
@ -440,7 +440,7 @@ fn process_table(table: &Table) -> ProcessedTable {
let mut out_row = vec![]; let mut out_row = vec![];
for column in row { for column in row {
out_row.push(ProcessedCell { out_row.push(ProcessedCell {
contents: split_sublines(&column.contents).collect::<Vec<_>>(), contents: split_sublines(&column.contents),
style: column.style.clone(), style: column.style.clone(),
}); });
} }
@ -450,7 +450,7 @@ fn process_table(table: &Table) -> ProcessedTable {
let mut processed_headers = vec![]; let mut processed_headers = vec![];
for header in &table.headers { for header in &table.headers {
processed_headers.push(ProcessedCell { processed_headers.push(ProcessedCell {
contents: split_sublines(&header.contents).collect::<Vec<_>>(), contents: split_sublines(&header.contents),
style: header.style.clone(), style: header.style.clone(),
}); });
} }
@ -476,12 +476,12 @@ fn get_max_column_widths(processed_table: &ProcessedTable) -> Vec<usize> {
let mut output = vec![0; max_num_columns]; let mut output = vec![0; max_num_columns];
for column in processed_table.headers.iter().enumerate() { for column in processed_table.headers.iter().enumerate() {
output[column.0] = max(output[column.0], column_width(column.1.contents.iter())); output[column.0] = max(output[column.0], column_width(&column.1.contents));
} }
for row in &processed_table.data { for row in &processed_table.data {
for column in row.iter().enumerate() { for column in row.iter().enumerate() {
output[column.0] = max(output[column.0], column_width(column.1.contents.iter())); output[column.0] = max(output[column.0], column_width(&column.1.contents));
} }
} }
@ -554,11 +554,19 @@ fn wrap_cells(processed_table: ProcessedTable, max_column_width: usize) -> Wrapp
]; ];
let mut output_headers = vec![]; let mut output_headers = vec![];
for header in processed_table.headers.into_iter().enumerate() { for header in processed_table.headers.into_iter().enumerate() {
let wrapped = wrap( let mut wrapped = WrappedCell {
max_column_width, lines: vec![],
header.1.contents.into_iter(), max_width: 0,
header.1.style, style: header.1.style,
); };
for contents in header.1.contents.into_iter() {
let (mut lines, inner_max_width) = wrap(max_column_width, contents.into_iter());
wrapped.lines.append(&mut lines);
if inner_max_width > wrapped.max_width {
wrapped.max_width = inner_max_width;
}
}
if column_widths[header.0] < wrapped.max_width { if column_widths[header.0] < wrapped.max_width {
column_widths[header.0] = wrapped.max_width; column_widths[header.0] = wrapped.max_width;
} }
@ -569,11 +577,18 @@ fn wrap_cells(processed_table: ProcessedTable, max_column_width: usize) -> Wrapp
for row in processed_table.data.into_iter() { for row in processed_table.data.into_iter() {
let mut output_row = vec![]; let mut output_row = vec![];
for column in row.into_iter().enumerate() { for column in row.into_iter().enumerate() {
let wrapped = wrap( let mut wrapped = WrappedCell {
max_column_width, lines: vec![],
column.1.contents.into_iter(), max_width: 0,
column.1.style, style: column.1.style,
); };
for contents in column.1.contents.into_iter() {
let (mut lines, inner_max_width) = wrap(max_column_width, contents.into_iter());
wrapped.lines.append(&mut lines);
if inner_max_width > wrapped.max_width {
wrapped.max_width = inner_max_width;
}
}
if column_widths[column.0] < wrapped.max_width { if column_widths[column.0] < wrapped.max_width {
column_widths[column.0] = wrapped.max_width; column_widths[column.0] = wrapped.max_width;
} }

View File

@ -50,29 +50,44 @@ impl<'a> Display for Line<'a> {
} }
} }
pub fn split_sublines(input: &str) -> impl Iterator<Item = Subline> { pub fn split_sublines(input: &str) -> Vec<Vec<Subline>> {
input.split_terminator(' ').map(|x| Subline { input
subline: x, .split_terminator('\n')
width: UnicodeWidthStr::width(x), .map(|line| {
}) line.split_terminator(' ')
.map(|x| Subline {
subline: x,
width: UnicodeWidthStr::width(x),
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>()
} }
pub fn column_width<'a>(input: impl Iterator<Item = &'a Subline<'a>>) -> usize { pub fn column_width<'a>(input: &[Vec<Subline<'a>>]) -> usize {
let mut total = 0; let mut max = 0;
let mut first = true; for line in input {
for inp in input { let mut total = 0;
if !first {
// Account for the space let mut first = true;
total += 1; for inp in line {
} else { if !first {
first = false; // Account for the space
total += 1;
} else {
first = false;
}
total += inp.width;
} }
total += inp.width; if total > max {
max = total;
}
} }
total max
} }
fn split_word<'a>(cell_width: usize, word: &'a str) -> Vec<Subline<'a>> { fn split_word<'a>(cell_width: usize, word: &'a str) -> Vec<Subline<'a>> {
@ -113,8 +128,7 @@ fn split_word<'a>(cell_width: usize, word: &'a str) -> Vec<Subline<'a>> {
pub fn wrap<'a>( pub fn wrap<'a>(
cell_width: usize, cell_width: usize,
mut input: impl Iterator<Item = Subline<'a>>, mut input: impl Iterator<Item = Subline<'a>>,
style: TextStyle, ) -> (Vec<WrappedLine>, usize) {
) -> WrappedCell {
let mut lines = vec![]; let mut lines = vec![];
let mut current_line: Vec<Subline> = vec![]; let mut current_line: Vec<Subline> = vec![];
let mut current_width = 0; let mut current_width = 0;
@ -218,9 +232,5 @@ pub fn wrap<'a>(
}); });
} }
WrappedCell { (output, current_max)
lines: output,
max_width: current_max,
style,
}
} }