]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libsmartcols: fix relative column width for maxout
authorKarel Zak <kzak@redhat.com>
Wed, 24 Feb 2016 11:34:37 +0000 (12:34 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 24 Feb 2016 11:34:37 +0000 (12:34 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libsmartcols/samples/continuous.c
libsmartcols/src/column.c
libsmartcols/src/table.c
libsmartcols/src/table_print.c

index 2fe720e2f852d69807c1925709401f1cc4c2dbce..02efd5de92ca4a4884dfe1977ba9fa130b56106d 100644 (file)
@@ -30,11 +30,12 @@ static double time_diff(struct timeval *a, struct timeval *b)
 /* add columns to the @tb */
 static void setup_columns(struct libscols_table *tb)
 {
-       if (!scols_table_new_column(tb, "#NUM", 0, SCOLS_FL_RIGHT))
+       scols_table_enable_maxout(tb, 1);
+       if (!scols_table_new_column(tb, "#NUM", 0.1, SCOLS_FL_RIGHT))
                goto fail;
-       if (!scols_table_new_column(tb, "DATA", 0, 0))
+       if (!scols_table_new_column(tb, "DATA", 0.7, 0))
                goto fail;
-       if (!scols_table_new_column(tb, "TIME", 0, 0))
+       if (!scols_table_new_column(tb, "TIME", 0.2, 0))
                goto fail;
        return;
 fail:
index 55c24da2215dad8773ca6607f35e4de67c3ea909..5e7050192853d2f149e60d2a343261f7ebe3ee9b 100644 (file)
@@ -119,7 +119,7 @@ err:
  * @cl: a pointer to a struct libscols_column instance
  * @whint: a width hint
  *
- * Sets the width hint of column @cl to @whint.
+ * Sets the width hint of column @cl to @whint. See scols_table_new_column().
  *
  * Returns: 0, a negative value in case of an error.
  */
index cc19e4ab20f17f9d2fcf420c8f9e63b6086a796c..d4261c06769ddfa4bffc9fbb709a15afb83be3a4 100644 (file)
@@ -233,17 +233,19 @@ int scols_table_remove_columns(struct libscols_table *tb)
  *   scols_column_set_....(cl, ...);
  *   scols_table_add_column(tb, cl);
  *
- * The column width is possible to define by three ways:
+ * The column width is possible to define by:
  *
  *  @whint = 0..1    : relative width, percent of terminal width
  *
  *  @whint = 1..N    : absolute width, empty column will be truncated to
- *                     the column header width
+ *                     the column header width if no specified STRICTWIDTH flag
  *
- *  @whint = 1..N
+ * Note that if table has disabled "maxout" flag (disabled by default) than
+ * 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.
  *
- * The column is necessary to address by
- * sequential number. The first defined column has the colnum = 0. For example:
+ * The column is necessary to address by sequential number. The first defined
+ * column has the colnum = 0. For example:
  *
  *     scols_table_new_column(tab, "FOO", 0.5, 0);             // colnum = 0
  *     scols_table_new_column(tab, "BAR", 0.5, 0);             // colnum = 1
index d6622be64ec40c8c2b69891338a1bd79cad2ce7d..e37f27761edcbcae01eb94b84d0fdba836d80de1 100644 (file)
@@ -177,9 +177,9 @@ static int line_ascii_art_to_buffer(struct libscols_table *tb,
        return buffer_append_data(buf, art);
 }
 
-static int is_last_column(struct libscols_table *tb, struct libscols_column *cl) 
+static int is_last_column(struct libscols_column *cl)
 {
-       int rc = list_entry_is_last(&cl->cl_columns, &tb->tb_columns);
+       int rc = list_entry_is_last(&cl->cl_columns, &cl->table->tb_columns);
        struct libscols_column *next;
 
        if (rc)
@@ -378,7 +378,7 @@ static int print_pending_data(
        for (i = len; i < width; i++)
                fputc(' ', tb->out);            /* padding */
 
-       if (is_last_column(tb, cl))
+       if (is_last_column(cl))
                return 0;
 
        fputs(colsep(tb), tb->out);             /* columns separator */
@@ -412,14 +412,14 @@ static int print_data(struct libscols_table *tb,
        switch (tb->format) {
        case SCOLS_FMT_RAW:
                fputs_nonblank(data, tb->out);
-               if (!is_last_column(tb, cl))
+               if (!is_last_column(cl))
                        fputs(colsep(tb), tb->out);
                return 0;
 
        case SCOLS_FMT_EXPORT:
                fprintf(tb->out, "%s=", scols_cell_get_data(&cl->header));
                fputs_quoted(data, tb->out);
-               if (!is_last_column(tb, cl))
+               if (!is_last_column(cl))
                        fputs(colsep(tb), tb->out);
                return 0;
 
@@ -430,7 +430,7 @@ static int print_data(struct libscols_table *tb,
                        fputs("null", tb->out);
                else
                        fputs_quoted(data, tb->out);
-               if (!is_last_column(tb, cl))
+               if (!is_last_column(cl))
                        fputs(", ", tb->out);
                return 0;
 
@@ -447,7 +447,7 @@ static int print_data(struct libscols_table *tb,
        width = cl->width;
        bytes = strlen(data);
 
-       if (is_last_column(tb, cl)
+       if (is_last_column(cl)
            && len < width
            && !scols_table_is_maxout(tb)
            && !scols_column_is_right(cl)
@@ -505,7 +505,7 @@ static int print_data(struct libscols_table *tb,
        for (i = len; i < width; i++)
                fputc(' ', tb->out);            /* padding */
 
-       if (is_last_column(tb, cl))
+       if (is_last_column(cl))
                return 0;
 
        if (len > width && !scols_column_is_trunc(cl))
@@ -957,6 +957,16 @@ static int count_column_width(struct libscols_table *tb,
 
        cl->width = 0;
 
+
+       if (cl->width_min) {
+               if (cl->width_hint < 1 && scols_table_is_maxout(tb))
+                       cl->width_min = (size_t) (cl->width_hint * tb->termwidth) - (is_last_column(cl) ? 0 : 1);
+               if (scols_cell_get_data(&cl->header)) {
+                       size_t len = mbs_safe_width(scols_cell_get_data(&cl->header));
+                       cl->width_min = max(cl->width_min, len);
+               }
+       }
+
        scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
        while (scols_table_next_line(tb, &itr, &ln) == 0) {
                size_t len;
@@ -988,20 +998,15 @@ static int count_column_width(struct libscols_table *tb,
 
        if (count && cl->width_avg == 0) {
                cl->width_avg = sum / count;
-
                if (cl->width_max > cl->width_avg * 2)
                        cl->is_extreme = 1;
        }
 
-       /* check and set minimal column width */
-       if (scols_cell_get_data(&cl->header))
-               cl->width_min = mbs_safe_width(scols_cell_get_data(&cl->header));
-
        /* enlarge to minimal width */
        if (cl->width < cl->width_min && !scols_column_is_strict_width(cl))
                cl->width = cl->width_min;
 
-       /* use relative size for large columns */
+       /* use absolute size for large columns */
        else if (cl->width_hint >= 1 && cl->width < (size_t) cl->width_hint
                 && cl->width_min < (size_t) cl->width_hint)
 
@@ -1009,7 +1014,6 @@ static int count_column_width(struct libscols_table *tb,
 
 done:
        ON_DBG(COL, dbg_column(tb, cl));
-       DBG(COL, ul_debugobj(cl, "column width=%zu, rc=%d", cl->width, rc));
        return rc;
 }
 
@@ -1020,7 +1024,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;               /* output width */
+       size_t width = 0, width_min = 0;        /* output width */
        int trunc_only, rc = 0;
        int extremes = 0;
 
@@ -1035,18 +1039,32 @@ static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf
                if (rc)
                        goto done;
 
-               width += cl->width + (is_last_column(tb, cl) ? 0 : 1);  /* separator for non-last column */
+               width += cl->width + (is_last_column(cl) ? 0 : 1);              /* separator for non-last column */
+               width_min += cl->width_min + (is_last_column(cl) ? 0 : 1);
                extremes += cl->is_extreme;
        }
 
        if (!tb->is_term) {
-               DBG(TAB, ul_debugobj(tb, "   non-terminal output"));
+               DBG(TAB, ul_debugobj(tb, " non-terminal output"));
                goto done;
        }
 
+       /* be paranoid */
+       if (width_min > tb->termwidth && scols_table_is_maxout(tb)) {
+               DBG(TAB, ul_debugobj(tb, " min width larger than terminal! [width=%zu, term=%zu]", width_min, tb->termwidth));
+
+               scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
+               while (width_min > tb->termwidth
+                      && scols_table_next_column(tb, &itr, &cl) == 0) {
+                       width_min--;
+                       cl->width_min--;
+               }
+               DBG(TAB, ul_debugobj(tb, " min width reduced to %zu", width_min));
+       }
+
        /* reduce columns with extreme fields */
        if (width > tb->termwidth && extremes) {
-               DBG(TAB, ul_debugobj(tb, "   reduce width (extreme columns)"));
+               DBG(TAB, ul_debugobj(tb, " reduce width (extreme columns)"));
 
                scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
                while (scols_table_next_column(tb, &itr, &cl) == 0) {
@@ -1069,7 +1087,7 @@ static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf
 
        if (width < tb->termwidth) {
                if (extremes) {
-                       DBG(TAB, ul_debugobj(tb, "   enlarge width (extreme columns)"));
+                       DBG(TAB, ul_debugobj(tb, " enlarge width (extreme columns)"));
 
                        /* enlarge the first extreme column */
                        scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
@@ -1098,7 +1116,7 @@ static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf
                }
 
                if (width < tb->termwidth && scols_table_is_maxout(tb)) {
-                       DBG(TAB, ul_debugobj(tb, "   enlarge width (max-out)"));
+                       DBG(TAB, ul_debugobj(tb, " enlarge width (max-out)"));
 
                        /* try enlarging all columns */
                        while (width < tb->termwidth) {
@@ -1115,7 +1133,7 @@ static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf
                        struct libscols_column *col = list_entry(
                                tb->tb_columns.prev, struct libscols_column, cl_columns);
 
-                       DBG(TAB, ul_debugobj(tb, "   enlarge width (last column)"));
+                       DBG(TAB, ul_debugobj(tb, " enlarge width (last column)"));
 
                        if (!scols_column_is_right(col) && tb->termwidth - width > 0) {
                                col->width += tb->termwidth - width;
@@ -1132,7 +1150,7 @@ static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf
        while (width > tb->termwidth) {
                size_t org = width;
 
-               DBG(TAB, ul_debugobj(tb, "   reduce width (current=%zu, "
+               DBG(TAB, ul_debugobj(tb, " reduce width (current=%zu, "
                                         "wanted=%zu, mode=%s)",
                                        width, tb->termwidth,
                                        trunc_only ? "trunc-only" : "all-relative"));
@@ -1140,7 +1158,7 @@ static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf
                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)",
+                       DBG(TAB, ul_debugobj(cl, "  checking %s (width=%zu, treeart=%zu)",
                                                cl->header.data, cl->width, cl->width_treeart));
 
                        if (width <= tb->termwidth)
@@ -1154,7 +1172,7 @@ static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf
                        if (cl->width == cl->width_min)
                                continue;
 
-                       DBG(TAB, ul_debugobj(tb, "     tring to reduce: %s (width=%zu)", cl->header.data, cl->width));
+                       DBG(TAB, ul_debugobj(tb, "  tring to reduce: %s (width=%zu)", cl->header.data, cl->width));
 
                        /* truncate column with relative sizes */
                        if (cl->width_hint < 1 && cl->width > 0 && width > 0 &&
@@ -1199,7 +1217,7 @@ static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf
                }
        }
 done:
-       DBG(TAB, ul_debugobj(tb, "  final width: %zu (rc=%d)", width, rc));
+       DBG(TAB, ul_debugobj(tb, " final width: %zu (rc=%d)", width, rc));
        ON_DBG(TAB, dbg_columns(tb));
 
        return rc;