From: drax Date: Sat, 6 Jul 2024 23:29:27 +0000 (+0200) Subject: column: Adds option -S so whitespaces are used instead of tabs in non table... X-Git-Tag: v2.42-start~274^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aec8bf943a71a25cbaa5cfc1b113263cadc74dd0;p=thirdparty%2Futil-linux.git column: Adds option -S so whitespaces are used instead of tabs in non table mode. Entries are padded with whitespaces, then spaces are added to separate the columns. This should fix https://github.com/util-linux/util-linux/issues/1551 --- diff --git a/bash-completion/column b/bash-completion/column index 3de9f16da..c9132f54d 100644 --- a/bash-completion/column +++ b/bash-completion/column @@ -5,7 +5,7 @@ _column_module() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" case $prev in - '-c'|'--output-width'|'-l'|'--table-columns-limit') + '-c'|'--output-width'|'-l'|'--table-columns-limit'|'-S'|'--use-spaces') COMPREPLY=( $(compgen -W "number" -- $cur) ) return 0 ;; @@ -50,6 +50,7 @@ _column_module() --separator --output-separator --fillrows + --use-spaces --help --version" COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) ) diff --git a/text-utils/column.1.adoc b/text-utils/column.1.adoc index c16743597..0fdc53455 100644 --- a/text-utils/column.1.adoc +++ b/text-utils/column.1.adoc @@ -89,6 +89,9 @@ Specify the columns delimiter for table output (default is two spaces). *-s, --separator* _separators_:: Specify the possible input item delimiters (default is whitespace). +*-S, --use-spaces* _number_:: +When not in table mode, use whitespaces instead of tabulations to align the columns. This option specifies the minimum number of whitespaces that separate two columns. + *-t, --table*:: Determine the number of columns the input contains and create a table. Columns are delimited with whitespace, by default, or with the characters supplied using the *--output-separator* option. Table output is useful for pretty-printing. diff --git a/text-utils/column.c b/text-utils/column.c index 9d11fe7ac..f5ae83d72 100644 --- a/text-utils/column.c +++ b/text-utils/column.c @@ -94,6 +94,7 @@ struct column_control { size_t nents; /* number of entries */ size_t maxlength; /* longest input record (line) */ size_t maxncols; /* maximal number of input columns */ + size_t mincolsep; /* minimal spaces between columns */ unsigned int greedy :1, json :1, @@ -101,7 +102,8 @@ struct column_control { hide_unnamed :1, maxout : 1, keep_empty_lines :1, /* --keep-empty-lines */ - tab_noheadings :1; + tab_noheadings :1, + use_spaces :1; }; typedef enum { @@ -753,11 +755,17 @@ static int read_input(struct column_control *ctl, FILE *fp) static void columnate_fillrows(struct column_control *ctl) { - size_t chcnt, col, cnt, endcol, numcols; + size_t chcnt, col, cnt, endcol, numcols, remains; wchar_t **lp; - ctl->maxlength = (ctl->maxlength + TABCHAR_CELLS) & ~(TABCHAR_CELLS - 1); + if (ctl->use_spaces) + ctl->maxlength += ctl->mincolsep; + else + ctl->maxlength = (ctl->maxlength + TABCHAR_CELLS) & ~(TABCHAR_CELLS - 1); numcols = ctl->termwidth / ctl->maxlength; + remains = ctl->termwidth % ctl->maxlength; + if (ctl->use_spaces && remains + ctl->mincolsep >= ctl->maxlength) + numcols++; endcol = ctl->maxlength; for (chcnt = col = 0, lp = ctl->ents; /* nothing */; ++lp) { fputws(*lp, stdout); @@ -769,9 +777,16 @@ static void columnate_fillrows(struct column_control *ctl) endcol = ctl->maxlength; putwchar('\n'); } else { - while ((cnt = ((chcnt + TABCHAR_CELLS) & ~(TABCHAR_CELLS - 1))) <= endcol) { - putwchar('\t'); - chcnt = cnt; + if (ctl->use_spaces) { + while (chcnt < endcol) { + putwchar(' '); + chcnt++; + } + } else { + while ((cnt = ((chcnt + TABCHAR_CELLS) & ~(TABCHAR_CELLS - 1))) <= endcol) { + putwchar('\t'); + chcnt = cnt; + } } endcol += ctl->maxlength; } @@ -782,12 +797,18 @@ static void columnate_fillrows(struct column_control *ctl) static void columnate_fillcols(struct column_control *ctl) { - size_t base, chcnt, cnt, col, endcol, numcols, numrows, row; + size_t base, chcnt, cnt, col, endcol, numcols, numrows, row, remains; - ctl->maxlength = (ctl->maxlength + TABCHAR_CELLS) & ~(TABCHAR_CELLS - 1); + if (ctl->use_spaces) + ctl->maxlength += ctl->mincolsep; + else + ctl->maxlength = (ctl->maxlength + TABCHAR_CELLS) & ~(TABCHAR_CELLS - 1); numcols = ctl->termwidth / ctl->maxlength; + remains = ctl->termwidth % ctl->maxlength; if (!numcols) numcols = 1; + if (ctl->use_spaces && remains + ctl->mincolsep >= ctl->maxlength) + numcols++; numrows = ctl->nents / numcols; if (ctl->nents % numcols) ++numrows; @@ -799,9 +820,16 @@ static void columnate_fillcols(struct column_control *ctl) chcnt += width(ctl->ents[base]); if ((base += numrows) >= ctl->nents) break; - while ((cnt = ((chcnt + TABCHAR_CELLS) & ~(TABCHAR_CELLS - 1))) <= endcol) { - putwchar('\t'); - chcnt = cnt; + if (ctl->use_spaces) { + while (chcnt < endcol) { + putwchar(' '); + chcnt++; + } + } else { + while ((cnt = ((chcnt + TABCHAR_CELLS) & ~(TABCHAR_CELLS - 1))) <= endcol) { + putwchar('\t'); + chcnt = cnt; + } } endcol += ctl->maxlength; } @@ -858,6 +886,7 @@ static void __attribute__((__noreturn__)) usage(void) fputs(_(" -o, --output-separator columns separator for table output (default is two spaces)\n"), out); fputs(_(" -s, --separator possible table delimiters\n"), out); fputs(_(" -x, --fillrows fill rows before columns\n"), out); + fputs(_(" -S, --use-spaces minimal whitespaces between columns (no tabs)\n"), out); fputs(USAGE_SEPARATOR, out); @@ -906,6 +935,7 @@ int main(int argc, char **argv) { "tree", required_argument, NULL, 'r' }, { "tree-id", required_argument, NULL, 'i' }, { "tree-parent", required_argument, NULL, 'p' }, + { "use-spaces", required_argument, NULL, 'S' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 }, }; @@ -925,7 +955,7 @@ int main(int argc, char **argv) ctl.output_separator = " "; ctl.input_separator = mbs_to_wcs("\t "); - while ((c = getopt_long(argc, argv, "C:c:dE:eH:hi:Jl:LN:n:mO:o:p:R:r:s:T:tVW:x", longopts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "C:c:dE:eH:hi:Jl:LN:n:mO:o:p:R:r:S:s:T:tVW:x", longopts, NULL)) != -1) { err_exclusive_options(c, longopts, excl, excl_st); @@ -992,6 +1022,10 @@ int main(int argc, char **argv) case 'r': ctl.tree = optarg; break; + case 'S': + ctl.use_spaces = 1; + ctl.mincolsep = strtou32_or_err(optarg, _("invalid spaces argument")); + break; case 's': free(ctl.input_separator); ctl.input_separator = mbs_to_wcs(optarg);