diff --git a/CHANGELOG.md b/CHANGELOG.md index c7ebdc55..e0bea331 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ - Fix arithmetic overflow in `LineRange::from` and `LineRange::parse_range`, see #2674, #2698 (@skoriop) - Fix paging not happening when stdout is interactive but stdin is not, see #2574 (@Nigecat) - Make `-pp` override `--paging` and vice versa when passed as a later argument, see #2660 (@J-Kappes) +- Fix search features not ignore file name, file size and line numbers when using `less` #2675 (@tdtrung17693) ## Other diff --git a/src/controller.rs b/src/controller.rs index ffc5dd5b..d2648bd4 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -49,6 +49,11 @@ impl<'b> Controller<'b> { output_buffer: Option<&mut dyn std::fmt::Write>, mut handle_error: impl FnMut(&Error, &mut dyn Write), ) -> Result { + let panel_width = if self.config.loop_through { + 0 + } else { + InteractivePrinter::get_panel_width(self.config, self.assets) + }; let mut output_type; #[cfg(feature = "paging")] @@ -73,7 +78,8 @@ impl<'b> Controller<'b> { let wrapping_mode = self.config.wrapping_mode; - output_type = OutputType::from_mode(paging_mode, wrapping_mode, self.config.pager)?; + output_type = + OutputType::from_mode(paging_mode, wrapping_mode, self.config, panel_width)?; } #[cfg(not(feature = "paging"))] @@ -92,6 +98,7 @@ impl<'b> Controller<'b> { Some(buf) => OutputHandle::FmtWrite(buf), None => OutputHandle::IoWrite(output_type.handle()?), }; + let mut no_errors: bool = true; let stderr = io::stderr(); @@ -144,6 +151,7 @@ impl<'b> Controller<'b> { #[cfg(not(feature = "lessopen"))] input.open(stdin, stdout_identifier)? }; + #[cfg(feature = "git")] let line_changes = if self.config.visible_lines.diff_mode() || (!self.config.loop_through && self.config.style_components.changes()) diff --git a/src/output.rs b/src/output.rs index dc75d6e7..b387b4b2 100644 --- a/src/output.rs +++ b/src/output.rs @@ -10,6 +10,7 @@ use crate::paging::PagingMode; #[cfg(feature = "paging")] use crate::wrapping::WrappingMode; +use crate::config::Config; #[cfg(feature = "paging")] #[derive(Debug, PartialEq)] enum SingleScreenAction { @@ -29,13 +30,19 @@ impl OutputType { pub fn from_mode( paging_mode: PagingMode, wrapping_mode: WrappingMode, - pager: Option<&str>, + config: &Config, + panel_width: usize, ) -> Result { use self::PagingMode::*; Ok(match paging_mode { - Always => OutputType::try_pager(SingleScreenAction::Nothing, wrapping_mode, pager)?, + Always => OutputType::try_pager( + SingleScreenAction::Nothing, + wrapping_mode, + config, + panel_width, + )?, QuitIfOneScreen => { - OutputType::try_pager(SingleScreenAction::Quit, wrapping_mode, pager)? + OutputType::try_pager(SingleScreenAction::Quit, wrapping_mode, config, panel_width)? } _ => OutputType::stdout(), }) @@ -46,11 +53,13 @@ impl OutputType { fn try_pager( single_screen_action: SingleScreenAction, wrapping_mode: WrappingMode, - pager_from_config: Option<&str>, + config: &Config, + panel_width: usize, ) -> Result { use crate::pager::{self, PagerKind, PagerSource}; use std::process::{Command, Stdio}; + let pager_from_config = config.pager; let pager_opt = pager::get_pager(pager_from_config).map_err(|_| "Could not parse pager command.")?; @@ -81,6 +90,11 @@ impl OutputType { // We only do this for PAGER (as it is not specific to 'bat'), not for BAT_PAGER // or bats '--pager' command line option. let replace_arguments_to_less = pager.source == PagerSource::EnvVarPager; + let less_version = match retrieve_less_version(&pager.bin) { + None => 1, + Some(LessVersion::Less(version)) => version, + _ => 0, + }; if args.is_empty() || replace_arguments_to_less { p.arg("-R"); // Short version of --RAW-CONTROL-CHARS for maximum compatibility @@ -99,22 +113,57 @@ impl OutputType { // // For newer versions (530 or 558 on Windows), we omit '--no-init' as it // is not needed anymore. - match retrieve_less_version(&pager.bin) { - None => { - p.arg("--no-init"); - } - Some(LessVersion::Less(version)) - if (version < 530 || (cfg!(windows) && version < 558)) => - { - p.arg("--no-init"); - } - _ => {} + if less_version == 1 + || (less_version > 1 + && (less_version < 530 || (cfg!(windows) && less_version < 558))) + { + p.arg("--no-init"); } } else { p.args(args); } + p.env("LESSCHARSET", "UTF-8"); + if less_version >= 600 { + let mut row_header = 0; + let mut col_header = 0; + let have_grid = config.style_components.grid(); + let have_numbers = config.style_components.numbers(); + let have_header_filename = config.style_components.header_filename(); + let have_header_filesize = config.style_components.header_filesize(); + + if have_grid { + // for top line + row_header += 1; + } + + if have_header_filename && have_header_filesize { + // 2 headers + row_header += 2; + if have_grid { + // for bottom line + row_header += 1; + } + } else if have_header_filesize || have_header_filename { + row_header += 1; + if have_grid { + // for bottom line + row_header += 1; + } + } + + if have_numbers && panel_width > 0 { + col_header += panel_width; + } + + if row_header > 0 || col_header > 0 { + let header_args = format!("{row_header},{col_header}"); + p.args(vec!["--header", &header_args]); + p.arg("--no-search-headers"); + } + } + #[cfg(feature = "lessopen")] // Ensures that 'less' does not preprocess input again if '$LESSOPEN' is set. p.arg("--no-lessopen"); diff --git a/src/printer.rs b/src/printer.rs index 282f0fe1..0b7dbca2 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -227,19 +227,7 @@ impl<'a> InteractivePrinter<'a> { }; // Create decorations. - let mut decorations: Vec> = Vec::new(); - - if config.style_components.numbers() { - decorations.push(Box::new(LineNumberDecoration::new(&colors))); - } - - #[cfg(feature = "git")] - { - if config.style_components.changes() { - decorations.push(Box::new(LineChangesDecoration::new(&colors))); - } - } - + let mut decorations: Vec> = Self::get_decorations(config, assets); let mut panel_width: usize = decorations.len() + decorations.iter().fold(0, |a, x| a + x.width()); @@ -296,6 +284,40 @@ impl<'a> InteractivePrinter<'a> { }) } + fn get_decorations( + config: &'a Config, + assets: &'a HighlightingAssets, + ) -> Vec> { + let theme = assets.get_theme(&config.theme); + let colors = if config.colored_output { + Colors::colored(theme, config.true_color) + } else { + Colors::plain() + }; + + // Create decorations. + let mut decorations: Vec> = Vec::new(); + + if config.style_components.numbers() { + decorations.push(Box::new(LineNumberDecoration::new(&colors))); + } + + #[cfg(feature = "git")] + { + if config.style_components.changes() { + decorations.push(Box::new(LineChangesDecoration::new(&colors))); + } + } + + return decorations; + } + + pub(crate) fn get_panel_width(config: &'a Config, assets: &'a HighlightingAssets) -> usize { + let decorations = Self::get_decorations(config, assets); + + return decorations.len() + decorations.iter().fold(0, |a, x| a + x.width()); + } + fn print_horizontal_line_term( &mut self, handle: &mut OutputHandle,