mirror of
https://github.com/sharkdp/bat
synced 2026-08-08 19:41:45 +00:00
Merge pull request #3640 from eyupcanakman/fix/binary-as-text-width-3631
Fix line wrapping for files with control characters
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
- Add `--fallback-syntax`/`--fallback-language` to apply syntax highlighting only when auto-detection fails, see #1341 (@Xavrir)
|
- Add `--fallback-syntax`/`--fallback-language` to apply syntax highlighting only when auto-detection fails, see #1341 (@Xavrir)
|
||||||
|
|
||||||
## Bugfixes
|
## Bugfixes
|
||||||
|
- 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 `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)
|
- 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)
|
- Report error when pager is missing instead of silently falling back, see #3588 (@IMaloney)
|
||||||
|
|||||||
+13
-5
@@ -37,6 +37,16 @@ use crate::wrapping::WrappingMode;
|
|||||||
use crate::BinaryBehavior;
|
use crate::BinaryBehavior;
|
||||||
use crate::StripAnsiMode;
|
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 {
|
const ANSI_UNDERLINE_ENABLE: EscapeSequence = EscapeSequence::CSI {
|
||||||
raw_sequence: "\x1B[4m",
|
raw_sequence: "\x1B[4m",
|
||||||
parameters: "4",
|
parameters: "4",
|
||||||
@@ -793,7 +803,7 @@ impl Printer for InteractivePrinter<'_> {
|
|||||||
|
|
||||||
for c in text.chars() {
|
for c in text.chars() {
|
||||||
// calculate the displayed width for next character
|
// calculate the displayed width for next character
|
||||||
let cw = c.width().unwrap_or(0);
|
let cw = char_width(c);
|
||||||
current_width += cw;
|
current_width += cw;
|
||||||
|
|
||||||
// Track whitespace positions for word wrapping.
|
// Track whitespace positions for word wrapping.
|
||||||
@@ -868,10 +878,8 @@ impl Printer for InteractivePrinter<'_> {
|
|||||||
if let Some(rs) = rest_start {
|
if let Some(rs) = rest_start {
|
||||||
// Word wrap: carry remainder to next line.
|
// Word wrap: carry remainder to next line.
|
||||||
let remainder = line_buf[rs..].to_string();
|
let remainder = line_buf[rs..].to_string();
|
||||||
let rem_width: usize = remainder
|
let rem_width: usize =
|
||||||
.chars()
|
remainder.chars().map(char_width).sum();
|
||||||
.map(|ch| ch.width().unwrap_or(0))
|
|
||||||
.sum();
|
|
||||||
line_buf.clear();
|
line_buf.clear();
|
||||||
line_buf.push_str(&remainder);
|
line_buf.push_str(&remainder);
|
||||||
current_width = rem_width + cw;
|
current_width = rem_width + cw;
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -2681,6 +2681,25 @@ fn binary_as_text() {
|
|||||||
.stderr("");
|
.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]
|
#[test]
|
||||||
fn no_strip_overstrike_for_plain_text() {
|
fn no_strip_overstrike_for_plain_text() {
|
||||||
// Overstrike is preserved for plain text files (no syntax highlighting)
|
// Overstrike is preserved for plain text files (no syntax highlighting)
|
||||||
|
|||||||
Reference in New Issue
Block a user