From 790bed3a2d513f7f225de7677a3b9fce4fba4e29 Mon Sep 17 00:00:00 2001 From: Ian Maloney Date: Fri, 20 Feb 2026 05:52:56 +0000 Subject: [PATCH 1/4] fix: respect --wrap=never flag when paging is enabled When output is piped to a pager, the wrapping_mode logic was not checking the explicit --wrap=never flag and would always default to NoWrapping(false). This meant the -S flag was not passed to less, causing lines to wrap despite the user's explicit request. The fix prioritizes explicit CLI flags (--wrap=never, --chop-long-lines) over the interactive_output-based logic, ensuring they are always respected. Fixes #3587 --- src/bin/bat/app.rs | 26 ++++++++++++--------- tests/integration_tests.rs | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs index 521674f2..fed45ab6 100644 --- a/src/bin/bat/app.rs +++ b/src/bin/bat/app.rs @@ -399,27 +399,31 @@ impl App { Some("no-printing") => BinaryBehavior::NoPrinting, _ => unreachable!("other values for --binary are not allowed"), }, - wrapping_mode: if self.interactive_output || maybe_term_width.is_some() { - if !self.matches.get_flag("chop-long-lines") { + wrapping_mode: { + // Check for explicit flags first (--chop-long-lines or --wrap) + if self.matches.get_flag("chop-long-lines") { + WrappingMode::NoWrapping(true) + } else { match self.matches.get_one::("wrap").map(|s| s.as_str()) { Some("character") => WrappingMode::Character, Some("never") => WrappingMode::NoWrapping(true), Some("auto") | None => { - if style_components.plain() && maybe_term_width.is_none() { - WrappingMode::NoWrapping(false) + // For "auto" or default mode, respect interactive_output setting + if self.interactive_output || maybe_term_width.is_some() { + if style_components.plain() && maybe_term_width.is_none() { + WrappingMode::NoWrapping(false) + } else { + WrappingMode::Character + } } else { - WrappingMode::Character + // We don't have the tty width when piping to another program. + // There's no point in wrapping when this is the case. + WrappingMode::NoWrapping(false) } } _ => unreachable!("other values for --wrap are not allowed"), } - } else { - WrappingMode::NoWrapping(true) } - } else { - // We don't have the tty width when piping to another program. - // There's no point in wrapping when this is the case. - WrappingMode::NoWrapping(false) }, colored_output: self.matches.get_flag("force-colorization") || match self.matches.get_one::("color").map(|s| s.as_str()) { diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index da8b21eb..4235080f 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -2884,6 +2884,52 @@ fn no_wrapping_with_chop_long_lines() { wrapping_test("--chop-long-lines", false); } +// Regression test for issue #3587: --wrap=never should be respected when paging is enabled +// The fix ensures that bat respects the --wrap=never flag even when output is piped to a pager +// by passing the -S flag to less to disable wrapping in the pager +#[test] +#[serial] +fn wrap_never_flag_respected_with_paging_always() { + mocked_pagers::with_mocked_versions_of_more_and_most_in_path(|| { + bat() + // Use cat as pager to pass through the output (avoiding the echo pager issue) + .arg("--pager=cat") + .arg("--paging=always") + .arg("--wrap=never") + .arg("--color=never") + .arg("--decorations=never") + .arg("--style=plain") + .write_stdin("abcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyz\n") + .assert() + .success() + // With --wrap=never and cat pager, the line should NOT wrap + .stdout(predicate::str::contains("abcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyz").normalize()) + .stderr(""); + }); +} + +// Regression test for issue #3587: -S flag should be respected when paging is enabled +#[test] +#[serial] +fn s_flag_respected_with_paging_always() { + mocked_pagers::with_mocked_versions_of_more_and_most_in_path(|| { + bat() + // Use cat as pager to pass through the output + .arg("--pager=cat") + .arg("--paging=always") + .arg("-S") + .arg("--color=never") + .arg("--decorations=never") + .arg("--style=plain") + .write_stdin("abcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyz\n") + .assert() + .success() + // With -S flag and cat pager, the line should NOT wrap + .stdout(predicate::str::contains("abcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyz").normalize()) + .stderr(""); + }); +} + #[test] fn theme_arg_overrides_env() { bat() From 22ee03ff000942ed1b5be14c7f853a3c4fcb40d2 Mon Sep 17 00:00:00 2001 From: Ian Maloney Date: Fri, 20 Feb 2026 05:57:04 +0000 Subject: [PATCH 2/4] add changelog entry for wrap-never bug fix --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8d93805..0e9a6c4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Improve native man pages and command help syntax highlighting by stripping overstriking, see #3517 (@akirk) ## Bugfixes +- Fix `--wrap=never` and `-S` flags being ignored when piping to pager, see #3590 (@IMaloney) - Fix crash with BusyBox `less` on Windows, see #3527 (@Anchal-T) - Fix `bat cache --help` failing with 'unexpected argument' error, see #3580 and #3560 (@NORMAL-EX) - `--help` now correctly honors `--pager=builtin`. See #3516 (@keith-hall) From 16d041492cc2de71cb95d3bbd48b6903eca6ca31 Mon Sep 17 00:00:00 2001 From: Ian Maloney Date: Fri, 20 Feb 2026 06:07:23 +0000 Subject: [PATCH 3/4] fix pr number in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e9a6c4d..8dfae67d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ - Improve native man pages and command help syntax highlighting by stripping overstriking, see #3517 (@akirk) ## Bugfixes -- Fix `--wrap=never` and `-S` flags being ignored when piping to pager, see #3590 (@IMaloney) +- Fix `--wrap=never` and `-S` flags being ignored when piping to pager, see #3592 (@IMaloney) - Fix crash with BusyBox `less` on Windows, see #3527 (@Anchal-T) - Fix `bat cache --help` failing with 'unexpected argument' error, see #3580 and #3560 (@NORMAL-EX) - `--help` now correctly honors `--pager=builtin`. See #3516 (@keith-hall) From 62b0388236ad36a05315d1c6fb78f132d165e0c8 Mon Sep 17 00:00:00 2001 From: Ian Maloney Date: Fri, 20 Feb 2026 06:12:14 +0000 Subject: [PATCH 4/4] remove code comments --- src/bin/bat/app.rs | 2 -- tests/integration_tests.rs | 8 -------- 2 files changed, 10 deletions(-) diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs index fed45ab6..54578087 100644 --- a/src/bin/bat/app.rs +++ b/src/bin/bat/app.rs @@ -400,7 +400,6 @@ impl App { _ => unreachable!("other values for --binary are not allowed"), }, wrapping_mode: { - // Check for explicit flags first (--chop-long-lines or --wrap) if self.matches.get_flag("chop-long-lines") { WrappingMode::NoWrapping(true) } else { @@ -408,7 +407,6 @@ impl App { Some("character") => WrappingMode::Character, Some("never") => WrappingMode::NoWrapping(true), Some("auto") | None => { - // For "auto" or default mode, respect interactive_output setting if self.interactive_output || maybe_term_width.is_some() { if style_components.plain() && maybe_term_width.is_none() { WrappingMode::NoWrapping(false) diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 4235080f..6e99990b 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -2884,15 +2884,11 @@ fn no_wrapping_with_chop_long_lines() { wrapping_test("--chop-long-lines", false); } -// Regression test for issue #3587: --wrap=never should be respected when paging is enabled -// The fix ensures that bat respects the --wrap=never flag even when output is piped to a pager -// by passing the -S flag to less to disable wrapping in the pager #[test] #[serial] fn wrap_never_flag_respected_with_paging_always() { mocked_pagers::with_mocked_versions_of_more_and_most_in_path(|| { bat() - // Use cat as pager to pass through the output (avoiding the echo pager issue) .arg("--pager=cat") .arg("--paging=always") .arg("--wrap=never") @@ -2902,19 +2898,16 @@ fn wrap_never_flag_respected_with_paging_always() { .write_stdin("abcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyz\n") .assert() .success() - // With --wrap=never and cat pager, the line should NOT wrap .stdout(predicate::str::contains("abcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyz").normalize()) .stderr(""); }); } -// Regression test for issue #3587: -S flag should be respected when paging is enabled #[test] #[serial] fn s_flag_respected_with_paging_always() { mocked_pagers::with_mocked_versions_of_more_and_most_in_path(|| { bat() - // Use cat as pager to pass through the output .arg("--pager=cat") .arg("--paging=always") .arg("-S") @@ -2924,7 +2917,6 @@ fn s_flag_respected_with_paging_always() { .write_stdin("abcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyz\n") .assert() .success() - // With -S flag and cat pager, the line should NOT wrap .stdout(predicate::str::contains("abcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyz").normalize()) .stderr(""); });