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(
vec![
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()),
],
vec![msg; 2],

View File

@ -224,7 +224,7 @@ pub struct ProcessedTable<'a> {
#[derive(Debug)]
pub struct ProcessedCell<'a> {
pub contents: Vec<Subline<'a>>,
pub contents: Vec<Vec<Subline<'a>>>,
pub style: TextStyle,
}
@ -440,7 +440,7 @@ fn process_table(table: &Table) -> ProcessedTable {
let mut out_row = vec![];
for column in row {
out_row.push(ProcessedCell {
contents: split_sublines(&column.contents).collect::<Vec<_>>(),
contents: split_sublines(&column.contents),
style: column.style.clone(),
});
}
@ -450,7 +450,7 @@ fn process_table(table: &Table) -> ProcessedTable {
let mut processed_headers = vec![];
for header in &table.headers {
processed_headers.push(ProcessedCell {
contents: split_sublines(&header.contents).collect::<Vec<_>>(),
contents: split_sublines(&header.contents),
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];
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 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![];
for header in processed_table.headers.into_iter().enumerate() {
let wrapped = wrap(
max_column_width,
header.1.contents.into_iter(),
header.1.style,
);
let mut wrapped = WrappedCell {
lines: vec![],
max_width: 0,
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 {
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() {
let mut output_row = vec![];
for column in row.into_iter().enumerate() {
let wrapped = wrap(
max_column_width,
column.1.contents.into_iter(),
column.1.style,
);
let mut wrapped = WrappedCell {
lines: vec![],
max_width: 0,
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 {
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> {
input.split_terminator(' ').map(|x| Subline {
subline: x,
width: UnicodeWidthStr::width(x),
})
pub fn split_sublines(input: &str) -> Vec<Vec<Subline>> {
input
.split_terminator('\n')
.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 {
let mut total = 0;
pub fn column_width<'a>(input: &[Vec<Subline<'a>>]) -> usize {
let mut max = 0;
let mut first = true;
for inp in input {
if !first {
// Account for the space
total += 1;
} else {
first = false;
for line in input {
let mut total = 0;
let mut first = true;
for inp in line {
if !first {
// 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>> {
@ -113,8 +128,7 @@ fn split_word<'a>(cell_width: usize, word: &'a str) -> Vec<Subline<'a>> {
pub fn wrap<'a>(
cell_width: usize,
mut input: impl Iterator<Item = Subline<'a>>,
style: TextStyle,
) -> WrappedCell {
) -> (Vec<WrappedLine>, usize) {
let mut lines = vec![];
let mut current_line: Vec<Subline> = vec![];
let mut current_width = 0;
@ -218,9 +232,5 @@ pub fn wrap<'a>(
});
}
WrappedCell {
lines: output,
max_width: current_max,
style,
}
(output, current_max)
}