diff --git a/crates/nu-table/src/main.rs b/crates/nu-table/src/main.rs index f426a9d02d..19a8ecf6a4 100644 --- a/crates/nu-table/src/main.rs +++ b/crates/nu-table/src/main.rs @@ -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], diff --git a/crates/nu-table/src/table.rs b/crates/nu-table/src/table.rs index 5bd8877bdd..ebd7edb02f 100644 --- a/crates/nu-table/src/table.rs +++ b/crates/nu-table/src/table.rs @@ -224,7 +224,7 @@ pub struct ProcessedTable<'a> { #[derive(Debug)] pub struct ProcessedCell<'a> { - pub contents: Vec>, + pub contents: Vec>>, 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::>(), + 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::>(), + contents: split_sublines(&header.contents), style: header.style.clone(), }); } @@ -476,12 +476,12 @@ fn get_max_column_widths(processed_table: &ProcessedTable) -> Vec { 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; } diff --git a/crates/nu-table/src/wrap.rs b/crates/nu-table/src/wrap.rs index bc86eb9f3c..33baa47c30 100644 --- a/crates/nu-table/src/wrap.rs +++ b/crates/nu-table/src/wrap.rs @@ -50,29 +50,44 @@ impl<'a> Display for Line<'a> { } } -pub fn split_sublines(input: &str) -> impl Iterator { - input.split_terminator(' ').map(|x| Subline { - subline: x, - width: UnicodeWidthStr::width(x), - }) +pub fn split_sublines(input: &str) -> Vec> { + input + .split_terminator('\n') + .map(|line| { + line.split_terminator(' ') + .map(|x| Subline { + subline: x, + width: UnicodeWidthStr::width(x), + }) + .collect::>() + }) + .collect::>() } -pub fn column_width<'a>(input: impl Iterator>) -> usize { - let mut total = 0; +pub fn column_width<'a>(input: &[Vec>]) -> 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> { @@ -113,8 +128,7 @@ fn split_word<'a>(cell_width: usize, word: &'a str) -> Vec> { pub fn wrap<'a>( cell_width: usize, mut input: impl Iterator>, - style: TextStyle, -) -> WrappedCell { +) -> (Vec, usize) { let mut lines = vec![]; let mut current_line: Vec = 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) }