summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2019-07-23 16:04:51 +0200
committerKarel Zak2019-07-23 16:24:42 +0200
commit94dbb322737524027a55e6ed5646dc69c5ed9e5b (patch)
treed4b325c8890240f984805abce6ace03fc16a2043
parentlibfdisk: improve partition copy on resize (diff)
downloadkernel-qcow2-util-linux-94dbb322737524027a55e6ed5646dc69c5ed9e5b.tar.gz
kernel-qcow2-util-linux-94dbb322737524027a55e6ed5646dc69c5ed9e5b.tar.xz
kernel-qcow2-util-linux-94dbb322737524027a55e6ed5646dc69c5ed9e5b.zip
libsmartcols: cleanup and extend padding functionality
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>
-rw-r--r--libsmartcols/docs/libsmartcols-sections.txt3
-rw-r--r--libsmartcols/samples/fromfile.c11
-rw-r--r--libsmartcols/src/libsmartcols.h.in3
-rw-r--r--libsmartcols/src/libsmartcols.sym6
-rw-r--r--libsmartcols/src/print.c81
-rw-r--r--libsmartcols/src/smartcolsP.h1
-rw-r--r--libsmartcols/src/table.c68
-rw-r--r--tests/expected/lsblk/lsblk-simple-lvm-vendor38
-rw-r--r--tests/expected/lsblk/lsblk-simple-nvme-vendor22
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