Skip to content

Commit 4f7c71a

Browse files
committed
Only strip overstrike when a syntax highlighting theme is used
1 parent 084fc34 commit 4f7c71a

File tree

5 files changed

+83
-14
lines changed

5 files changed

+83
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
## Bugfixes
66

7-
- Strip overstriking to better support man pages, see #3517 (@akirk)
7+
- Strip overstriking before applying syntax highlighting to better support man pages, see #3517 (@akirk)
88
- `--help` now correctly honors `--pager=builtin`. See #3516 (@keith-hall)
99

1010
## Other

src/printer.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -167,20 +167,12 @@ impl Printer for SimplePrinter<'_> {
167167
}
168168
}
169169
} else {
170+
// SimplePrinter doesn't have syntax info, so we don't strip overstrike.
171+
// This preserves raw data for plain output mode.
170172
match handle {
171-
OutputHandle::IoWrite(handle) => {
172-
// Only strip overstrike for valid UTF-8, otherwise write raw bytes
173-
if let Ok(line) = std::str::from_utf8(line_buffer) {
174-
let line = strip_overstrike(line);
175-
handle.write_all(line.as_bytes())?;
176-
} else {
177-
handle.write_all(line_buffer)?;
178-
}
179-
}
173+
OutputHandle::IoWrite(handle) => handle.write_all(line_buffer)?,
180174
OutputHandle::FmtWrite(handle) => {
181-
let line = String::from_utf8_lossy(line_buffer);
182-
let line = strip_overstrike(&line);
183-
write!(handle, "{line}")?;
175+
write!(handle, "{}", String::from_utf8_lossy(line_buffer))?;
184176
}
185177
}
186178
};
@@ -216,6 +208,7 @@ pub(crate) struct InteractivePrinter<'a> {
216208
background_color_highlight: Option<Color>,
217209
consecutive_empty_lines: usize,
218210
strip_ansi: bool,
211+
strip_overstrike: bool,
219212
}
220213

221214
impl<'a> InteractivePrinter<'a> {
@@ -314,6 +307,10 @@ impl<'a> InteractivePrinter<'a> {
314307
_ => false,
315308
};
316309

310+
// Strip overstrike only when we have syntax highlighting (not plain text).
311+
// Overstrike is used by man pages for bold/underline formatting.
312+
let strip_overstrike = !is_plain_text;
313+
317314
Ok(InteractivePrinter {
318315
panel_width,
319316
colors,
@@ -327,6 +324,7 @@ impl<'a> InteractivePrinter<'a> {
327324
background_color_highlight,
328325
consecutive_empty_lines: 0,
329326
strip_ansi,
327+
strip_overstrike,
330328
})
331329
}
332330

@@ -640,7 +638,7 @@ impl Printer for InteractivePrinter<'_> {
640638
};
641639

642640
// Strip overstrike sequences (used by man pages for bold/underline).
643-
if line.contains('\x08') {
641+
if self.strip_overstrike && line.contains('\x08') {
644642
line = Cow::Owned(strip_overstrike(&line).into_owned());
645643
}
646644

tests/examples/git-commit.man

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
GIT-COMMIT(1) Git Manual GIT-COMMIT(1)
2+
3+
NNAAMMEE
4+
git-commit - Record changes to the repository
5+
6+
SSYYNNOOPPSSIISS
7+
ggiitt ccoommmmiitt [--aa | ----iinntteerraaccttiivvee | ----ppaattcchh] [--ss] [--vv] [--uu[_<_m_o_d_e_>]] [----aammeenndd]
8+
[----ddrryy--rruunn] [(--cc | --CC | ----ssqquuaasshh) _<_c_o_m_m_i_t_> | ----ffiixxuupp [(aammeenndd|rreewwoorrdd)::]_<_c_o_m_m_i_t_>]
9+
[--FF _<_f_i_l_e_> | --mm _<_m_s_g_>] [----rreesseett--aauutthhoorr] [----aallllooww--eemmppttyy]
10+
[----aallllooww--eemmppttyy--mmeessssaaggee] [----nnoo--vveerriiffyy] [--ee] [----aauutthhoorr==_<_a_u_t_h_o_r_>]
11+
[----ddaattee==_<_d_a_t_e_>] [----cclleeaannuupp==_<_m_o_d_e_>] [----[nnoo--]ssttaattuuss]
12+
[--ii | --oo] [----ppaatthhssppeecc--ffrroomm--ffiillee==_<_f_i_l_e_> [----ppaatthhssppeecc--ffiillee--nnuull]]
13+
[(----ttrraaiilleerr _<_t_o_k_e_n_>[(==|::)_<_v_a_l_u_e_>])...] [--SS[_<_k_e_y_i_d_>]]
14+
[----] [_<_p_a_t_h_s_p_e_c_>...]
15+
16+
DDEESSCCRRIIPPTTIIOONN
17+
Create a new commit containing the current contents of the index and
18+
the given log message describing the changes. The new commit is a
19+
direct child of HEAD, usually the tip of the current branch, and the
20+
branch is updated to point to it (unless no branch is associated with
21+
the working tree, in which case HHEEAADD is "detached" as described in ggiitt--
22+
cchheecckkoouutt(1)).
23+
24+
The content to be committed can be specified in several ways:
25+
26+
1. by using ggiitt--aadddd(1) to incrementally "add" changes to the index
27+
before using the ccoommmmiitt command (Note: even modified files must be
28+
"added");
29+
30+
2. by using ggiitt--rrmm(1) to remove files from the working tree and the

tests/examples/overstrike.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
BBold tteexxtt and _u_n_d_e_r_l_i_n_e

tests/integration_tests.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2541,6 +2541,46 @@ fn binary_as_text() {
25412541
.stderr("");
25422542
}
25432543

2544+
#[test]
2545+
fn no_strip_overstrike_for_plain_text() {
2546+
// Overstrike is preserved for plain text files (no syntax highlighting)
2547+
bat()
2548+
.arg("--color=never")
2549+
.arg("--decorations=never")
2550+
.arg("overstrike.txt")
2551+
.assert()
2552+
.success()
2553+
.stdout("B\x08Bold t\x08te\x08ex\x08xt\x08t and _\x08u_\x08n_\x08d_\x08e_\x08r_\x08l_\x08i_\x08n_\x08e\n")
2554+
.stderr("");
2555+
}
2556+
2557+
#[test]
2558+
fn strip_overstrike_with_syntax_highlighting() {
2559+
// Overstrike is stripped when syntax highlighting is applied (e.g., for help)
2560+
bat()
2561+
.arg("--force-colorization")
2562+
.arg("--language=help")
2563+
.arg("overstrike.txt")
2564+
.assert()
2565+
.success()
2566+
.stdout(predicate::str::contains("Bold text and underline"))
2567+
.stderr("");
2568+
}
2569+
2570+
#[test]
2571+
fn strip_overstrike_for_manpage_syntax() {
2572+
// Overstrike is stripped for .man files (Manpage syntax)
2573+
bat()
2574+
.arg("--force-colorization")
2575+
.arg("git-commit.man")
2576+
.assert()
2577+
.success()
2578+
.stdout(predicate::str::contains("NAME"))
2579+
.stdout(predicate::str::contains("git-commit - Record changes"))
2580+
.stdout(predicate::str::is_match(r"\x1b\[38;[0-9;]+m--interactive\x1b\[").unwrap())
2581+
.stderr("");
2582+
}
2583+
25442584
#[test]
25452585
fn no_paging_arg() {
25462586
bat()

0 commit comments

Comments
 (0)