coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH RFC] expand: add support for incremental tab stops


From: Pádraig Brady
Subject: Re: [PATCH RFC] expand: add support for incremental tab stops
Date: Tue, 28 Mar 2017 19:43:54 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0

On 28/03/17 15:49, Jacob Keller wrote:
> When viewing output of a diff program in unified format, the output
> comes prefixed by a single column to show which lines are removed,
> added, or just context. This single column can impact the display of tab
> characters compared to how they would display if the lines were not
> prefixed. For example, diff might show
> 
>  a context line
>  another context line
> +a new line
> -an old line
> 
> But if there were tabs, it could incorrectly display these due to the
> change in the column widths. Add a new option to the expand tab list
> which will allow us to specify how to expand tabs in this scenario.
> 
> Currently, expand has the option of specifying hard coded tab stop
> lists, as well as extending this with a '/' notation which indicates to
> continue with tab stops at that multiple when the hard coded list is
> used up.
> 
> Add a new variant, '+' prefix to the last tab, which indicates to keep
> adding tabs at that increment after the last hard coded tab stop.
> 
> Thus, --tabs="1,+8" is equivalent to --tabs="1,9,17,25,33,41,49,57,..."
> 
> This is useful because we can now pipe the output of a diff command and
> properly expand the tabs as the user would expect, keeping all tabs
> properly aligned so that the output does not appear munged.
> 
> It may be worth adding a separate switch for this mode "--diff" or
> similar so that users are more likely to discover the capability, but
> this patch does not implement such an option at this time.
> ---
>  src/expand-common.c  | 63 
> ++++++++++++++++++++++++++++++++++++++++++++++++++--
>  src/expand.c         |  5 +++++
>  tests/misc/expand.pl | 14 ++++++++++++
>  3 files changed, 80 insertions(+), 2 deletions(-)
> 
> diff --git a/src/expand-common.c b/src/expand-common.c
> index e1b549fab101..7b7902284e33 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;
>  
> @@ -94,7 +97,7 @@ set_extend_size (uintmax_t tabval)
>  {
>    bool ok = true;
>  
> -  if (extend_size)
> +  if (extend_size || increment_size)
>      {
>        error (0, 0,
>               _("'/' specifier only allowed"
> @@ -106,6 +109,23 @@ set_extend_size (uintmax_t tabval)
>    return ok;
>  }
>  
> +static bool
> +set_increment_size(uintmax_t tabval)
> +{
> +  bool ok = true;
> +
> +  if (extend_size || 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);
>              }
> @@ -144,8 +173,28 @@ parse_tab_stops (char const *stops)
>                       quote (stops));
>                ok = false;
>              }
> +          else if (increment_tabval)
> +            {
> +              error (0, 0, _("'/' specifier mutually exclusive with '+'"));
> +              ok = false;
> +            }
>            extend_tabval = true;
>          }
> +      else if (*stops == '+')
> +        {
> +          if (have_tabval)
> +            {
> +              error (0, 0, _("'+' specifier not at start of number: %s"),
> +                     quote (stops));
> +              ok = false;
> +            }
> +          else if (extend_tabval)
> +            {
> +              error (0, 0, _("'+' specifier mutually exclusive with '/'"));
> +              ok = false;
> +            }
> +          increment_tabval = true;
> +        }
>        else if (ISDIGIT (*stops))
>          {
>            if (!have_tabval)
> @@ -179,6 +228,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);
>      }
> @@ -221,7 +272,7 @@ finalize_tab_stops (void)
>  
>    if (first_free_tab == 0)
>      tab_size = max_column_width = extend_size ? extend_size : 8;
> -  else if (first_free_tab == 1 && ! extend_size)
> +  else if (first_free_tab == 1 && ! extend_size && ! increment_size)
>      tab_size = tab_list[0];
>    else
>      tab_size = 0;
> @@ -251,6 +302,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 final_tab = first_free_tab ? tab_list[first_free_tab - 1] : 
> 0;
> +
> +      return column + (increment_size - ((column - final_tab) % 
> increment_size));
> +    }
> +
>    *last_tab = true;
>    return 0;
>  }
> diff --git a/src/expand.c b/src/expand.c
> index 2b7781ca51e2..8067ba237b2c 100644
> --- a/src/expand.c
> +++ b/src/expand.c
> @@ -83,6 +83,11 @@ Convert tabs in each FILE to spaces, writing to standard 
> output.\n\
>  "), stdout);
>        fputs (_("\
>    -t, --tabs=LIST     use comma separated list of explicit tab positions\n\
> +                      the final value can be preceded by either a '/' in\n\
> +                      which case it indicates additional tab stops at that\n\
> +                      multiple, and it can be preceded by a '+' in which\n\
> +                      case it indicates additional tab stops incrementing\n\
> +                      by that value.\n\
>  "), stdout);
>        fputs (HELP_OPTION_DESCRIPTION, stdout);
>        fputs (VERSION_OPTION_DESCRIPTION, stdout);
> diff --git a/tests/misc/expand.pl b/tests/misc/expand.pl
> index b04d2e72db6b..88e4b26a3c81 100755
> --- a/tests/misc/expand.pl
> +++ b/tests/misc/expand.pl
> @@ -151,6 +151,20 @@ my @Tests =
>     ['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
> +   ['increment0', '--tab=1,+8',    {IN=>"+\t\tb\tc"}, {OUT=>"                
>  b       c"}],
> +   ['increment1', '--tabs=1,+5',   {IN=>"\ta\tb\tc"}, {OUT=>" a    b    c"}],
> +   ['increment2', '--tabs=2,+5',   {IN=>"\ta\tb\tc"}, {OUT=>"  a    b    
> c"}],
> +   ['increment3', '--tabs=1,2,+5', {IN=>"\ta\tb\tc"}, {OUT=>" a     b    
> c"}],
> +   ['increment4', '--tabs=+5',     {IN=>"\ta\tb"},    {OUT=>"     a    b"}],
> +   ['increment5', '--tabs=++5',    {IN=>"\ta\tb"},    {OUT=>"     a    b"}],
> +   ['increment6', '--tabs=+,+5',   {IN=>"\ta\tb"},    {OUT=>"     a    b"}],
> +   ['increment7', '--tabs=,+5',    {IN=>"\ta\tb"},    {OUT=>"     a    b"}],
> +   ['increment8', '--tabs=1 -t+5', {IN=>"\ta\tb\tc"}, {OUT=>" a    b    c"}],
> +   ['increment9', '--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"}],
> 


I like this a lot.
I'll document the `diff one two | expand --tabs=1,+8` example.

thanks!
Pádraig



reply via email to

[Prev in Thread] Current Thread [Next in Thread]