On Thu, Sep 20, 2012 at 09:40:49AM -0700, Junio C Hamano wrote:
>  - I am wondering if somebody ever want to do this with a follow-up
>    patch:
> 
>       Left %h%|Center %cd%|Right %ad
> 
>    Is %| a sensible choice for "flush right"?  I am wondering if it
>    makes more sense to make %|, %< and %> as "multi-column
>    introducer" (the example defines output with three columns) that
>    also tells how text inside each column is flushed inside the
>    column, e.g.
> 
>       %>col 1 right flushed%|col 2 centered%< col 3 left flushed
> 
>    or something like that (we may want explicit "column width"
>    specifiers if we were to do this kind of thing).

Instead of thinking of "columns", we could go back to "placeholders",
or in printf terms, an "%s". In addition to plain %s, we need
something similar to "%*s" and "%-*s" to pad right and left.

Conceptually it's simpler. We don't have to deal with a bunch of
problems in your quotes that I cut out. Still it allows users to do
flush right, flush left and so on within limits. They just need to
think in terms of fixed-size cells. So...

%>(N)%? is transformed roughly to printf("%-*s", N, %?). Similarly
%<(N)%? becomes printf("%*s", N, %?). We could have %|(N) to pad both
%left and right (aka centered).

Better?

We might need a modifier or something to allow cutting (and maybe
putting ellipsis in place) to keep oversized cells from breaking the
layout.

The demonstration patch follows. You can't build because I don't post
the whole series.

-- 8< --
diff --git a/pretty.c b/pretty.c
index b1cec71..543c309 100644
--- a/pretty.c
+++ b/pretty.c
@@ -617,6 +617,12 @@ struct chunk {
        size_t len;
 };
 
+enum flush_type {
+       no_flush,
+       flush_right,
+       flush_left
+};
+
 struct format_commit_context {
        const struct commit *commit;
        const struct pretty_print_context *pretty_ctx;
@@ -624,13 +630,14 @@ struct format_commit_context {
        unsigned commit_message_parsed:1;
        unsigned commit_signature_parsed:1;
        unsigned use_color:1;
+       enum flush_type flush_type;
        struct {
                char *gpg_output;
                char good_bad;
                char *signer;
        } signature;
        char *message;
-       size_t width, indent1, indent2;
+       size_t width, indent1, indent2, padding;
 
        /* These offsets are relative to the start of the commit message. */
        struct chunk author;
@@ -944,6 +951,24 @@ static size_t format_commit_one(struct strbuf *sb, const 
char *placeholder,
                        return end - placeholder + 1;
                } else
                        return 0;
+
+       case '<':
+       case '>':
+               if (placeholder[1] == '(') {
+                       const char *start = placeholder + 2;
+                       const char *end = strchr(start, ')');
+                       char *next;
+                       int width;
+                       if (!end || end == start)
+                               return 0;
+                       width = strtoul(start, &next, 10);
+                       if (next == start || width == 0)
+                               return 0;
+                       c->padding = width;
+                       c->flush_type = *placeholder == '<' ? flush_right : 
flush_left;
+                       return end - placeholder + 1;
+               }
+               return 0;
        }
 
        /* these depend on the commit */
@@ -1102,6 +1127,8 @@ static size_t format_commit_one(struct strbuf *sb, const 
char *placeholder,
 static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
                                 void *context)
 {
+       struct format_commit_context *c = context;
+       struct strbuf local_sb = STRBUF_INIT;
        int consumed;
        size_t orig_len;
        enum {
@@ -1127,10 +1154,23 @@ static size_t format_commit_item(struct strbuf *sb, 
const char *placeholder,
        if (magic != NO_MAGIC)
                placeholder++;
 
-       orig_len = sb->len;
-       consumed = format_commit_one(sb, placeholder, context);
-       if (magic == NO_MAGIC)
-               return consumed;
+       if (c->flush_type != no_flush) {
+               int len;
+               consumed = format_commit_one(&local_sb, placeholder, context);
+               /* the number of column, esc seq skipped */
+               len = utf8_strnwidth(local_sb.buf, -1, 1);
+               strbuf_addf(sb,
+                           c->flush_type == flush_right ? "%-*s" : "%*s",
+                           (int)(c->padding + (local_sb.len - len)),
+                           local_sb.buf);
+               strbuf_release(&local_sb);
+               c->flush_type = no_flush;
+       } else {
+               orig_len = sb->len;
+               consumed = format_commit_one(sb, placeholder, context);
+               if (magic == NO_MAGIC)
+                       return consumed;
+       }
 
        if ((orig_len == sb->len) && magic == DEL_LF_BEFORE_EMPTY) {
                while (sb->len && sb->buf[sb->len - 1] == '\n')
-- 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