** 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.
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
/* 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;
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
bool have_tabval = false;
uintmax_t tabval = 0;
bool extend_tabval = false;
+ bool increment_tabval = false;
char const *num_start = NULL;
bool ok = true;
break;
}
}
+ else if (increment_tabval)
+ {
+ if (! set_increment_size (tabval))
+ {
+ ok = false;
+ break;
+ }
+ }
else
add_tab_stop (tabval);
}
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))
{
{
if (extend_tabval)
ok &= set_extend_size (tabval);
+ else if (increment_tabval)
+ ok &= set_increment_size (tabval);
else
add_tab_stop (tabval);
}
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,
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;
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;
}
['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"}],