grep: don't emit the -T alignment tab on empty lines

With -T, grep pads the prefix with a tab so line content lands on a tab
stop. GNU omits that tab when the line has no content: an empty line
prints just its prefix (a whitespace-only line still gets the tab).
uu_grep always wrote the tab, so empty matched lines gained a spurious
trailing tab. Gate the tab on non-empty content. Fixes the GNU testsuite
'initial-tab' test.
This commit is contained in:
Sylvestre Ledru
2026-05-30 18:06:14 +02:00
parent 98e6bb6f53
commit a7b15320af
2 changed files with 24 additions and 0 deletions
+6
View File
@@ -71,6 +71,7 @@ impl<'a> OutputWriter<'a> {
view.line_number,
view.byte_offset + start as u64,
b':',
false,
)?;
self.write_colored_bytes(
@@ -90,6 +91,7 @@ impl<'a> OutputWriter<'a> {
view.line_number,
view.byte_offset,
if view.is_match { b':' } else { b'-' },
view.line.is_empty(),
)?;
let mut last_end = 0;
@@ -125,6 +127,7 @@ impl<'a> OutputWriter<'a> {
line_number: u64,
byte_offset: u64,
sep_char: u8,
content_empty: bool,
) -> io::Result<()> {
if self.config.show_filename {
self.write_colored_fmt(
@@ -155,7 +158,10 @@ impl<'a> OutputWriter<'a> {
self.write_separator(sep_char)?;
}
// GNU grep aligns content with a tab under -T, but only when there is
// content to align: an empty line keeps just its prefix (no tab).
if self.config.initial_tab
&& !content_empty
&& (self.config.line_number || self.config.byte_offset || self.config.show_filename)
{
self.out.write_all(b"\t")?;
+18
View File
@@ -126,6 +126,24 @@ fn ere_invalid_pattern_is_error() {
.stderr_contains("invalid pattern");
}
#[test]
fn initial_tab_skips_empty_lines() {
// -T aligns content with a tab, but GNU omits the tab for an empty line
// (a whitespace-only line still gets one). -H forces the filename prefix
// on, so the tab is exercised.
let (s, mut c) = ucmd();
s.fixtures.write("in", "x\n\n");
c.args(&["-T", "-H", "^", "in"])
.succeeds()
.stdout_is("in:\tx\nin:\n");
let (s, mut c) = ucmd();
s.fixtures.write("in", "x\n \n");
c.args(&["-T", "-H", "^", "in"])
.succeeds()
.stdout_is("in:\tx\nin:\t \n");
}
#[test]
fn fixed_string_is_literal() {
// Metacharacters are not interpreted.