[PATCH v8 0/11] Port tag.c over to use ref-filter APIs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is part of my GSoC project to unify git tag -l, git branch -l,
git for-each-ref.  This patch series is continued from: Git (next)
https://github.com/git/git/commit/bf5418f49ff0cebc6e5ce04ad1417e1a47c81b61

This series consists of porting tag.c over to using the ref-filter APIs

Version 7 can be found here:
http://thread.gmane.org/gmane.comp.version-control.git/274990

Changes:
* Make padright a general align atom.
* Make print_value() and emit() output to a strbuf rather than stdout directly.

Interdiff:

diff --git a/Documentation/git-for-each-ref.txt
b/Documentation/git-for-each-ref.txt
index bcf319a..e89b9b0 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -127,11 +127,12 @@ color::
     Change output color.  Followed by `:<colorname>`, where names
     are described in `color.branch.*`.

-padright::
-    Pad succeeding atom or string to the right. Followed by
-    `:<value>`, where `value` states the total length of atom or
-    string including the padding. If the `value` is lesser than
-    the atom or string length, then no padding is performed.
+align::
+    Align succeeding atoms to the right, left or middle. Followed
+    by `:<type>,<paddinglength>`, where the `<type>` is either
+    left, right or middle and `<paddinglength>` is the total
+    length of the padding to be performed. If the atom length is
+    more than the padding length then no padding is performed.

 In addition to the above, for commit and tag objects, the header
 field names (`tree`, `parent`, `object`, `type`, and `tag`) can
