]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libsmartcols: cleanup and extend padding functionality
authorKarel Zak <kzak@redhat.com>
Tue, 23 Jul 2019 14:04:51 +0000 (16:04 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 23 Jul 2019 14:24:42 +0000 (16:24 +0200)
LIBSMARTCOLS_DEBUG_PADDING=on in the next examples forces libsmartcols
print '.' as a padding char. See line "ffff" in the exmaples.

* default output is to fill all except last cell

$ LIBSMARTCOLS_DEBUG_PADDING=on ./sample-scols-fromfile --nlines 10  --width 80 --column tests/ts/libsmartcols/files/col-name --column tests/ts/libsmartcols/files/col-number --column tests/ts/libsmartcols/files/col-string --column tests/ts/libsmartcols/files/col-string tests/ts/libsmartcols/files/data-string tests/ts/libsmartcols/files/data-number tests/ts/libsmartcols/files/data-string-empty tests/ts/libsmartcols/files/data-string-empty 2> /dev/null
NAME.. ......NUM STRINGS STRINGS
aaaa.. ........0 aaaa... aaaa
bbb... ......100 bbb.... bbb
ccccc. .......21 ccccc.. ccccc
dddddd ........3 dddddd. dddddd
ee.... ......411 ee..... ee
ffff.. .....5111 .......
gggggg 678993321 gggggg. gggggg
hhh... ..7666666 hhh.... hhh

* scols_table_enable_minout() minimizes output for tailing empty cells, example:

$ LIBSMARTCOLS_DEBUG_PADDING=on ./sample-scols-fromfile --nlines 10 --minout  --width 80 --column tests/ts/libsmartcols/files/col-name --column tests/ts/libsmartcols/files/col-number --column tests/ts/libsmartcols/files/col-string --column tests/ts/libsmartcols/files/col-string tests/ts/libsmartcols/files/data-string tests/ts/libsmartcols/files/data-number tests/ts/libsmartcols/files/data-string-empty tests/ts/libsmartcols/files/data-string-empty 2> /dev/null
NAME.. ......NUM STRINGS STRINGS
aaaa.. ........0 aaaa... aaaa
bbb... ......100 bbb.... bbb
ccccc. .......21 ccccc.. ccccc
dddddd ........3 dddddd. dddddd
ee.... ......411 ee..... ee
ffff.. .....5111
gggggg 678993321 gggggg. gggggg
hhh... ..7666666 hhh.... hhh

* cleanup up scols_table_enable_maxout() use, example:

$ LIBSMARTCOLS_DEBUG_PADDING=on ./sample-scols-fromfile --nlines 10 --maxout  --width 80 --column tests/ts/libsmartcols/files/col-name --column tests/ts/libsmartcols/files/col-number --column tests/ts/libsmartcols/files/col-string --column tests/ts/libsmartcols/files/col-string tests/ts/libsmartcols/files/data-string tests/ts/libsmartcols/files/data-number tests/ts/libsmartcols/files/data-string-empty tests/ts/libsmartcols/files/data-string-empty 2> /dev/null
NAME.............. ..................NUM STRINGS............ STRINGS............
aaaa.............. ....................0 aaaa............... aaaa...............
bbb............... ..................100 bbb................ bbb................
ccccc............. ...................21 ccccc.............. ccccc..............
dddddd............ ....................3 dddddd............. dddddd.............
ee................ ..................411 ee................. ee.................
ffff.............. .................5111 ................... ...................
gggggg............ ............678993321 gggggg............. gggggg.............
hhh............... ..............7666666 hhh................ hhh................

Note that we cannot make scols_table_enable_minout() default because
for example "column --table" is pretty commonly used with non-blank
columns separator and in this case all cells has to be filled.

$ echo -e "aa,b,ccc\na,,\naaa,bbb,ccc" |  column --table --separator ',' --output-separator '|'
aa |b  |ccc
a  |   |
aaa|bbb|ccc

Addresses: https://github.com/karelzak/util-linux/issues/826
Signed-off-by: Karel Zak <kzak@redhat.com>
libsmartcols/docs/libsmartcols-sections.txt
libsmartcols/samples/fromfile.c
libsmartcols/src/libsmartcols.h.in
libsmartcols/src/libsmartcols.sym
libsmartcols/src/print.c
libsmartcols/src/smartcolsP.h
libsmartcols/src/table.c
tests/expected/lsblk/lsblk-simple-lvm-vendor
tests/expected/lsblk/lsblk-simple-nvme-vendor

index 72c4ab866c367b91debdb94459092e662244fc27..4f3178b3ab7ea153a4c4b812c4e41eba32dedd72 100644 (file)
@@ -132,6 +132,7 @@ scols_table_enable_export
 scols_table_enable_header_repeat
 scols_table_enable_json
 scols_table_enable_maxout
+scols_table_enable_minout
 scols_table_enable_noheadings
 scols_table_enable_nolinesep
 scols_table_enable_nowrap
@@ -155,6 +156,7 @@ scols_table_is_export
 scols_table_is_header_repeat
 scols_table_is_json
 scols_table_is_maxout
+scols_table_is_minout
 scols_table_is_noheadings
 scols_table_is_noencoding
 scols_table_is_nolinesep
@@ -165,6 +167,7 @@ scols_table_move_column
 scols_table_new_column
 scols_table_new_line
 scols_table_next_column
+scols_table_set_columns_iter
 scols_table_next_line
 scols_table_reduce_termwidth
 scols_table_remove_column
index c1ab728fd65f419302adc05f77fbec9f5e42b392..35d85489b5b3782f2f557808fd5a45cccf906fa3 100644 (file)
@@ -151,7 +151,8 @@ static int parse_column_data(FILE *f, struct libscols_table *tb, int col)
                if (!ln)
                        break;
 
-               scols_line_set_data(ln, col, str);
+               if (str && *str)
+                       scols_line_set_data(ln, col, str);
        }
 
        free(str);
@@ -204,6 +205,7 @@ static void __attribute__((__noreturn__)) usage(void)
                "\n %s [options] <column-data-file> ...\n\n", program_invocation_short_name);
 
        fputs(" -m, --maxout                   fill all terminal width\n", out);
+       fputs(" -M, --minout                   minimize tailing padding\n", out);
        fputs(" -c, --column <file>            column definition\n", out);
        fputs(" -n, --nlines <num>             number of lines\n", out);
        fputs(" -J, --json                     JSON output format\n", out);
@@ -227,6 +229,7 @@ int main(int argc, char *argv[])
 
        static const struct option longopts[] = {
                { "maxout", 0, NULL, 'm' },
+               { "minout", 0, NULL, 'M' },
                { "column", 1, NULL, 'c' },
                { "nlines", 1, NULL, 'n' },
                { "width",  1, NULL, 'w' },
@@ -242,6 +245,7 @@ int main(int argc, char *argv[])
 
        static const ul_excl_t excl[] = {       /* rows and cols in ASCII order */
                { 'E', 'J', 'r' },
+               { 'M', 'm' },
                { 0 }
        };
        int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
@@ -253,7 +257,7 @@ int main(int argc, char *argv[])
        if (!tb)
                err(EXIT_FAILURE, "failed to create output table");
 
-       while((c = getopt_long(argc, argv, "hCc:Ei:Jmn:p:rw:", longopts, NULL)) != -1) {
+       while((c = getopt_long(argc, argv, "hCc:Ei:JMmn:p:rw:", longopts, NULL)) != -1) {
 
                err_exclusive_options(c, longopts, excl, excl_st);
 
@@ -285,6 +289,9 @@ int main(int argc, char *argv[])
                case 'm':
                        scols_table_enable_maxout(tb, TRUE);
                        break;
+               case 'M':
+                       scols_table_enable_minout(tb, TRUE);
+                       break;
                case 'r':
                        scols_table_enable_raw(tb, TRUE);
                        break;
index bd47f789844412d2dbe106a39101da5f52345c96..d4be9969a0c96ac3b570e35b1c8ad9a8e1d4a2af 100644 (file)
@@ -243,6 +243,7 @@ extern int scols_table_is_header_repeat(const struct libscols_table *tb);
 extern int scols_table_is_empty(const struct libscols_table *tb);
 extern int scols_table_is_export(const struct libscols_table *tb);
 extern int scols_table_is_maxout(const struct libscols_table *tb);
+extern int scols_table_is_minout(const struct libscols_table *tb);
 extern int scols_table_is_nowrap(const struct libscols_table *tb);
 extern int scols_table_is_nolinesep(const struct libscols_table *tb);
 extern int scols_table_is_tree(const struct libscols_table *tb);
@@ -256,6 +257,7 @@ extern int scols_table_enable_noheadings(struct libscols_table *tb, int enable);
 extern int scols_table_enable_header_repeat(struct libscols_table *tb, int enable);
 extern int scols_table_enable_export(struct libscols_table *tb, int enable);
 extern int scols_table_enable_maxout(struct libscols_table *tb, int enable);
+extern int scols_table_enable_minout(struct libscols_table *tb, int enable);
 extern int scols_table_enable_nowrap(struct libscols_table *tb, int enable);
 extern int scols_table_enable_nolinesep(struct libscols_table *tb, int enable);
 extern int scols_table_enable_noencoding(struct libscols_table *tb, int enable);
@@ -272,6 +274,7 @@ extern int scols_table_remove_columns(struct libscols_table *tb);
 extern int scols_table_move_column(struct libscols_table *tb, struct libscols_column *pre, struct libscols_column *cl);
 extern struct libscols_column *scols_table_new_column(struct libscols_table *tb, const char *name, double whint, int flags);
 extern int scols_table_next_column(struct libscols_table *tb, struct libscols_iter *itr, struct libscols_column **cl);
+extern int scols_table_set_columns_iter(struct libscols_table *tb, struct libscols_iter *itr, struct libscols_column *cl);
 extern const char *scols_table_get_column_separator(const struct libscols_table *tb);
 extern const char *scols_table_get_line_separator(const struct libscols_table *tb);
 extern size_t scols_table_get_ncols(const struct libscols_table *tb);
index e318c9054ed48863e3319ddd3148d9224f8e8eab..99353be807c2a8f32f0bbd636f2cc6637640b11d 100644 (file)
@@ -194,3 +194,9 @@ SMARTCOLS_2.34 {
        scols_symbols_set_group_last_child;
        scols_symbols_set_group_middle_child;
 } SMARTCOLS_2.33;
+
+SMARTCOLS_2.35 {
+       scols_table_enable_minout;
+       scols_table_is_minout;
+       scols_table_set_columns_iter;
+} SMARTCOLS_2.34;
index 986af153c50ee2ef6195e2ab1e1f9582f957abd4..c92154219295fc046220a1073ac3794f22252e3c 100644 (file)
 
 #define want_repeat_header(tb) (!(tb)->header_repeat || (tb)->header_next <= (tb)->termlines_used)
 
+static int is_next_columns_empty(
+                       struct libscols_table *tb,
+                       struct libscols_column *cl,
+                       struct libscols_line *ln)
+{
+       struct libscols_iter itr;
+
+       if (!tb || !cl)
+               return 0;
+       if (is_last_column(cl))
+               return 1;
+       if (!ln)
+               return 0;
+
+       scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
+       scols_table_set_columns_iter(tb, &itr, cl);
+
+       /* skip current column */
+       scols_table_next_column(tb, &itr, &cl);
+
+       while (scols_table_next_column(tb, &itr, &cl) == 0) {
+               struct libscols_cell *ce;
+               const char *data = NULL;
+
+                if (scols_column_is_hidden(cl))
+                        continue;
+               if (scols_column_is_tree(cl))
+                       return 0;
+
+               ce = scols_line_get_cell(ln, cl->seqnum);
+               if (ce)
+                       data = scols_cell_get_data(ce);
+               if (data && *data)
+                       return 0;
+       }
+       return 1;
+}
 
 /* returns pointer to the end of used data */
 static int tree_ascii_art_to_buffer(struct libscols_table *tb,
@@ -216,14 +253,20 @@ static void print_empty_cell(struct libscols_table *tb,
                }
        }
 
-       if (is_last_column(cl))
+       /* minout -- don't fill */
+       if (scols_table_is_minout(tb) && is_next_columns_empty(tb, cl, ln))
+               return;
+
+       /* default -- fill except last column */
+       if (!scols_table_is_maxout(tb) && is_last_column(cl))
                return;
 
        /* fill rest of cell with space */
        for(; len_pad < cl->width; ++len_pad)
                fputs(cellpadding_symbol(tb), tb->out);
 
-       fputs(colsep(tb), tb->out);
+       if (!is_last_column(cl))
+               fputs(colsep(tb), tb->out);
 }
 
 
@@ -367,13 +410,21 @@ static int print_pending_data(
                fputs(UL_COLOR_RESET, tb->out);
        free(data);
 
-       if (is_last_column(cl))
+       /* minout -- don't fill */
+       if (scols_table_is_minout(tb) && is_next_columns_empty(tb, cl, ln))
                return 0;
 
-       for (i = len; i < width; i++)
-               fputs(cellpadding_symbol(tb), tb->out);         /* padding */
+       /* default -- fill except last column */
+       if (!scols_table_is_maxout(tb) && is_last_column(cl))
+               return 0;
+
+       /* fill rest of cell with space */
+       for(i = len; i < width; i++)
+               fputs(cellpadding_symbol(tb), tb->out);
+
+       if (!is_last_column(cl))
+               fputs(colsep(tb), tb->out);
 
-       fputs(colsep(tb), tb->out);     /* columns separator */
        return 0;
 err:
        free(data);
@@ -491,7 +542,7 @@ static int print_data(struct libscols_table *tb,
                data = NULL;
        }
 
-       if (data) {
+       if (data && *data) {
                if (scols_column_is_right(cl)) {
                        if (color)
                                fputs(color, tb->out);
@@ -518,16 +569,24 @@ static int print_data(struct libscols_table *tb,
                } else
                        fputs(data, tb->out);
        }
-       for (i = len; i < width; i++)
-               fputs(cellpadding_symbol(tb), tb->out); /* padding */
 
-       if (is_last)
+       /* minout -- don't fill */
+       if (scols_table_is_minout(tb) && is_next_columns_empty(tb, cl, ln))
                return 0;
 
+       /* default -- fill except last column */
+       if (!scols_table_is_maxout(tb) && is_last)
+               return 0;
+
+       /* fill rest of cell with space */
+       for(i = len; i < width; i++)
+               fputs(cellpadding_symbol(tb), tb->out);
+
        if (len > width && !scols_column_is_trunc(cl)) {
                DBG(COL, ul_debugobj(cl, "*** data len=%zu > column width=%zu", len, width));
                print_newline_padding(tb, cl, ln, buffer_get_size(buf));        /* next column starts on next line */
-       } else
+
+       } else if (!is_last)
                fputs(colsep(tb), tb->out);             /* columns separator */
 
        return 0;
index 3653eda0704e1fb73390f3f5bdfd62c5589324b4..e745a05a48cea22ee57c893f27130a69c1e32370 100644 (file)
@@ -238,6 +238,7 @@ struct libscols_table {
                        padding_debug   :1,     /* output visible padding chars */
                        is_dummy_print  :1,     /* printing used for width calcualion only */
                        maxout          :1,     /* maximize output */
+                       minout          :1,     /* minimize output (mutually exclusive to maxout) */
                        header_repeat   :1,     /* print header after libscols_table->termheight */
                        header_printed  :1,     /* header already printed */
                        priv_symbols    :1,     /* default private symbols */
index 944c1e593bfd5fdf08971f19b68e90fe7f577891..e14c82b1b8c3649b4ad01785fb93235bdb2dc7b9 100644 (file)
@@ -474,6 +474,33 @@ int scols_table_next_column(struct libscols_table *tb,
        return rc;
 }
 
+/**
+ * scols_table_set_columns_iter:
+ * @tb: tab pointer
+ * @itr: iterator
+ * @cl: tab entry
+ *
+ * Sets @iter to the position of @cl in the file @tb.
+ *
+ * Returns: 0 on success, negative number in case of error.
+ */
+int scols_table_set_columns_iter(
+                       struct libscols_table *tb,
+                       struct libscols_iter *itr,
+                       struct libscols_column *cl)
+{
+       if (!tb || !itr || !cl)
+               return -EINVAL;
+
+       if (cl->table != tb)
+               return -EINVAL;
+
+       SCOLS_ITER_INIT(itr, &tb->tb_columns);
+       itr->p = &cl->cl_columns;
+
+       return 0;
+}
+
 /**
  * scols_table_get_ncols:
  * @tb: table
@@ -1133,19 +1160,45 @@ int scols_table_enable_header_repeat(struct libscols_table *tb, int enable)
  * @enable: 1 or 0
  *
  * The extra space after last column is ignored by default. The output
- * maximization use the extra space for all columns.
+ * maximization add padding for all columns.
+ *
+ * This setting is mutually exclusive to cols_table_enable_minout().
  *
  * Returns: 0 on success, negative number in case of an error.
  */
 int scols_table_enable_maxout(struct libscols_table *tb, int enable)
 {
-       if (!tb)
+       if (!tb || tb->minout)
                return -EINVAL;
+
        DBG(TAB, ul_debugobj(tb, "maxout: %s", enable ? "ENABLE" : "DISABLE"));
        tb->maxout = enable ? 1 : 0;
        return 0;
 }
 
+/**
+ * scols_table_enable_minout:
+ * @tb: table
+ * @enable: 1 or 0
+ *
+ * Force library to terminate line after last column with data. The extra
+ * padding is not added to the empty cells at the end of the line. The default is fill
+ * tailing empty cells except the last line cell.
+ *
+ * This setting is mutually exclusive to cols_table_enable_maxout().
+ *
+ * Returns: 0 on success, negative number in case of an error.
+ */
+int scols_table_enable_minout(struct libscols_table *tb, int enable)
+{
+       if (!tb || tb->maxout)
+               return -EINVAL;
+
+       DBG(TAB, ul_debugobj(tb, "minout: %s", enable ? "ENABLE" : "DISABLE"));
+       tb->minout = enable ? 1 : 0;
+       return 0;
+}
+
 /**
  * scols_table_enable_nowrap:
  * @tb: table
@@ -1315,6 +1368,17 @@ int scols_table_is_maxout(const struct libscols_table *tb)
        return tb->maxout;
 }
 
+/**
+ * scols_table_is_minout
+ * @tb: table
+ *
+ * Returns: 1 if output minimization is enabled or 0
+ */
+int scols_table_is_minout(const struct libscols_table *tb)
+{
+       return tb->minout;
+}
+
 /**
  * scols_table_is_tree:
  * @tb: table
index 591c703af278599faf23e239ab35026110fc5d50..24ee97dd4cd785af9385fedaef623450fbcdaea4 100644 (file)
@@ -1,22 +1,22 @@
 NAME                      MODEL                                    VENDOR    REV
-loop0                                                                           
-`-vg_foo.4059-lv_foo.4059                                                       
-loop1                                                                           
-`-vg_foo.4059-lv_foo.4059                                                       
-loop2                                                                           
-`-vg_foo.4059-lv_foo.4059                                                       
-loop3                                                                           
-`-vg_foo.4059-lv_foo.4059                                                       
+loop0                                                                       
+`-vg_foo.4059-lv_foo.4059                                                   
+loop1                                                                       
+`-vg_foo.4059-lv_foo.4059                                                   
+loop2                                                                       
+`-vg_foo.4059-lv_foo.4059                                                   
+loop3                                                                       
+`-vg_foo.4059-lv_foo.4059                                                   
 sda                       KINGSTON SH103S3                         ATA      BBF0
-|-sda1                                                                          
-|-sda2                                                                          
-|-sda3                                                                          
-|-sda4                                                                          
-|-sda5                                                                          
-`-sda6                                                                          
+|-sda1                                                                      
+|-sda2                                                                      
+|-sda3                                                                      
+|-sda4                                                                      
+|-sda5                                                                      
+`-sda6                                                                      
 sdb                       WDC WD800JD-00MS                         ATA      1E01
-`-sdb1                                                                          
-nvme0n1                   KINGSTON SKC1000240G                                  
-|-nvme0n1p1                                                                     
-|-nvme0n1p2                                                                     
-`-nvme0n1p3                                                                     
+`-sdb1                                                                      
+nvme0n1                   KINGSTON SKC1000240G                              
+|-nvme0n1p1                                                                 
+|-nvme0n1p2                                                                 
+`-nvme0n1p3                                                                 
index 69e972a31cbf9708013a81c4550297e7414eebb3..2a0a90514eb5bc3c6105583e8f14b385d38c4972 100644 (file)
@@ -1,14 +1,14 @@
 NAME        MODEL                                    VENDOR    REV
 sda         KINGSTON SH103S3                         ATA      BBF0
-|-sda1                                                            
-|-sda2                                                            
-|-sda3                                                            
-|-sda4                                                            
-|-sda5                                                            
-`-sda6                                                            
+|-sda1                                                        
+|-sda2                                                        
+|-sda3                                                        
+|-sda4                                                        
+|-sda5                                                        
+`-sda6                                                        
 sdb         WDC WD800JD-00MS                         ATA      1E01
-`-sdb1                                                            
-nvme0n1     KINGSTON SKC1000240G                                  
-|-nvme0n1p1                                                       
-|-nvme0n1p2                                                       
-`-nvme0n1p3                                                       
+`-sdb1                                                        
+nvme0n1     KINGSTON SKC1000240G                              
+|-nvme0n1p1                                                   
+|-nvme0n1p2                                                   
+`-nvme0n1p3