On Tue, Jul 09, 2013 at 04:02:11PM +0530, Ramkumar Ramachandra wrote:
> Hi,
> 
> I'm sending this out in the hope of attracting some reviews.  It's an
> unedited resend, and there were zero conflicts from the rebase.

I still don't like my callback idea. How about this? It's refactoring
a bit so that you can now extract the color parsing and alignment code
from pretty.c and add them to for-each-ref as new atoms in --format.
As this is simply extending --format, the syntax unification idea is
put back on the shelf and won't hinder your work.

parse_color() can be used to generate color escape sequences. For
alignment, you can do something like this:

pad_an_item();
process_following_atom_after_the_alignment_atom();
align_an_item();

I'm afraid it needs a bit more work on the for-each-ref side and may
even need some fixups (I tested t4205 only and it passed, but I may
have left some bugs)

-- 8< --
diff --git a/pretty.c b/pretty.c
index 9e43154..40a30a4 100644
--- a/pretty.c
+++ b/pretty.c
@@ -766,19 +766,23 @@ enum trunc_type {
        trunc_right
 };
 
+struct alignment {
+       enum flush_type flush_type;
+       enum trunc_type truncate;
+       int padding;
+};
+
 struct format_commit_context {
        const struct commit *commit;
        const struct pretty_print_context *pretty_ctx;
        unsigned commit_header_parsed:1;
        unsigned commit_message_parsed:1;
        struct signature_check signature_check;
-       enum flush_type flush_type;
-       enum trunc_type truncate;
        char *message;
        char *commit_encoding;
        size_t width, indent1, indent2;
        int auto_color;
-       int padding;
+       struct alignment alignment;
 
        /* These offsets are relative to the start of the commit message. */
        struct chunk author;
@@ -957,7 +961,7 @@ static int format_reflog_person(struct strbuf *sb,
 
 static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
                          const char *placeholder,
-                         struct format_commit_context *c)
+                         int color_setting)
 {
        if (placeholder[1] == '(') {
                const char *begin = placeholder + 2;
@@ -967,7 +971,7 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
                if (!end)
                        return 0;
                if (!prefixcmp(begin, "auto,")) {
-                       if (!want_color(c->pretty_ctx->color))
+                       if (!want_color(color_setting))
                                return end - placeholder + 1;
                        begin += 5;
                }
@@ -995,7 +999,7 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
 
 static size_t parse_padding_placeholder(struct strbuf *sb,
                                        const char *placeholder,
-                                       struct format_commit_context *c)
+                                       struct alignment *c)
 {
        const char *ch = placeholder;
        enum flush_type flush_type;
@@ -1076,7 +1080,8 @@ static size_t format_commit_one(struct strbuf *sb, /* in 
UTF-8 */
                        c->auto_color = 1;
                        return 7; /* consumed 7 bytes, "C(auto)" */
                } else {
-                       int ret = parse_color(sb, placeholder, c);
+                       int ret = parse_color(sb, placeholder,
+                                             c->pretty_ctx->color);
                        if (ret)
                                c->auto_color = 0;
                        /*
@@ -1126,7 +1131,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in 
UTF-8 */
 
        case '<':
        case '>':
-               return parse_padding_placeholder(sb, placeholder, c);
+               return parse_padding_placeholder(sb, placeholder, 
&c->alignment);
        }
 
        /* these depend on the commit */
@@ -1291,12 +1296,8 @@ static size_t format_commit_one(struct strbuf *sb, /* in 
UTF-8 */
        return 0;       /* unknown placeholder */
 }
 
-static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
-                                   const char *placeholder,
-                                   struct format_commit_context *c)
+static int pad_an_item(struct strbuf *sb, int padding)
 {
-       struct strbuf local_sb = STRBUF_INIT;
-       int total_consumed = 0, len, padding = c->padding;
        if (padding < 0) {
                const char *start = strrchr(sb->buf, '\n');
                int occupied;
@@ -1305,9 +1306,17 @@ static size_t format_and_pad_commit(struct strbuf *sb, 
/* in UTF-8 */
                occupied = utf8_strnwidth(start, -1, 1);
                padding = (-padding) - occupied;
        }
+       return padding;
+}
+
+static int format_an_item(const char *placeholder,
+                         struct strbuf *local_sb,
+                         struct format_commit_context *c)
+{
+       int total_consumed = 0;
        while (1) {
                int modifier = *placeholder == 'C';
-               int consumed = format_commit_one(&local_sb, placeholder, c);
+               int consumed = format_commit_one(local_sb, placeholder, c);
                total_consumed += consumed;
 
                if (!modifier)
@@ -1319,9 +1328,19 @@ static size_t format_and_pad_commit(struct strbuf *sb, 
/* in UTF-8 */
                placeholder++;
                total_consumed++;
        }
-       len = utf8_strnwidth(local_sb.buf, -1, 1);
+       return total_consumed;
+}
 
-       if (c->flush_type == flush_left_and_steal) {
+static void align_an_item(struct strbuf *sb, /* in UTF-8 */
+                         struct strbuf *item,
+                         enum flush_type flush_type,
+                         enum trunc_type truncate,
+                         int padding)
+{
+       int len;
+
+       len = utf8_strnwidth(item->buf, -1, 1);
+       if (flush_type == flush_left_and_steal) {
                const char *ch = sb->buf + sb->len - 1;
                while (len > padding && ch > sb->buf) {
                        const char *p;
@@ -1343,55 +1362,68 @@ static size_t format_and_pad_commit(struct strbuf *sb, 
/* in UTF-8 */
                         * got a good ansi sequence, put it back to
                         * local_sb as we're cutting sb
                         */
-                       strbuf_insert(&local_sb, 0, p, ch + 1 - p);
+                       strbuf_insert(item, 0, p, ch + 1 - p);
                        ch = p - 1;
                }
                strbuf_setlen(sb, ch + 1 - sb->buf);
-               c->flush_type = flush_left;
+               flush_type = flush_left;
        }
 
        if (len > padding) {
-               switch (c->truncate) {
+               switch (truncate) {
                case trunc_left:
-                       strbuf_utf8_replace(&local_sb,
+                       strbuf_utf8_replace(item,
                                            0, len - (padding - 2),
                                            "..");
                        break;
                case trunc_middle:
-                       strbuf_utf8_replace(&local_sb,
+                       strbuf_utf8_replace(item,
                                            padding / 2 - 1,
                                            len - (padding - 2),
                                            "..");
                        break;
                case trunc_right:
-                       strbuf_utf8_replace(&local_sb,
+                       strbuf_utf8_replace(item,
                                            padding - 2, len - (padding - 2),
                                            "..");
                        break;
                case trunc_none:
                        break;
                }
-               strbuf_addstr(sb, local_sb.buf);
+               strbuf_addstr(sb, item->buf);
        } else {
                int sb_len = sb->len, offset = 0;
-               if (c->flush_type == flush_left)
+               if (flush_type == flush_left)
                        offset = padding - len;
-               else if (c->flush_type == flush_both)
+               else if (flush_type == flush_both)
                        offset = (padding - len) / 2;
                /*
                 * we calculate padding in columns, now
                 * convert it back to chars
                 */
-               padding = padding - len + local_sb.len;
+               padding = padding - len + item->len;
                strbuf_grow(sb, padding);
                strbuf_setlen(sb, sb_len + padding);
                memset(sb->buf + sb_len, ' ', sb->len - sb_len);
-               memcpy(sb->buf + sb_len + offset, local_sb.buf,
-                      local_sb.len);
+               memcpy(sb->buf + sb_len + offset, item->buf,
+                      item->len);
        }
+}
+
+static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
+                                   const char *placeholder,
+                                   struct format_commit_context *c)
+{
+       int consumed, padding;
+       struct strbuf local_sb = STRBUF_INIT;
+
+       padding = pad_an_item(sb, c->alignment.padding);
+       consumed = format_an_item(placeholder, &local_sb, c);
+       align_an_item(sb, &local_sb, c->alignment.flush_type,
+                     c->alignment.truncate, padding);
        strbuf_release(&local_sb);
-       c->flush_type = no_flush;
-       return total_consumed;
+       c->alignment.flush_type = no_flush;
+       return consumed;
 }
 
 static size_t format_commit_item(struct strbuf *sb, /* in UTF-8 */
@@ -1424,7 +1456,7 @@ static size_t format_commit_item(struct strbuf *sb, /* in 
UTF-8 */
                placeholder++;
 
        orig_len = sb->len;
-       if (((struct format_commit_context *)context)->flush_type != no_flush)
+       if (((struct format_commit_context *)context)->alignment.flush_type != 
no_flush)
                consumed = format_and_pad_commit(sb, placeholder, context);
        else
                consumed = format_commit_one(sb, placeholder, context);
-- 8< --
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to