diff options
author | Jacob Keller <jacob.e.keller@intel.com> | 2017-03-28 15:49:50 -0700 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2017-04-02 16:35:08 -0700 |
commit | 9daef34543cc3267ec8e2cc22488bf202448ed84 (patch) | |
tree | e0cb2828dc5477fe61f9edf6db41c36edd350664 | |
parent | c7bcea1b78a581e85247d51980db22b7a3858f58 (diff) | |
download | coreutils-9daef34543cc3267ec8e2cc22488bf202448ed84.tar.gz |
expand,unexpand: add support for incremental tab stops
Support --tabs="1,+8" which is equivalent to --tabs="1,9,17,..."
useful for viewing unified diff output with its 1 character
gutter for example.
* doc/coreutils.texi ({expand,unexpand} invocation): Document,
using diff processing as the example.
* src/expand-common.c (set_increment_size): Update the new
increment_size global.
(parse_tab_stops): Handle the new '+' prefix.
(finalize_tab_stops): Verify both '+' and '/' prefixes
are not used together.
* tests/misc/expand.pl: Add test cases.
* NEWS: Mention the new feature.
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | doc/coreutils.texi | 8 | ||||
-rw-r--r-- | src/expand-common.c | 60 | ||||
-rwxr-xr-x | tests/misc/expand.pl | 16 |
4 files changed, 86 insertions, 2 deletions
@@ -17,6 +17,10 @@ GNU coreutils NEWS -*- outline -*- ** New features + expand and unexpand now support specifying an offset for tab stops + by prefixing the last specified number like --tabs=1,+8 which is + useful for visualizing diff output for example. + split supports a new --hex-suffixes[=from] option to create files with lower case hexadecimal suffixes, similar to the --numeric-suffixes option. diff --git a/doc/coreutils.texi b/doc/coreutils.texi index b8e24aa56..c22e07615 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -7056,10 +7056,18 @@ If only one tab stop is given, set the tabs @var{tab1} spaces apart last tab stop given with single spaces. @macro gnuExpandTabs Tab stops can be separated by blanks as well as by commas. + As a GNU extension the last @var{tab} specified can be prefixed with a @samp{/} to indicate a tab size to use for remaining positions. For example, @option{--tabs=2,4,/8} will set tab stops at position 2 and 4, and every multiple of 8 after that. + +Also the last @var{tab} specified can be prefixed with a @samp{+} to indicate +a tab size to use for remaining positions, offset from the final explicitly +specified tab stop. +For example, to ignore the 1 character gutter present in diff output, +one can specify a 1 character offset using @option{--tabs=1,+8}, +which will set tab stops at positions 1,9,17,@dots{} @end macro @gnuExpandTabs diff --git a/src/expand-common.c b/src/expand-common.c index e1b549fab..05e5bec2d 100644 --- a/src/expand-common.c +++ b/src/expand-common.c @@ -38,6 +38,9 @@ static uintmax_t tab_size = 0; /* If nonzero, the size of all tab stops after the last specifed. */ static uintmax_t extend_size = 0; +/* If nonzero, an increment for additional tab stops after the last specified.*/ +static uintmax_t increment_size = 0; + /* The maximum distance between tab stops. */ size_t max_column_width; @@ -106,6 +109,23 @@ set_extend_size (uintmax_t tabval) return ok; } +static bool +set_increment_size (uintmax_t tabval) +{ + bool ok = true; + + if (increment_size) + { + error (0,0, + _("'+' specifier only allowed" + " with the last value")); + ok = false; + } + increment_size = tabval; + + return ok; +} + /* Add the comma or blank separated list of tab stops STOPS to the list of tab stops. */ extern void @@ -114,6 +134,7 @@ parse_tab_stops (char const *stops) bool have_tabval = false; uintmax_t tabval = 0; bool extend_tabval = false; + bool increment_tabval = false; char const *num_start = NULL; bool ok = true; @@ -131,6 +152,14 @@ parse_tab_stops (char const *stops) break; } } + else if (increment_tabval) + { + if (! set_increment_size (tabval)) + { + ok = false; + break; + } + } else add_tab_stop (tabval); } @@ -145,6 +174,18 @@ parse_tab_stops (char const *stops) ok = false; } extend_tabval = true; + increment_tabval = false; + } + else if (*stops == '+') + { + if (have_tabval) + { + error (0, 0, _("'+' specifier not at start of number: %s"), + quote (stops)); + ok = false; + } + increment_tabval = true; + extend_tabval = false; } else if (ISDIGIT (*stops)) { @@ -179,6 +220,8 @@ parse_tab_stops (char const *stops) { if (extend_tabval) ok &= set_extend_size (tabval); + else if (increment_tabval) + ok &= set_increment_size (tabval); else add_tab_stop (tabval); } @@ -204,6 +247,9 @@ validate_tab_stops (uintmax_t const *tabs, size_t entries) die (EXIT_FAILURE, 0, _("tab sizes must be ascending")); prev_tab = tabs[i]; } + + if (increment_size && extend_size) + die (EXIT_FAILURE, 0, _("'/' specifier is mutually exclusive with '+'")); } /* Called after all command-line options have been parsed, @@ -220,8 +266,10 @@ finalize_tab_stops (void) validate_tab_stops (tab_list, first_free_tab); if (first_free_tab == 0) - tab_size = max_column_width = extend_size ? extend_size : 8; - else if (first_free_tab == 1 && ! extend_size) + tab_size = max_column_width = extend_size + ? extend_size : increment_size + ? increment_size : 8; + else if (first_free_tab == 1 && ! extend_size && ! increment_size) tab_size = tab_list[0]; else tab_size = 0; @@ -251,6 +299,14 @@ get_next_tab_column (const uintmax_t column, size_t* tab_index, if (extend_size) return column + (extend_size - column % extend_size); + /* incremental last tab - add increment_size to the previous tab stop */ + if (increment_size) + { + uintmax_t end_tab = tab_list[first_free_tab - 1]; + + return column + (increment_size - ((column - end_tab) % increment_size)); + } + *last_tab = true; return 0; } diff --git a/tests/misc/expand.pl b/tests/misc/expand.pl index b04d2e72d..7fe783042 100755 --- a/tests/misc/expand.pl +++ b/tests/misc/expand.pl @@ -146,11 +146,27 @@ my @Tests = ['trail3', '--tabs=1,2,/5', {IN=>"\ta\tb\tc"}, {OUT=>" a b c"}], ['trail4', '--tabs=/5', {IN=>"\ta\tb"}, {OUT=>" a b"}], ['trail5', '--tabs=//5', {IN=>"\ta\tb"}, {OUT=>" a b"}], + ['trail5a','--tabs=+/5', {IN=>"\ta\tb"}, {OUT=>" a b"}], ['trail6', '--tabs=/,/5', {IN=>"\ta\tb"}, {OUT=>" a b"}], ['trail7', '--tabs=,/5', {IN=>"\ta\tb"}, {OUT=>" a b"}], ['trail8', '--tabs=1 -t/5', {IN=>"\ta\tb\tc"}, {OUT=>" a b c"}], ['trail9', '--tab=1,2 -t/5',{IN=>"\ta\tb\tc"}, {OUT=>" a b c"}], + # Test incremental trailing '+' feature which specifies that + # tab stops should continue every increment + ['incre0', '--tab=1,+5', {IN=>"+\t\ta\tb"}, {OUT=>"+ a b"}], + ['incre1', '--tabs=1,+5', {IN=>"\ta\tb\tc"}, {OUT=>" a b c"}], + ['incre2', '--tabs=2,+5', {IN=>"\ta\tb\tc"}, {OUT=>" a b c"}], + ['incre3', '--tabs=1,2,+5', {IN=>"\ta\tb\tc"}, {OUT=>" a b c"}], + ['incre4', '--tabs=+5', {IN=>"\ta\tb"}, {OUT=>" a b"}], + ['incre5', '--tabs=++5', {IN=>"\ta\tb"}, {OUT=>" a b"}], + ['incre5a','--tabs=/+5', {IN=>"\ta\tb"}, {OUT=>" a b"}], + ['incre6', '--tabs=+,+5', {IN=>"\ta\tb"}, {OUT=>" a b"}], + ['incre7', '--tabs=,+5', {IN=>"\ta\tb"}, {OUT=>" a b"}], + ['incre8', '--tabs=1 -t+5', {IN=>"\ta\tb\tc"}, {OUT=>" a b c"}], + ['incre9', '--tab=1,2 -t+5',{IN=>"\ta\tb\tc"}, {OUT=>" a b c"}], + + # Test errors ['e1', '--tabs="a"', {IN=>''}, {OUT=>''}, {EXIT=>1}, {ERR => "$prog: tab size contains invalid character(s): 'a'\n"}], |