summaryrefslogtreecommitdiffstats
path: root/libsmartcols
diff options
context:
space:
mode:
authorKarel Zak2017-04-07 13:40:14 +0200
committerKarel Zak2017-04-07 14:34:11 +0200
commitf691831481a28d7d902524d650cd76e28ac939f9 (patch)
tree62d8fa6bad2d97583a6cda8ad7b0fc080a19070f /libsmartcols
parentlibsmartcols: add scols_line_move_cells() (diff)
downloadkernel-qcow2-util-linux-f691831481a28d7d902524d650cd76e28ac939f9.tar.gz
kernel-qcow2-util-linux-f691831481a28d7d902524d650cd76e28ac939f9.tar.xz
kernel-qcow2-util-linux-f691831481a28d7d902524d650cd76e28ac939f9.zip
libsmartcols: column width reduction refactoring
The current implementation is unreadable... Let's write it again with more obvious semantic. Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libsmartcols')
-rw-r--r--libsmartcols/src/table.c17
-rw-r--r--libsmartcols/src/table_print.c95
2 files changed, 80 insertions, 32 deletions
diff --git a/libsmartcols/src/table.c b/libsmartcols/src/table.c
index 3672114b2..066a1e9a7 100644
--- a/libsmartcols/src/table.c
+++ b/libsmartcols/src/table.c
@@ -326,6 +326,23 @@ int scols_table_move_column(struct libscols_table *tb,
* relative width is used as a hint only. It's possible that column will be
* narrow if the specified size is too large for column data.
*
+ *
+ * If the width of all columns is greater than terminal width then library
+ * tries to reduce width of the individual columns. It's done in three stages:
+ *
+ * #1 reduce columns with SCOLS_FL_TRUNC flag and with relative width if the
+ * width is greater than width defined by @whint (@whint * terminal_width)
+ *
+ * #2 reduce all columns with SCOLS_FL_TRUNC flag
+ *
+ * #3 reduce all columns with relative width
+ *
+ * The next stage is always used if the previous stage is unsuccessful. Note
+ * that SCOLS_FL_WRAP is interpreted as SCOLS_FL_TRUNC when calculate column
+ * width (if custom wrap function is not specified), but the final text is not
+ * truncated, but wrapped to multi-line cell.
+ *
+ *
* The column is necessary to address by sequential number. The first defined
* column has the colnum = 0. For example:
*
diff --git a/libsmartcols/src/table_print.c b/libsmartcols/src/table_print.c
index 1fe700273..6b4b727c0 100644
--- a/libsmartcols/src/table_print.c
+++ b/libsmartcols/src/table_print.c
@@ -1090,7 +1090,7 @@ static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf
struct libscols_column *cl;
struct libscols_iter itr;
size_t width = 0, width_min = 0; /* output width */
- int trunc_only, rc = 0;
+ int stage, rc = 0;
int extremes = 0;
size_t colsepsz;
@@ -1220,60 +1220,91 @@ static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf
}
}
- /* bad, we have to reduce output width, this is done in two steps:
- * 1) reduce columns with a relative width and with truncate flag
- * 2) reduce columns with a relative width without truncate flag
+ /* bad, we have to reduce output width, this is done in three stages:
+ *
+ * 1) trunc relative with trunc flag if the column width is greater than
+ * expected column width (it means "width_hint * terminal_width").
+ *
+ * 2) trunc all with trunc flag
+ *
+ * 3) trunc relative without trunc flag
+ *
+ * Note that SCOLS_FL_WRAP (if no custom wrap function is specified) is
+ * interpreted as SCOLS_FL_TRUNC.
*/
- trunc_only = 1;
- while (width > tb->termwidth) {
- size_t org = width;
+ for (stage = 1; width > tb->termwidth && stage <= 3; ) {
+ size_t org_width = width;
- DBG(TAB, ul_debugobj(tb, " reduce width (current=%zu, "
- "wanted=%zu, mode=%s)",
- width, tb->termwidth,
- trunc_only ? "trunc-only" : "all-relative"));
+ DBG(TAB, ul_debugobj(tb, " reduce width - #%d stage (current=%zu, wanted=%zu)",
+ stage, width, tb->termwidth));
scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
while (scols_table_next_column(tb, &itr, &cl) == 0) {
- DBG(TAB, ul_debugobj(cl, " checking %s (width=%zu, treeart=%zu)",
+ int trunc_flag = 0;
+
+ DBG(TAB, ul_debugobj(cl, " checking %s (width=%zu, treeart=%zu)",
cl->header.data, cl->width, cl->width_treeart));
if (scols_column_is_hidden(cl))
continue;
if (width <= tb->termwidth)
break;
- if (cl->width_hint > 1 && !scols_column_is_trunc(cl))
- continue; /* never truncate columns with absolute sizes */
+
+ /* never truncate if already minimal width */
+ if (cl->width == cl->width_min)
+ continue;
+
+ /* never truncate the tree */
if (scols_column_is_tree(cl) && width <= cl->width_treeart)
- continue; /* never truncate the tree */
- if (trunc_only && !(scols_column_is_trunc(cl) ||
- (scols_column_is_wrap(cl) && !scols_column_is_customwrap(cl))))
continue;
- if (cl->width == cl->width_min)
+
+ /* nothing to truncate */
+ if (cl->width == 0 || width == 0)
continue;
- DBG(TAB, ul_debugobj(tb, " trying to reduce: %s (width=%zu)", cl->header.data, cl->width));
+ trunc_flag = scols_column_is_trunc(cl)
+ || (scols_column_is_wrap(cl) && !scols_column_is_customwrap(cl));
- /* truncate column with relative sizes */
- if (cl->width_hint < 1 && cl->width > 0 && width > 0 &&
- cl->width >= (size_t) (cl->width_hint * tb->termwidth)) {
+ switch (stage) {
+ /* #1 stage - trunc relative with TRUNC flag */
+ case 1:
+ if (!trunc_flag) /* ignore: missing flag */
+ break;
+ if (cl->width_hint >= 1) /* ignore: no relative */
+ break;
+ if (cl->width < (size_t) (cl->width_hint * tb->termwidth)) /* ignore: smaller than expected width */
+ break;
+
+ DBG(TAB, ul_debugobj(tb, " reducing (relative with flag)"));
cl->width--;
width--;
- }
+ break;
- /* truncate column with absolute size */
- if (cl->width_hint > 1 && cl->width > 0 && width > 0 &&
- !trunc_only) {
+ /* #2 stage - trunc all with TRUNC flag */
+ case 2:
+ if (!trunc_flag) /* ignore: missing flag */
+ break;
+
+ DBG(TAB, ul_debugobj(tb, " reducing (all with flag)"));
cl->width--;
width--;
- }
- }
- if (org == width) {
- if (trunc_only)
- trunc_only = 0;
- else
break;
+
+ /* #3 stage - trunc relative without flag */
+ case 3:
+ if (cl->width_hint >= 1) /* ignore: no relative */
+ break;
+
+ DBG(TAB, ul_debugobj(tb, " reducing (relative without flag)"));
+ cl->width--;
+ width--;
+ break;
+ }
}
+
+ /* the current stage is without effect, go to the next */
+ if (org_width == width)
+ stage++;
}
/* ignore last column(s) or force last column to be truncated if