From 618d7340bb63fa6168615585075c6debb7240a82 Mon Sep 17 00:00:00 2001 From: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Date: Thu, 19 Mar 2026 21:34:12 -0700 Subject: [PATCH 1/4] fix: consistent .deb MUSL package names Fix two inconsistencies in MUSL .deb package naming: 1. Change dpkg_arch for aarch64-unknown-linux-musl from `arm64` to `musl-linux-arm64` to match the convention used by other MUSL targets. 2. Change the DPKG_BASENAME case pattern from `*-musl)` to `*-musl*)` so it also matches `musleabihf`, giving the arm target the `bat-musl` prefix like all other MUSL packages. After this fix, all MUSL .deb packages follow the consistent pattern: `bat-musl_VERSION_musl-linux-ARCH.deb` Closes #3482 --- .github/workflows/CICD.yml | 4 ++-- CHANGELOG.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index f1bc3887..e1b82424 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -161,7 +161,7 @@ jobs: fail-fast: false matrix: job: - - { target: aarch64-unknown-linux-musl , os: ubuntu-latest , dpkg_arch: arm64, use-cross: true } + - { target: aarch64-unknown-linux-musl , os: ubuntu-latest , dpkg_arch: musl-linux-arm64, use-cross: true } - { target: aarch64-unknown-linux-gnu , os: ubuntu-latest , dpkg_arch: arm64, use-cross: true } - { target: arm-unknown-linux-gnueabihf , os: ubuntu-latest , dpkg_arch: armhf, use-cross: true } - { target: arm-unknown-linux-musleabihf, os: ubuntu-latest , dpkg_arch: musl-linux-armhf, use-cross: true } @@ -335,7 +335,7 @@ jobs: DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }} DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }}-musl - case ${{ matrix.job.target }} in *-musl) DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-musl ; DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }} ;; esac; + case ${{ matrix.job.target }} in *-musl*) DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-musl ; DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }} ;; esac; DPKG_VERSION=${{ needs.crate_metadata.outputs.version }} DPKG_ARCH="${{ matrix.job.dpkg_arch }}" DPKG_NAME="${DPKG_BASENAME}_${DPKG_VERSION}_${DPKG_ARCH}.deb" diff --git a/CHANGELOG.md b/CHANGELOG.md index 7de41716..ea1475bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Add `--fallback-syntax`/`--fallback-language` to apply syntax highlighting only when auto-detection fails, see #1341 (@Xavrir) ## Bugfixes +- Fix inconsistent `.deb` MUSL package names (aarch64-musl used `arm64` instead of `musl-linux-arm64`, and `musleabihf` target missed `bat-musl` prefix), see #3482 (@mvanhorn) - Fix `BAT_CONFIG_DIR` pointing at system config directory causing duplicate flag errors. Closes #3589, see #3620 (@Xavrir) - Fix syntax highlighting for symlinked files when the symlink name has no extension but the target does. Closes #1001, see #3621 (@Xavrir) - Report error when pager is missing instead of silently falling back, see #3588 (@IMaloney) From 99c8e15c27c7fc03c9b50aa494f7d0db14885040 Mon Sep 17 00:00:00 2001 From: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Date: Thu, 19 Mar 2026 21:37:45 -0700 Subject: [PATCH 2/4] fix: update changelog entry with PR number for CI check --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea1475bb..c3c893b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ - Add `--fallback-syntax`/`--fallback-language` to apply syntax highlighting only when auto-detection fails, see #1341 (@Xavrir) ## Bugfixes -- Fix inconsistent `.deb` MUSL package names (aarch64-musl used `arm64` instead of `musl-linux-arm64`, and `musleabihf` target missed `bat-musl` prefix), see #3482 (@mvanhorn) +- Fix inconsistent `.deb` MUSL package names (aarch64-musl used `arm64` instead of `musl-linux-arm64`, and `musleabihf` target missed `bat-musl` prefix). Closes #3482, see #3642 (@mvanhorn) - Fix `BAT_CONFIG_DIR` pointing at system config directory causing duplicate flag errors. Closes #3589, see #3620 (@Xavrir) - Fix syntax highlighting for symlinked files when the symlink name has no extension but the target does. Closes #1001, see #3621 (@Xavrir) - Report error when pager is missing instead of silently falling back, see #3588 (@IMaloney) From fc94a0ec49dcea3d5c022d38299f82b1f894f844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ey=C3=BCp=20Can=20Akman?= Date: Thu, 19 Mar 2026 13:26:14 +0300 Subject: [PATCH 3/4] fix: account for caret notation width in text wrapping Control characters displayed in caret notation (e.g. ^@ for NUL) occupy 2 terminal columns, but the width calculation treated them as 0-width. Add a char_width() helper that returns 2 for control characters, fixing incorrect line wrapping with --binary=as-text. Fixes #3631 --- CHANGELOG.md | 1 + src/printer.rs | 18 ++++++++++++----- .../examples/regression_tests/issue_3631.txt | Bin 0 -> 24 bytes tests/integration_tests.rs | 19 ++++++++++++++++++ 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 tests/examples/regression_tests/issue_3631.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 7de41716..34bd719e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Add `--fallback-syntax`/`--fallback-language` to apply syntax highlighting only when auto-detection fails, see #1341 (@Xavrir) ## Bugfixes +- Fix incorrect text width computation when using `--binary=as-text` with non-printable characters in caret notation, see #3631 (@eyupcanakman) - Fix `BAT_CONFIG_DIR` pointing at system config directory causing duplicate flag errors. Closes #3589, see #3620 (@Xavrir) - Fix syntax highlighting for symlinked files when the symlink name has no extension but the target does. Closes #1001, see #3621 (@Xavrir) - Report error when pager is missing instead of silently falling back, see #3588 (@IMaloney) diff --git a/src/printer.rs b/src/printer.rs index 6a57fb62..c58c914d 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -37,6 +37,16 @@ use crate::wrapping::WrappingMode; use crate::BinaryBehavior; use crate::StripAnsiMode; +// Return the displayed width of a character. +// +// Control characters (0x00..=0x1F and 0x7F) are rendered by the terminal +// in caret notation (e.g. ^@, ^A, ..., ^?), which occupies two columns. +// UnicodeWidthChar::width() returns None for these, so we map them to 2 +// here instead of the previous default of 0. +fn char_width(c: char) -> usize { + c.width().unwrap_or(if c.is_control() { 2 } else { 0 }) +} + const ANSI_UNDERLINE_ENABLE: EscapeSequence = EscapeSequence::CSI { raw_sequence: "\x1B[4m", parameters: "4", @@ -793,7 +803,7 @@ impl Printer for InteractivePrinter<'_> { for c in text.chars() { // calculate the displayed width for next character - let cw = c.width().unwrap_or(0); + let cw = char_width(c); current_width += cw; // Track whitespace positions for word wrapping. @@ -868,10 +878,8 @@ impl Printer for InteractivePrinter<'_> { if let Some(rs) = rest_start { // Word wrap: carry remainder to next line. let remainder = line_buf[rs..].to_string(); - let rem_width: usize = remainder - .chars() - .map(|ch| ch.width().unwrap_or(0)) - .sum(); + let rem_width: usize = + remainder.chars().map(char_width).sum(); line_buf.clear(); line_buf.push_str(&remainder); current_width = rem_width + cw; diff --git a/tests/examples/regression_tests/issue_3631.txt b/tests/examples/regression_tests/issue_3631.txt new file mode 100644 index 0000000000000000000000000000000000000000..8449691fdeab44ee83cf8b8059c2aff05c2e76b5 GIT binary patch literal 24 OcmZQzzyz*-E?fWtr~u*s literal 0 HcmV?d00001 diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index cfbad253..c6ea83e9 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -2681,6 +2681,25 @@ fn binary_as_text() { .stderr(""); } +#[test] +fn binary_as_text_control_char_width() { + // Control characters are displayed as caret notation (e.g. ^@) by the + // terminal, occupying 2 columns each. With 20 NUL bytes (40 columns) + + // "END" (3 columns) = 43 columns, wrapping at terminal width 40 must + // produce 2 lines, not 1. See #3631. + bat() + .arg("--binary=as-text") + .arg("--wrap=character") + .arg("--terminal-width=40") + .arg("--decorations=always") + .arg("--style=plain") + .arg("--color=never") + .arg("regression_tests/issue_3631.txt") + .assert() + .success() + .stdout(predicate::function(|s: &str| s.lines().count() == 2)); +} + #[test] fn no_strip_overstrike_for_plain_text() { // Overstrike is preserved for plain text files (no syntax highlighting) From 1f540752ef21f64aafa46007bb2bf7f328ad5230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ey=C3=BCp=20Can=20Akman?= Date: Thu, 19 Mar 2026 19:24:26 +0300 Subject: [PATCH 4/4] fix: reference PR number in CHANGELOG entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34bd719e..180f9ad0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ - Add `--fallback-syntax`/`--fallback-language` to apply syntax highlighting only when auto-detection fails, see #1341 (@Xavrir) ## Bugfixes -- Fix incorrect text width computation when using `--binary=as-text` with non-printable characters in caret notation, see #3631 (@eyupcanakman) +- Fix incorrect text width computation when using `--binary=as-text` with non-printable characters in caret notation, see #3640 and #3631 (@eyupcanakman) - Fix `BAT_CONFIG_DIR` pointing at system config directory causing duplicate flag errors. Closes #3589, see #3620 (@Xavrir) - Fix syntax highlighting for symlinked files when the symlink name has no extension but the target does. Closes #1001, see #3621 (@Xavrir) - Report error when pager is missing instead of silently falling back, see #3588 (@IMaloney)