diff --git a/CHANGELOG.md b/CHANGELOG.md index bb027c55..8015b14d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ## Bugfixes +- Fix long file name wrapping in header, see #2835 (@FilipRazek) - Fix `NO_COLOR` support, see #2767 (@acuteenvy) ## Other diff --git a/src/printer.rs b/src/printer.rs index cb80edc4..257cc766 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -287,6 +287,14 @@ impl<'a> InteractivePrinter<'a> { } } + fn get_header_component_indent_length(&self) -> usize { + if self.config.style_components.grid() && self.panel_width > 0 { + self.panel_width + 2 + } else { + self.panel_width + } + } + fn print_header_component_indent(&mut self, handle: &mut OutputHandle) -> Result<()> { if self.config.style_components.grid() { write!( @@ -302,6 +310,30 @@ impl<'a> InteractivePrinter<'a> { } } + fn print_header_component_with_indent( + &mut self, + handle: &mut OutputHandle, + content: &str, + ) -> Result<()> { + self.print_header_component_indent(handle)?; + writeln!(handle, "{}", content) + } + + fn print_header_multiline_component( + &mut self, + handle: &mut OutputHandle, + content: &str, + ) -> Result<()> { + let mut content = content; + let content_width = self.config.term_width - self.get_header_component_indent_length(); + while content.len() > content_width { + let (content_line, remaining) = content.split_at(content_width); + self.print_header_component_with_indent(handle, content_line)?; + content = remaining; + } + self.print_header_component_with_indent(handle, content) + } + fn preprocess(&self, text: &str, cursor: &mut usize) -> String { if self.config.tab_width > 0 { return expand_tabs(text, self.config.tab_width, cursor); @@ -377,31 +409,32 @@ impl<'a> Printer for InteractivePrinter<'a> { } } - header_components.iter().try_for_each(|component| { - self.print_header_component_indent(handle)?; - - match component { - StyleComponent::HeaderFilename => writeln!( - handle, - "{}{}{}", - description - .kind() - .map(|kind| format!("{}: ", kind)) - .unwrap_or_else(|| "".into()), - self.colors.header_value.paint(description.title()), - mode - ), - + header_components + .iter() + .try_for_each(|component| match component { + StyleComponent::HeaderFilename => { + let header_filename = format!( + "{}{}{}", + description + .kind() + .map(|kind| format!("{}: ", kind)) + .unwrap_or_else(|| "".into()), + self.colors.header_value.paint(description.title()), + mode + ); + self.print_header_multiline_component(handle, &header_filename) + } StyleComponent::HeaderFilesize => { let bsize = metadata .size .map(|s| format!("{}", ByteSize(s))) .unwrap_or_else(|| "-".into()); - writeln!(handle, "Size: {}", self.colors.header_value.paint(bsize)) + let header_filesize = + format!("Size: {}", self.colors.header_value.paint(bsize)); + self.print_header_multiline_component(handle, &header_filesize) } _ => Ok(()), - } - })?; + })?; if self.config.style_components.grid() { if self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable { diff --git a/tests/examples/this-file-path-is-really-long-and-would-have-broken-the-layout-of-the-header.txt b/tests/examples/this-file-path-is-really-long-and-would-have-broken-the-layout-of-the-header.txt new file mode 100644 index 00000000..4dac98dc --- /dev/null +++ b/tests/examples/this-file-path-is-really-long-and-would-have-broken-the-layout-of-the-header.txt @@ -0,0 +1 @@ +The header is not broken \ No newline at end of file diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index be70fdca..437ae8e7 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1381,6 +1381,61 @@ fn header_full_binary() { .stderr(""); } +#[test] +#[cfg(not(feature = "git"))] +fn header_narrow_terminal() { + bat() + .arg("--terminal-width=30") + .arg("--decorations=always") + .arg("this-file-path-is-really-long-and-would-have-broken-the-layout-of-the-header.txt") + .assert() + .success() + .stdout( + "\ +─────┬──────────────────────── + │ File: this-file-path-is + │ -really-long-and-would- + │ have-broken-the-layout- + │ of-the-header.txt +─────┼──────────────────────── + 1 │ The header is not broke + │ n +─────┴──────────────────────── +", + ) + .stderr(""); +} + +#[test] +fn header_very_narrow_terminal() { + bat() + .arg("--terminal-width=10") + .arg("--decorations=always") + .arg("this-file-path-is-really-long-and-would-have-broken-the-layout-of-the-header.txt") + .assert() + .success() + .stdout( + "\ +────────── +File: this +-file-path +-is-really +-long-and- +would-have +-broken-th +e-layout-o +f-the-head +er.txt +────────── +The header + is not br +oken +────────── +", + ) + .stderr(""); +} + #[test] #[cfg(feature = "git")] // Expected output assumes git is enabled fn header_default() {