summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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