1
0
mirror of https://github.com/sharkdp/bat.git synced 2026-02-08 00:32:08 +00:00

Only strip overstrike when a syntax highlighting theme is used

This commit is contained in:
Alex Kirk
2025-12-09 10:17:15 +01:00
parent 5fb8a25c30
commit 64a4b204a2
5 changed files with 80 additions and 15 deletions

View File

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

View File

@@ -168,19 +168,9 @@ impl Printer for SimplePrinter<'_> {
}
} else {
match handle {
OutputHandle::IoWrite(handle) => {
// Only strip overstrike for valid UTF-8, otherwise write raw bytes
if let Ok(line) = std::str::from_utf8(line_buffer) {
let line = strip_overstrike(line);
handle.write_all(line.as_bytes())?;
} else {
handle.write_all(line_buffer)?;
}
}
OutputHandle::IoWrite(handle) => handle.write_all(line_buffer)?,
OutputHandle::FmtWrite(handle) => {
let line = String::from_utf8_lossy(line_buffer);
let line = strip_overstrike(&line);
write!(handle, "{line}")?;
write!(handle, "{}", String::from_utf8_lossy(line_buffer))?;
}
}
};
@@ -216,6 +206,7 @@ pub(crate) struct InteractivePrinter<'a> {
background_color_highlight: Option<Color>,
consecutive_empty_lines: usize,
strip_ansi: bool,
strip_overstrike: bool,
}
impl<'a> InteractivePrinter<'a> {
@@ -314,6 +305,9 @@ impl<'a> InteractivePrinter<'a> {
_ => false,
};
// Strip overstrike only when we have syntax highlighting (not plain text).
let strip_overstrike = !is_plain_text;
Ok(InteractivePrinter {
panel_width,
colors,
@@ -327,6 +321,7 @@ impl<'a> InteractivePrinter<'a> {
background_color_highlight,
consecutive_empty_lines: 0,
strip_ansi,
strip_overstrike,
})
}
@@ -639,8 +634,7 @@ impl Printer for InteractivePrinter<'_> {
}
};
// Strip overstrike sequences (used by man pages for bold/underline).
if line.contains('\x08') {
if self.strip_overstrike && line.contains('\x08') {
line = Cow::Owned(strip_overstrike(&line).into_owned());
}

30
tests/examples/git-commit.man vendored Normal file
View File

@@ -0,0 +1,30 @@
GIT-COMMIT(1) Git Manual GIT-COMMIT(1)
NNAAMMEE
git-commit - Record changes to the repository
SSYYNNOOPPSSIISS
ggiitt ccoommmmiitt [--aa | ----iinntteerraaccttiivvee | ----ppaattcchh] [--ss] [--vv] [--uu[_<_m_o_d_e_>]] [----aammeenndd]
[----ddrryy--rruunn] [(--cc | --CC | ----ssqquuaasshh) _<_c_o_m_m_i_t_> | ----ffiixxuupp [(aammeenndd|rreewwoorrdd)::]_<_c_o_m_m_i_t_>]
[--FF _<_f_i_l_e_> | --mm _<_m_s_g_>] [----rreesseett--aauutthhoorr] [----aallllooww--eemmppttyy]
[----aallllooww--eemmppttyy--mmeessssaaggee] [----nnoo--vveerriiffyy] [--ee] [----aauutthhoorr==_<_a_u_t_h_o_r_>]
[----ddaattee==_<_d_a_t_e_>] [----cclleeaannuupp==_<_m_o_d_e_>] [----[nnoo--]ssttaattuuss]
[--ii | --oo] [----ppaatthhssppeecc--ffrroomm--ffiillee==_<_f_i_l_e_> [----ppaatthhssppeecc--ffiillee--nnuull]]
[(----ttrraaiilleerr _<_t_o_k_e_n_>[(==|::)_<_v_a_l_u_e_>])...] [--SS[_<_k_e_y_i_d_>]]
[----] [_<_p_a_t_h_s_p_e_c_>...]
DDEESSCCRRIIPPTTIIOONN
Create a new commit containing the current contents of the index and
the given log message describing the changes. The new commit is a
direct child of HEAD, usually the tip of the current branch, and the
branch is updated to point to it (unless no branch is associated with
the working tree, in which case HHEEAADD is "detached" as described in ggiitt--
cchheecckkoouutt(1)).
The content to be committed can be specified in several ways:
1. by using ggiitt--aadddd(1) to incrementally "add" changes to the index
before using the ccoommmmiitt command (Note: even modified files must be
"added");
2. by using ggiitt--rrmm(1) to remove files from the working tree and the

1
tests/examples/overstrike.txt vendored Normal file
View File

@@ -0,0 +1 @@
BBold tteexxtt and _u_n_d_e_r_l_i_n_e

View File

@@ -2541,6 +2541,46 @@ fn binary_as_text() {
.stderr("");
}
#[test]
fn no_strip_overstrike_for_plain_text() {
// Overstrike is preserved for plain text files (no syntax highlighting)
bat()
.arg("--color=never")
.arg("--decorations=never")
.arg("overstrike.txt")
.assert()
.success()
.stdout("B\x08Bold t\x08te\x08ex\x08xt\x08t and _\x08u_\x08n_\x08d_\x08e_\x08r_\x08l_\x08i_\x08n_\x08e\n")
.stderr("");
}
#[test]
fn strip_overstrike_with_syntax_highlighting() {
// Overstrike is stripped when syntax highlighting is applied (e.g., for help)
bat()
.arg("--force-colorization")
.arg("--language=help")
.arg("overstrike.txt")
.assert()
.success()
.stdout(predicate::str::contains("Bold text and underline"))
.stderr("");
}
#[test]
fn strip_overstrike_for_manpage_syntax() {
// Overstrike is stripped for .man files (Manpage syntax)
bat()
.arg("--force-colorization")
.arg("git-commit.man")
.assert()
.success()
.stdout(predicate::str::contains("NAME"))
.stdout(predicate::str::contains("git-commit - Record changes"))
.stdout(predicate::str::is_match(r"\x1b\[38;[0-9;]+m--interactive\x1b\[").unwrap())
.stderr("");
}
#[test]
fn no_paging_arg() {
bat()