Skip to content

Track strikethrough (SGR 9) so it is not dropped across highlighted tokens - #4015

Merged
keith-hall merged 1 commit into
sharkdp:masterfrom
mikehasa:fix/track-strikethrough-sgr9
Sep 22, 2026
Merged

keith-hall merged 1 commit into
sharkdp:masterfrom
mikehasa:fix/track-strikethrough-sgr9

Conversation

@mikehasa

Copy link
Copy Markdown
Contributor

Summary

src/vscreen.rs tracks the terminal's active ANSI style in an Attributes struct so bat can re-apply it before each syntax-highlighted token (nu_ansi_term appends a full \x1B[0m reset after every token). The struct already has a strike field, documented ON: ^[9m / OFF: ^[29m, that is initialized, cleared in sgr_reset(), and re-emitted in Display — but update_with_sgr() had no match arm for SGR 9 or 29, so strike was only ever cleared, never set.

Consequence: with ANSI passthrough (the default — --strip-ansi and --sanitize both default to never), bold/dim/italic/underline survive across highlighted tokens because they are tracked and re-emitted, but strikethrough visibly disappears after the first token.

This adds the missing 9 (set) and 29 (clear) arms, mirroring the sibling underline (4/24) and italic (3/23) arms, so strikethrough persists like every other supported attribute. Two-line behavioral change; no API change. to_reset_sequence() intentionally does not reset SGR attributes yet (existing commented-out TODO), so strike is handled there exactly like bold/italic — no change needed.

Test Plan

  • cargo test (unit + integration).
  • Extended the test_sgr_attributes_do_not_leak_into_wrong_field unit test to include SGR 9, and added test_sgr_strike_is_tracked_and_cleared covering set (9) and clear (29).
  • Added integration test ansi_sgr_strike_joins_attributes_when_wrapped, modeled on the existing ansi_sgr_joins_attributes_when_wrapped, asserting strikethrough is re-emitted across a wrap boundary. It fails before the fix and passes after.

Developed with assistance from Claude Code; reviewed & validated by me.

🤖 Generated with Claude Code

…okens

The `Attributes` ANSI style tracker in `src/vscreen.rs` declares, initializes,
clears (in `sgr_reset`), and re-emits (in `Display`) a `strike` field
documented as `ON: ^[9m / OFF: ^[29m`, but `update_with_sgr()` had no match
arm for SGR 9 (set strikethrough) or 29 (clear strikethrough). As a result
`strike` was only ever cleared, never set.

Because bat re-applies the tracked input ANSI style before each highlighted
text run (nu_ansi_term appends a full reset after every token), attributes
that are tracked — bold, dim, italic, underline — survive across tokens,
while strikethrough was silently dropped after the first token. This path is
active by default (`--strip-ansi`/`--sanitize` default to `never`).

Add the missing `9` and `29` arms, mirroring the sibling underline (4/24) and
italic (3/23) arms, so strikethrough is tracked and re-emitted like every
other supported attribute.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mikehasa
mikehasa force-pushed the fix/track-strikethrough-sgr9 branch from 5316c1d to 156ef1d Compare September 22, 2026 12:15

@keith-hall keith-hall left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@keith-hall
keith-hall merged commit 4987f76 into sharkdp:master Sep 22, 2026
24 checks passed
@mikehasa

Copy link
Copy Markdown
Contributor Author

Thanks for the review and merge, @keith-hall! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants