diff options
-rw-r--r-- | libsmartcols/docs/libsmartcols-sections.txt | 3 | ||||
-rw-r--r-- | libsmartcols/samples/fromfile.c | 11 | ||||
-rw-r--r-- | libsmartcols/src/libsmartcols.h.in | 3 | ||||
-rw-r--r-- | libsmartcols/src/libsmartcols.sym | 6 | ||||
-rw-r--r-- | libsmartcols/src/print.c | 81 | ||||
-rw-r--r-- | libsmartcols/src/smartcolsP.h | 1 | ||||
-rw-r--r-- | libsmartcols/src/table.c | 68 | ||||
-rw-r--r-- | tests/expected/lsblk/lsblk-simple-lvm-vendor | 38 | ||||
-rw-r--r-- | tests/expected/lsblk/lsblk-simple-nvme-vendor | 22 |
9 files changed, 188 insertions, 45 deletions
diff --git a/libsmartcols/docs/libsmartcols-sections.txt b/libsmartcols/docs/libsmartcols-sections.txt index 72c4ab866..4f3178b3a 100644 --- a/libsmartcols/docs/libsmartcols-sections.txt +++ b/libsmartcols/docs/libsmartcols-sections.txt @@ -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 diff --git a/libsmartcols/samples/fromfile.c b/libsmartcols/samples/fromfile.c index c1ab728fd..35d85489b 100644 --- a/libsmartcols/samples/fromfile.c +++ b/libsmartcols/samples/fromfile.c @@ -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; diff --git a/libsmartcols/src/libsmartcols.h.in b/libsmartcols/src/libsmartcols.h.in index bd47f7898..d4be9969a 100644 --- a/libsmartcols/src/libsmartcols.h.in +++ b/libsmartcols/src/libsmartcols.h.in @@ -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); diff --git a/libsmartcols/src/libsmartcols.sym b/libsmartcols/src/libsmartcols.sym index e318c9054..99353be80 100644 --- a/libsmartcols/src/libsmartcols.sym +++ b/libsmartcols/src/libsmartcols.sym @@ -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; diff --git a/libsmartcols/src/print.c b/libsmartcols/src/print.c index 986af153c..c92154219 100644 --- a/libsmartcols/src/print.c +++ b/libsmartcols/src/print.c @@ -50,6 +50,43 @@ #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; diff --git a/libsmartcols/src/smartcolsP.h b/libsmartcols/src/smartcolsP.h index 3653eda07..e745a05a4 100644 --- a/libsmartcols/src/smartcolsP.h +++ b/libsmartcols/src/smartcolsP.h @@ -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 */ diff --git a/libsmartcols/src/table.c b/libsmartcols/src/table.c index 944c1e593..e14c82b1b 100644 --- a/libsmartcols/src/table.c +++ b/libsmartcols/src/table.c @@ -475,6 +475,33 @@ int scols_table_next_column(struct libscols_table *tb, } /** + * 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,20 +1160,46 @@ 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 * @enable: 1 or 0 @@ -1316,6 +1369,17 @@ int scols_table_is_maxout(const struct libscols_table *tb) } /** + * 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 * diff --git a/tests/expected/lsblk/lsblk-simple-lvm-vendor b/tests/expected/lsblk/lsblk-simple-lvm-vendor index 591c703af..24ee97dd4 100644 --- a/tests/expected/lsblk/lsblk-simple-lvm-vendor +++ b/tests/expected/lsblk/lsblk-simple-lvm-vendor @@ -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 diff --git a/tests/expected/lsblk/lsblk-simple-nvme-vendor b/tests/expected/lsblk/lsblk-simple-nvme-vendor index 69e972a31..2a0a90514 100644 --- a/tests/expected/lsblk/lsblk-simple-nvme-vendor +++ b/tests/expected/lsblk/lsblk-simple-nvme-vendor @@ -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 |