]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libsmartcols: use ASCII art for trees rather than padding
authorKarel Zak <kzak@redhat.com>
Wed, 7 Jan 2015 14:20:22 +0000 (15:20 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 7 Jan 2015 14:20:22 +0000 (15:20 +0100)
Based on patch from  Roman Odaisky.

References: https://launchpad.net/bugs/1406133
Signed-off-by: Karel Zak <kzak@redhat.com>
libsmartcols/src/table_print.c

index 542d8a22d7c4934adc1fa5c46e46a9a9b4c1bc95..ddbd12d3f77eb730b8da9297b61953cf23940de4 100644 (file)
@@ -151,12 +151,103 @@ static size_t buffer_get_safe_art_size(struct libscols_buffer *buf)
        return bytes;
 }
 
+/* returns pointer to the end of used data */
+static int line_ascii_art_to_buffer(struct libscols_table *tb,
+                                   struct libscols_line *ln,
+                                   struct libscols_buffer *buf)
+{
+       const char *art;
+       int rc;
+
+       assert(ln);
+       assert(buf);
+
+       if (!ln->parent)
+               return 0;
+
+       rc = line_ascii_art_to_buffer(tb, ln->parent, buf);
+       if (rc)
+               return rc;
+
+       if (list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch))
+               art = "  ";
+       else
+               art = tb->symbols->vert;
+
+       return buffer_append_data(buf, art);
+}
+
 #define is_last_column(_tb, _cl) \
                list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns)
 
 #define colsep(tb) ((tb)->colsep ? (tb)->colsep : " ")
 #define linesep(tb) ((tb)->linesep ? (tb)->linesep : "\n")
 
+/* print padding or asci-art instead of data of @cl */
+static void print_empty_cell(struct libscols_table *tb,
+                         struct libscols_column *cl,
+                         struct libscols_line *ln,     /* optional */
+                         size_t bufsz)
+{
+       size_t len_pad = 0;             /* in screen cells as opposed to bytes */
+
+       /* generate tree asci-art rather than padding */
+       if (ln && scols_column_is_tree(cl)) {
+               if (!ln->parent) {
+                       /* only print symbols->vert if followed by something */
+                       if (!list_empty(&ln->ln_branch)) {
+                               fputs(tb->symbols->vert, tb->out);
+                               len_pad = mbs_safe_width(tb->symbols->vert);
+                       }
+               } else {
+                       /* use the same draw function as though we were intending to draw an L-shape */
+                       struct libscols_buffer *art = new_buffer(bufsz);
+                       char *data;
+
+                       if (art) {
+                               /* whatever the rc, len_pad will be sensible */
+                               line_ascii_art_to_buffer(tb, ln, art);
+                               data = buffer_get_safe_data(art, &len_pad);
+                               if (data && len_pad)
+                                       fputs(data, tb->out);
+                               free_buffer(art);
+                       }
+               }
+       }
+       /* fill rest of cell with space */
+       for(; len_pad <= cl->width; ++len_pad)
+               fputc(' ', tb->out);
+}
+
+/* fill-in all line with padding (or tree asci-art)
+ *
+ * This is necessary after long non-truncated colum where next column
+ * is printed in next line. For example (see 'DDD'):
+ *
+ * aaa bbb ccc ddd eee
+ * AAA BBB CCCCCCC
+ *             DDD EEE
+ * ^^^^^^^^^^^^
+ *  new line padding
+ */
+static void print_newline_padding(struct libscols_table *tb,
+                                 struct libscols_column *cl,
+                                 struct libscols_line *ln,     /* optional */
+                                 size_t bufsz,
+                                 size_t len)
+{
+       size_t i;
+
+       assert(tb);
+       assert(cl);
+
+       fputs(linesep(tb), tb->out);            /* line break */
+
+       /* fill cells after line break */
+       for (i = 0; i <= (size_t) cl->seqnum; i++)
+               print_empty_cell(tb, scols_table_get_column(tb, i), ln, bufsz);
+}
+
 static int print_data(struct libscols_table *tb,
                      struct libscols_column *cl,
                      struct libscols_line *ln, /* optional */
@@ -252,46 +343,17 @@ static int print_data(struct libscols_table *tb,
                        fputs(data, tb->out);
        }
        for (i = len; i < width; i++)
-               fputs(" ", tb->out);            /* padding */
-
-       if (!is_last_column(tb, cl)) {
-               if (len > width && !scols_column_is_trunc(cl)) {
-                       fputs(linesep(tb), tb->out);
-                       for (i = 0; i <= (size_t) cl->seqnum; i++) {
-                               struct libscols_column *x = scols_table_get_column(tb, i);
-                               fprintf(tb->out, "%*s ", -((int)x->width), " ");
-                       }
-               } else
-                       fputs(colsep(tb), tb->out);     /* columns separator */
-       }
-
-       return 0;
-}
-
-/* returns pointer to the end of used data */
-static int line_ascii_art_to_buffer(struct libscols_table *tb,
-                                   struct libscols_line *ln,
-                                   struct libscols_buffer *buf)
-{
-       const char *art;
-       int rc;
+               fputc(' ', tb->out);            /* padding */
 
-       assert(ln);
-       assert(buf);
-
-       if (!ln->parent)
+       if (is_last_column(tb, cl))
                return 0;
 
-       rc = line_ascii_art_to_buffer(tb, ln->parent, buf);
-       if (rc)
-               return rc;
-
-       if (list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch))
-               art = "  ";
+       if (len > width && !scols_column_is_trunc(cl))
+               print_newline_padding(tb, cl, ln, buf->bufsz, len);     /* next column starts on next line */
        else
-               art = tb->symbols->vert;
+               fputs(colsep(tb), tb->out);             /* columns separator */
 
-       return buffer_append_data(buf, art);
+       return 0;
 }
 
 static int cell_to_buffer(struct libscols_table *tb,