diff --git a/builtin/tag.c b/builtin/tag.c
index fc01117..529b29f 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -41,7 +41,7 @@ static int list_tags(struct ref_filter *filter,
struct ref_sorting *sorting, con
         filter->lines = 0;

     if (filter->lines)
-        format = "%(padright:16)%(refname:short)";
+        format = "%(align:left,16)%(refname:short)";
     else if (!format)
         format = "%(refname:short)";

diff --git a/ref-filter.c b/ref-filter.c
index 65d168e..afeab37 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -56,7 +56,7 @@ static struct {
     { "flag" },
     { "HEAD" },
     { "color" },
-    { "padright" },
+    { "align" },
 };

 /*
@@ -624,7 +624,7 @@ static void populate_value(struct ref_array_item *ref)
         const char *name = used_atom[i];
         struct atom_value *v = &ref->value[i];
         int deref = 0;
-        const char *refname;
+        const char *refname = NULL;
         const char *formatp;
         struct branch *branch = NULL;

@@ -664,8 +664,6 @@ static void populate_value(struct ref_array_item *ref)
             if (color_parse(name + 6, color) < 0)
                 die(_("unable to parse format"));
             v->s = xstrdup(color);
-            v->color = 1;
-            v->modifier_atom = 1;
             continue;
         } else if (!strcmp(name, "flag")) {
             char buf[256], *cp = buf;
@@ -693,17 +691,23 @@ static void populate_value(struct ref_array_item *ref)
             else
                 v->s = " ";
             continue;
-        } else if (starts_with(name, "padright:")) {
+        } else if (starts_with(name, "align:")) {
             const char *valp = NULL;
+            struct align *align = xmalloc(sizeof(struct align));

-            skip_prefix(name, "padright:", &valp);
-            if (!valp[0])
-                die(_("no value given with 'padright:'"));
-            if (strtoul_ui(valp, 10, (unsigned int *)&v->ul))
-                die(_("positive integer expected after ':' in padright:%u\n"),
-                    (unsigned int)v->ul);
-            v->modifier_atom = 1;
-            v->pad_to_right = 1;
+            skip_prefix(name, "align:", &valp);
+
+            if (skip_prefix(valp, "left,", &valp))
+                align->align_type = ALIGN_LEFT;
+            else if (skip_prefix(valp, "right,", &valp))
+                align->align_type = ALIGN_RIGHT;
+            else if (skip_prefix(valp, "middle,", &valp))
+                align->align_type = ALIGN_MIDDLE;
+            else
+                die(_("align: improper format"));
+            if (strtoul_ui(valp, 10, &align->align_value))
+                die(_("align: positive value expected"));
+            v->align = align;
             continue;
         } else
             continue;
@@ -1243,55 +1247,26 @@ void ref_array_sort(struct ref_sorting
*sorting, struct ref_array *array)
     qsort(array->items, array->nr, sizeof(struct ref_array_item *),
compare_refs);
 }

-static void apply_formatting_state(struct ref_formatting_state *state,
-                   const char *buf, struct strbuf *value)
-{
-    if (state->color) {
-        strbuf_addstr(value, state->color);
-        state->color = NULL;
-    }
-    if (state->pad_to_right) {
-        if (!is_utf8(buf))
-            strbuf_addf(value, "%-*s", state->pad_to_right, buf);
-        else {
-            int utf8_compensation = strlen(buf) - utf8_strwidth(buf);
-            strbuf_addf(value, "%-*s", state->pad_to_right +
utf8_compensation, buf);
-        }
-        state->pad_to_right = 0;
-        return;
-    }
-
-    strbuf_addstr(value, buf);
-}
-
-static void print_value(struct atom_value *v, struct
ref_formatting_state *state)
+static void print_value(struct atom_value *v, struct
ref_formatting_state *state,
+            struct strbuf *output)
 {
-    struct strbuf value = STRBUF_INIT;
-    struct strbuf formatted = STRBUF_INIT;
-
-    apply_formatting_state(state, v->s, &value);
-
     switch (state->quote_style) {
     case QUOTE_NONE:
-        fputs(value.buf, stdout);
+        strbuf_addstr(output, v->s);
         break;
     case QUOTE_SHELL:
-        sq_quote_buf(&formatted, value.buf);
+        sq_quote_buf(output, v->s);
         break;
     case QUOTE_PERL:
-        perl_quote_buf(&formatted, value.buf);
+        perl_quote_buf(output, v->s);
         break;
     case QUOTE_PYTHON:
-        python_quote_buf(&formatted, value.buf);
+        python_quote_buf(output, v->s);
         break;
     case QUOTE_TCL:
-        tcl_quote_buf(&formatted, value.buf);
+        tcl_quote_buf(output, v->s);
         break;
     }
-    if (state->quote_style != QUOTE_NONE)
-        fputs(formatted.buf, stdout);
-    strbuf_release(&value);
-    strbuf_release(&formatted);
 }

 static int hex1(char ch)
@@ -1312,12 +1287,8 @@ static int hex2(const char *cp)
         return -1;
 }

-static void emit(const char *cp, const char *ep,
-         struct ref_formatting_state *state)
+static void emit(const char *cp, const char *ep, struct strbuf *output)
 {
-    struct strbuf value = STRBUF_INIT;
-    struct strbuf format = STRBUF_INIT;
-
     while (*cp && (!ep || cp < ep)) {
         if (*cp == '%') {
             if (cp[1] == '%')
@@ -1325,28 +1296,61 @@ static void emit(const char *cp, const char *ep,
             else {
                 int ch = hex2(cp + 1);
                 if (0 <= ch) {
-                    putchar(ch);
+                    strbuf_addch(output, ch);
                     cp += 3;
                     continue;
                 }
             }
         }
-        strbuf_addch(&value, *cp);
+        strbuf_addch(output, *cp);
         cp++;
     }
-    apply_formatting_state(state, value.buf, &format);
-    fputs(format.buf, stdout);
-    strbuf_release(&format);
-    strbuf_release(&value);
 }

-static void store_formatting_state(struct ref_formatting_state *state,
-                   struct atom_value *atomv)
+static void process_formatting_state(struct atom_value *atomv, struct
ref_formatting_state *state)
 {
-    if (atomv->color)
-        state->color = atomv->s;
-    if (atomv->pad_to_right)
-        state->pad_to_right = atomv->ul;
+    if (atomv->align) {
+        state->align = atomv->align;
+        atomv->align = NULL;
+    }
+}
+
+static void apply_formatting_state(struct ref_formatting_state
*state, struct strbuf *value,
+                   struct strbuf *format)
+{
+    if (state->align) {
+        int len = 0, buf_len = value->len;
+        struct align *align = state->align;
+
+        if (!value->buf)
+            return;
+        if (!is_utf8(value->buf)) {
+            len = value->len - utf8_strwidth(value->buf);
+            buf_len -= len;
+        }
+
+        if (align->align_value < buf_len) {
+            state->align = NULL;
+            strbuf_addbuf(format, value);
+            strbuf_release(value);
+            return;
+        }
+
+        if (align->align_type == ALIGN_LEFT)
+            strbuf_addf(format, "%-*s", len + align->align_value, value->buf);
+        else if (align->align_type == ALIGN_MIDDLE) {
+            int right = (align->align_value - buf_len)/2;
+            strbuf_addf(format, "%*s%-*s", align->align_value - right + len,
+                    value->buf, right, "");
+        } else if (align->align_type == ALIGN_RIGHT)
+            strbuf_addf(format, "%*s", align->align_value, value->buf);
+        strbuf_release(value);
+        state->align = NULL;
+        return;
+    }
+    strbuf_addbuf(format, value);
+    strbuf_release(value);
+
 }

 /*
@@ -1396,26 +1400,34 @@ void show_ref_array_item(struct ref_array_item
*info, const char *format,
              int quote_style, unsigned int lines)
 {
     const char *cp, *sp, *ep;
+    struct strbuf value = STRBUF_INIT;
+    struct strbuf final_buf = STRBUF_INIT;
     struct ref_formatting_state state;
+    int i;

     memset(&state, 0, sizeof(state));
     state.quote_style = quote_style;

     for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
-        struct atom_value *atomv;
+        struct atom_value *atomv = NULL;

         ep = strchr(sp, ')');
-        if (cp < sp)
-            emit(cp, sp, &state);
+        if (cp < sp) {
+            emit(cp, sp, &value);
+            apply_formatting_state(&state, &value, &final_buf);
+        }
         get_ref_atom_value(info, parse_ref_filter_atom(sp + 2, ep), &atomv);
-        if (atomv->modifier_atom)
-            store_formatting_state(&state, atomv);
-        else
-            print_value(atomv, &state);
+        if (atomv->align)
+            process_formatting_state(atomv, &state);
+        else {
+            print_value(atomv, &state, &value);
+            apply_formatting_state(&state, &value, &final_buf);
+        }
     }
     if (*cp) {
         sp = cp + strlen(cp);
-        emit(cp, sp, &state);
+        emit(cp, sp, &value);
+        apply_formatting_state(&state, &value, &final_buf);
     }
     if (need_color_reset_at_eol) {
         struct atom_value resetv;
@@ -1424,8 +1436,14 @@ void show_ref_array_item(struct ref_array_item
*info, const char *format,
         if (color_parse("reset", color) < 0)
             die("BUG: couldn't parse 'reset' as a color");
         resetv.s = color;
-        print_value(&resetv, &state);
+        print_value(&resetv, &state, &value);
+        apply_formatting_state(&state, &value, &final_buf);
     }
+
+    for (i = 0; i < final_buf.len; i++)
+        printf("%c", final_buf.buf[i]);
+    strbuf_release(&final_buf);
+
     if (lines > 0) {
         struct object_id oid;
         hashcpy(oid.hash, info->objectname);
diff --git a/ref-filter.h b/ref-filter.h
index b50a036..b3b9cd8 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -17,18 +17,25 @@
 #define FILTER_REFS_ALL 0x2
 #define FILTER_REFS_TAGS 0x4

-struct atom_value {
-    const char *s;
-    unsigned long ul; /* used for sorting when not FIELD_STR */
-    unsigned int modifier_atom : 1, /*  atoms which act as modifiers
for the next atom */
-        color : 1,
-        pad_to_right : 1;
-};
+#define ALIGN_LEFT 0x01
+#define ALIGN_RIGHT 0x02
+#define ALIGN_MIDDLE 0x04

 struct ref_formatting_state {
     int quote_style;
-    unsigned int pad_to_right;
-    const char *color;
+    struct align *align;
+    struct strbuf *sb;
+};
+
+struct align {
+    unsigned int align_type,
+        align_value;
+};
+
+struct atom_value {
+    const char *s;
+    struct align *align;
+    unsigned long ul; /* used for sorting when not FIELD_STR */
 };

 struct ref_sorting {
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 842efde..7332bea 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -81,35 +81,83 @@ test_expect_success 'filtering with --contains' '
     test_cmp expect actual
 '

-test_expect_success 'padding to the right using `padright`' '
+test_expect_success 'left alignment' '
     cat >expect <<-\EOF &&
-    master    ||    master
-    side      ||    side
-    odd/spot  ||    odd/spot
-    double-tag||    double-tag
-    four      ||    four
-    one       ||    one
-    signed-tag||    signed-tag
-    three     ||    three
-    two       ||    two
+    refs/heads/master   |refs/heads/master
+    refs/heads/side     |refs/heads/side
+    refs/odd/spot       |refs/odd/spot
+    refs/tags/double-tag|refs/tags/double-tag
+    refs/tags/four      |refs/tags/four
+    refs/tags/one       |refs/tags/one
+    refs/tags/signed-tag|refs/tags/signed-tag
+    refs/tags/three     |refs/tags/three
+    refs/tags/two       |refs/tags/two
     EOF
-    git for-each-ref
--format="%(padright:10)%(refname:short)|%(padright:5)|%(refname:short)"
>actual &&
+    git for-each-ref --format="%(align:left,20)%(refname)|%(refname)"
>actual &&
     test_cmp expect actual
 '

-test_expect_success 'no padding when `padright` length is smaller
than atom length' '
+test_expect_success 'middle alignment' '
     cat >expect <<-\EOF &&
-    refs/heads/master|
-    refs/heads/side|
-    refs/odd/spot|
-    refs/tags/double-tag|
-    refs/tags/four|
-    refs/tags/one|
-    refs/tags/signed-tag|
-    refs/tags/three|
-    refs/tags/two|
+    |  refs/heads/master |refs/heads/master
+    |   refs/heads/side  |refs/heads/side
+    |    refs/odd/spot   |refs/odd/spot
+    |refs/tags/double-tag|refs/tags/double-tag
+    |   refs/tags/four   |refs/tags/four
+    |    refs/tags/one   |refs/tags/one
+    |refs/tags/signed-tag|refs/tags/signed-tag
+    |   refs/tags/three  |refs/tags/three
+    |    refs/tags/two   |refs/tags/two
     EOF
-    git for-each-ref --format="%(padright:5)%(refname)|" >actual &&
+    git for-each-ref
--format="|%(align:middle,20)%(refname)|%(refname)" >actual &&
+    test_cmp expect actual
+'
+
+test_expect_success 'right alignment' '
+    cat >expect <<-\EOF &&
+    |   refs/heads/master|refs/heads/master
+    |     refs/heads/side|refs/heads/side
+    |       refs/odd/spot|refs/odd/spot
+    |refs/tags/double-tag|refs/tags/double-tag
+    |      refs/tags/four|refs/tags/four
+    |       refs/tags/one|refs/tags/one
+    |refs/tags/signed-tag|refs/tags/signed-tag
+    |     refs/tags/three|refs/tags/three
+    |       refs/tags/two|refs/tags/two
+    EOF
+    git for-each-ref
--format="|%(align:right,20)%(refname)|%(refname)" >actual &&
+    test_cmp expect actual
+'
+
+test_expect_success 'alignment value lesser than atom value' '
+    cat >expect <<-\EOF &&
+    |refs/heads/master|
+    |refs/heads/side|
+    |  refs/odd/spot|
+    |refs/tags/double-tag|
+    | refs/tags/four|
+    |  refs/tags/one|
+    |refs/tags/signed-tag|
+    |refs/tags/three|
+    |  refs/tags/two|
+    EOF
+    git for-each-ref --format="|%(align:right,15)%(refname)|" >actual &&
+    test_cmp expect actual
+'
+
+test_expect_success 'non atom alignment' '
+    cat >expect <<-\EOF &&
+    |    |master  |  refs/heads/master|  refs/heads/master
+    |    |side  |  refs/heads/side|  refs/heads/side
+    |    |odd/spot  |  refs/odd/spot|  refs/odd/spot
+    |    |double-tag  |  refs/tags/double-tag|  refs/tags/double-tag
+    |    |four  |  refs/tags/four|  refs/tags/four
+    |    |one  |  refs/tags/one|  refs/tags/one
+    |    |signed-tag  |  refs/tags/signed-tag|  refs/tags/signed-tag
+    |    |three  |  refs/tags/three|  refs/tags/three
+    |    |two  |  refs/tags/two|  refs/tags/two
+    EOF
+    git for-each-ref
--format="|%(align:right,5)|%(refname:short)%(align:middle,5)|%(refname)%(align:left,3)|%(refname)"
>actual &&
     test_cmp expect actual
 '

-- 
Regards,
Karthik Nayak
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]