pretty: expand tabs in indented logs to make things line up properly
[gitweb.git] / pretty.c
index 151c2ae3128bb7c1a0ae13166539cb79e6edaeb8..c8b075d91b9dfdcca505c6576b470c8d03e34ac4 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -543,9 +543,9 @@ static void add_merge_info(const struct pretty_print_context *pp,
                struct commit *p = parent->item;
                const char *hex = NULL;
                if (pp->abbrev)
-                       hex = find_unique_abbrev(p->object.sha1, pp->abbrev);
+                       hex = find_unique_abbrev(p->object.oid.hash, pp->abbrev);
                if (!hex)
-                       hex = sha1_to_hex(p->object.sha1);
+                       hex = oid_to_hex(&p->object.oid);
                parent = parent->next;
 
                strbuf_addf(sb, " %s", hex);
@@ -1119,12 +1119,12 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
 
        /* these depend on the commit */
        if (!commit->object.parsed)
-               parse_object(commit->object.sha1);
+               parse_object(commit->object.oid.hash);
 
        switch (placeholder[0]) {
        case 'H':               /* commit hash */
                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
-               strbuf_addstr(sb, sha1_to_hex(commit->object.sha1));
+               strbuf_addstr(sb, oid_to_hex(&commit->object.oid));
                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
                return 1;
        case 'h':               /* abbreviated commit hash */
@@ -1133,18 +1133,18 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                        strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
                        return 1;
                }
-               strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1,
+               strbuf_addstr(sb, find_unique_abbrev(commit->object.oid.hash,
                                                     c->pretty_ctx->abbrev));
                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
                c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
                return 1;
        case 'T':               /* tree hash */
-               strbuf_addstr(sb, sha1_to_hex(commit->tree->object.sha1));
+               strbuf_addstr(sb, oid_to_hex(&commit->tree->object.oid));
                return 1;
        case 't':               /* abbreviated tree hash */
                if (add_again(sb, &c->abbrev_tree_hash))
                        return 1;
-               strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.sha1,
+               strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.oid.hash,
                                                     c->pretty_ctx->abbrev));
                c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off;
                return 1;
@@ -1152,7 +1152,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                for (p = commit->parents; p; p = p->next) {
                        if (p != commit->parents)
                                strbuf_addch(sb, ' ');
-                       strbuf_addstr(sb, sha1_to_hex(p->item->object.sha1));
+                       strbuf_addstr(sb, oid_to_hex(&p->item->object.oid));
                }
                return 1;
        case 'p':               /* abbreviated parent hashes */
@@ -1162,7 +1162,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                        if (p != commit->parents)
                                strbuf_addch(sb, ' ');
                        strbuf_addstr(sb, find_unique_abbrev(
-                                       p->item->object.sha1,
+                                       p->item->object.oid.hash,
                                        c->pretty_ctx->abbrev));
                }
                c->abbrev_parent_hashes.len = sb->len -
@@ -1629,6 +1629,72 @@ void pp_title_line(struct pretty_print_context *pp,
        strbuf_release(&title);
 }
 
+static int pp_utf8_width(const char *start, const char *end)
+{
+       int width = 0;
+       size_t remain = end - start;
+
+       while (remain) {
+               int n = utf8_width(&start, &remain);
+               if (n < 0 || !start)
+                       return -1;
+               width += n;
+       }
+       return width;
+}
+
+static void strbuf_add_tabexpand(struct strbuf *sb,
+                                const char *line, int linelen)
+{
+       const char *tab;
+
+       while ((tab = memchr(line, '\t', linelen)) != NULL) {
+               int width = pp_utf8_width(line, tab);
+
+               /*
+                * If it wasn't well-formed utf8, or it
+                * had characters with badly defined
+                * width (control characters etc), just
+                * give up on trying to align things.
+                */
+               if (width < 0)
+                       break;
+
+               /* Output the data .. */
+               strbuf_add(sb, line, tab - line);
+
+               /* .. and the de-tabified tab */
+               strbuf_addchars(sb, ' ', 8 - (width % 8));
+
+               /* Skip over the printed part .. */
+               linelen -= tab + 1 - line;
+               line = tab + 1;
+       }
+
+       /*
+        * Print out everything after the last tab without
+        * worrying about width - there's nothing more to
+        * align.
+        */
+       strbuf_add(sb, line, linelen);
+}
+
+/*
+ * pp_handle_indent() prints out the intendation, and
+ * the whole line (without the final newline), after
+ * de-tabifying.
+ */
+static void pp_handle_indent(struct pretty_print_context *pp,
+                            struct strbuf *sb, int indent,
+                            const char *line, int linelen)
+{
+       strbuf_addchars(sb, ' ', indent);
+       if (pp->expand_tabs_in_log)
+               strbuf_add_tabexpand(sb, line, linelen);
+       else
+               strbuf_add(sb, line, linelen);
+}
+
 void pp_remainder(struct pretty_print_context *pp,
                  const char **msg_p,
                  struct strbuf *sb,
@@ -1653,8 +1719,9 @@ void pp_remainder(struct pretty_print_context *pp,
 
                strbuf_grow(sb, linelen + indent + 20);
                if (indent)
-                       strbuf_addchars(sb, ' ', indent);
-               strbuf_add(sb, line, linelen);
+                       pp_handle_indent(pp, sb, indent, line, linelen);
+               else
+                       strbuf_add(sb, line, linelen);
                strbuf_addch(sb, '\n');
        }
 }