When an ignored suffix is also a registered extension (e.g. `.txt` maps to
"Plain Text"), `get_syntax_for_file_extension` matched the raw extension
before attempting the suffix strip. As a result `--ignored-suffix .txt` had
no effect on such files and first-line/shebang detection was never reached,
so a shell script saved as `*.txt` stayed unhighlighted.
Strip ignored suffixes first and detect on the remainder; only fall back to
the raw extension when no ignored suffix applies. When a suffix is stripped
but the remainder has no syntax, return `None` so the caller can use
first-line detection. Default behavior (no `--ignored-suffix`) is unchanged.
See #2745.
`get_languages` computed `desired_width = term_width - longest - separator.len()`.
When `--terminal-width` is smaller than the longest language name (e.g. 1), this
underflows `usize`: in overflow-checked builds it panics ("attempt to subtract with
overflow"), and in release it wraps to ~usize::MAX, silently disabling the extension
line-wrapping so `--terminal-width` is ignored for `--list-languages`.
Use `saturating_sub`, mirroring the fix applied to `print_snip` in #3804 (the snip
separator had the same `term_width - ...` underflow pattern). Output at normal widths
is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`InteractivePrinter::print_snip` computes the snip separator width as
`term_width - panel_count - snip_left_count - title_count`. At `--terminal-width 1`
the panel is disabled and `title_count == 2`, so the subtraction underflows
`usize` (release has no overflow-checks, so it wraps to ~usize::MAX); `str::repeat`
then aborts with "capacity overflow" whenever a snip separator is emitted (two or
more disjoint line ranges, or a diff gap) — which the default style does.
Use `saturating_sub` for the repeat counts so they clamp to 0 instead of
underflowing. Added an integration test.
The Drop cleanup for Preprocessed inverted the exit-status check, so bat
emitted a warning when LESSCLOSE exited successfully and stayed silent on
failure. Align the condition with the intended behavior.
When bat is built without the `git` feature, `StyleComponent::Changes`
is not available. Add `#[cfg(feature = "git")]` guard so `--diff --plain`
works in both configurations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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
When --plain is set (via CLI or config file), --diff output loses all
visual markers, making it indistinguishable from plain text. The diff
line filtering still works, but without Changes markers or Snip
separators the output is not useful.
Automatically include Changes and Snip style components when --diff is
active alongside --plain. This preserves the --plain intent (no grid,
no header, no line numbers) while keeping diff output readable.
Closes#3630
This would catch any dotfiles that end in "ignore", but not `.ignore`
Set as a lower priority rule (90 vs the usual 50) because it's a blanket
assignation. If there are conflict with other, more specific rules,
those will take precedence.