diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2016-11-19 02:49:15 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2016-11-19 02:50:59 -0800 |
commit | 928af46ede5d5bd3b564466042531d57b0e506bf (patch) | |
tree | b0aebeecbb4378a14940e712dc598a3a1493cfd5 | |
parent | a99b612d1a2ce392a7ca6c59724013a965e81e04 (diff) | |
download | grep-928af46ede5d5bd3b564466042531d57b0e506bf.tar.gz |
grep: -T now adjusts number widths for worst case
* NEWS, doc/grep.texi (Output Line Prefix Control):
Document this (Bug#24451).
* src/grep.c (offset_width): New static var.
(print_offset): Use it instead of arg. All callers changed.
(grep): Set it.
* tests/initial-tab: Test this.
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | doc/grep.texi | 6 | ||||
-rw-r--r-- | src/grep.c | 28 | ||||
-rwxr-xr-x | tests/initial-tab | 5 |
4 files changed, 32 insertions, 11 deletions
@@ -20,6 +20,10 @@ GNU grep NEWS -*- outline -*- longer outputs tab-backspace-':'-C, an approach that has problems if run inside an Emacs shell window. [bug introduced in grep-2.5.2] + grep -T now uses worst-case widths of line numbers and byte offsets + instead of guessing widths that might not work with larger files. + [bug introduced in grep-2.5.2] + grep's use of getprogname no longer causes a build failure on HP-UX. ** Improvements diff --git a/doc/grep.texi b/doc/grep.texi index 9af13c42..3a12dce2 100644 --- a/doc/grep.texi +++ b/doc/grep.texi @@ -463,10 +463,8 @@ Make sure that the first character of actual line content lies on a tab stop, so that the alignment of tabs looks normal. This is useful with options that prefix their output to the actual content: @option{-H}, @option{-n}, and @option{-b}. -In order to improve the probability that lines -from a single file will all start at the same column, -this also causes the line number and byte offset (if present) -to be printed in a minimum-size field width. +This may also prepend spaces to output line numbers and byte offsets +so that lines from a single file all start at the same column. @item -u @itemx --unix-byte-offsets @@ -81,6 +81,9 @@ static bool only_matching; /* If nonzero, make sure first content char in a line is on a tab stop. */ static bool align_tabs; +/* Print width of line numbers and byte offsets. Nonzero if ALIGN_TABS. */ +static int offset_width; + /* See below */ struct FL_pair { @@ -1079,12 +1082,13 @@ print_sep (char sep) /* Print a line number or a byte offset. */ static void -print_offset (uintmax_t pos, int min_width, const char *color) +print_offset (uintmax_t pos, const char *color) { #if !HAVE_PRINTF_C99_SIZES /* Do not rely on printf to print pos, since uintmax_t may be longer than long, and long long is not portable. */ + int min_width = offset_width; char buf[sizeof pos * CHAR_BIT]; char *p = buf + sizeof buf; @@ -1096,14 +1100,13 @@ print_offset (uintmax_t pos, int min_width, const char *color) while ((pos /= 10) != 0); /* Do this to maximize the probability of alignment across lines. */ - if (align_tabs) - while (--min_width >= 0) - *--p = ' '; + while (--min_width >= 0) + *--p = ' '; #endif /* !HAVE_PRINTF_C99_SIZES */ pr_sgr_start_if (color); #if HAVE_PRINTF_C99_SIZES - printf_errno ("%*ju", align_tabs ? min_width : 0, pos); + printf_errno ("%*ju", offset_width, pos); #else fwrite_errno (p, 1, buf + sizeof buf - p); #endif @@ -1151,7 +1154,7 @@ print_line_head (char *beg, size_t len, char const *lim, char sep) totalnl = add_count (totalnl, 1); lastnl = lim; } - print_offset (totalnl, 4, line_num_color); + print_offset (totalnl, line_num_color); print_sep (sep); } @@ -1159,7 +1162,7 @@ print_line_head (char *beg, size_t len, char const *lim, char sep) { uintmax_t pos = add_count (totalcc, beg - bufbeg); pos = dossified_pos (pos); - print_offset (pos, 6, byte_num_color); + print_offset (pos, byte_num_color); print_sep (sep); } @@ -1511,6 +1514,17 @@ grep (int fd, struct stat const *st, bool *ineof) return 0; } + offset_width = 0; + if (align_tabs) + { + /* Width is log of maximum number. Line numbers are origin-1. */ + uintmax_t num = usable_st_size (st) ? st->st_size : UINTMAX_MAX; + num += out_line && num < UINTMAX_MAX; + do + offset_width++; + while ((num /= 10) != 0); + } + for (bool firsttime = true; ; firsttime = false) { if (nlines_first_null < 0 && eol && binary_files != TEXT_BINARY_FILES diff --git a/tests/initial-tab b/tests/initial-tab index af5efb37..8b3cb8c4 100755 --- a/tests/initial-tab +++ b/tests/initial-tab @@ -29,4 +29,9 @@ printf 'in:\tx\nin:\n' > exp || framework_failure_ grep -T '^' in /dev/null > out || fail=1 compare exp out || fail=1 +printf '%s\n' a b c d e f g h i j > in1 || framework_failure_ +printf 'in1: 1:\ta\n' > exp1 || framework_failure_ +grep -Tn 'a' in1 /dev/null > out1 || fail=1 +compare exp1 out1 || fail=1 + Exit $fail |