Skip to content

Commit a58dd83

Browse files
ak2gitster
authored andcommitted
pretty: add %(decorate[:<options>]) format
Add %(decorate[:<options>]) format that lists ref names similarly to the %d format, but which allows the otherwise fixed prefix, suffix and separator strings to be customized. Omitted options default to the strings used in %d. Rename expand_separator() function used to expand %x literal formatting codes to expand_string_arg(), as it is now used on strings other than separators. Examples: - %(decorate) is equivalent to %d. - %(decorate:prefix=,suffix=) is equivalent to %D. - %(decorate:prefix=[,suffix=],separator=%x3B) produces a list enclosed in square brackets and separated by semicolons. Test the format in t4205-log-pretty-formats.sh and document it in pretty-formats.txt. Signed-off-by: Andy Koppe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent dcb347f commit a58dd83

File tree

3 files changed

+92
-4
lines changed

3 files changed

+92
-4
lines changed

Documentation/pretty-formats.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,16 @@ The placeholders are:
224224
linkgit:git-rev-list[1])
225225
'%d':: ref names, like the --decorate option of linkgit:git-log[1]
226226
'%D':: ref names without the " (", ")" wrapping.
227+
'%(decorate[:<options>])'::
228+
ref names with custom decorations. The `decorate` string may be followed by a
229+
colon and zero or more comma-separated options. Option values may contain
230+
literal formatting codes. These must be used for commas (`%x2C`) and closing
231+
parentheses (`%x29`), due to their role in the option syntax.
232+
+
233+
** 'prefix=<value>': Shown before the list of ref names. Defaults to "{nbsp}`(`".
234+
** 'suffix=<value>': Shown after the list of ref names. Defaults to "`)`".
235+
** 'separator=<value>': Shown between ref names. Defaults to "`,`{nbsp}".
236+
227237
'%(describe[:<options>])'::
228238
human-readable name, like linkgit:git-describe[1]; empty string for
229239
undescribable commits. The `describe` string may be followed by a colon and

pretty.c

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,8 +1252,8 @@ static int format_trailer_match_cb(const struct strbuf *key, void *ud)
12521252
return 0;
12531253
}
12541254

1255-
static struct strbuf *expand_separator(struct strbuf *sb,
1256-
const char *argval, size_t arglen)
1255+
static struct strbuf *expand_string_arg(struct strbuf *sb,
1256+
const char *argval, size_t arglen)
12571257
{
12581258
char *fmt = xstrndup(argval, arglen);
12591259
const char *format = fmt;
@@ -1301,9 +1301,9 @@ int format_set_trailers_options(struct process_trailer_options *opts,
13011301
opts->filter_data = filter_list;
13021302
opts->only_trailers = 1;
13031303
} else if (match_placeholder_arg_value(*arg, "separator", arg, &argval, &arglen)) {
1304-
opts->separator = expand_separator(sepbuf, argval, arglen);
1304+
opts->separator = expand_string_arg(sepbuf, argval, arglen);
13051305
} else if (match_placeholder_arg_value(*arg, "key_value_separator", arg, &argval, &arglen)) {
1306-
opts->key_value_separator = expand_separator(kvsepbuf, argval, arglen);
1306+
opts->key_value_separator = expand_string_arg(kvsepbuf, argval, arglen);
13071307
} else if (!match_placeholder_bool_arg(*arg, "only", arg, &opts->only_trailers) &&
13081308
!match_placeholder_bool_arg(*arg, "unfold", arg, &opts->unfold) &&
13091309
!match_placeholder_bool_arg(*arg, "keyonly", arg, &opts->key_only) &&
@@ -1384,6 +1384,40 @@ static size_t parse_describe_args(const char *start, struct strvec *args)
13841384
return arg - start;
13851385
}
13861386

1387+
1388+
static int parse_decoration_option(const char **arg,
1389+
const char *name,
1390+
char **opt)
1391+
{
1392+
const char *argval;
1393+
size_t arglen;
1394+
1395+
if (match_placeholder_arg_value(*arg, name, arg, &argval, &arglen)) {
1396+
struct strbuf sb = STRBUF_INIT;
1397+
1398+
expand_string_arg(&sb, argval, arglen);
1399+
*opt = strbuf_detach(&sb, NULL);
1400+
return 1;
1401+
}
1402+
return 0;
1403+
}
1404+
1405+
static void parse_decoration_options(const char **arg,
1406+
struct decoration_options *opts)
1407+
{
1408+
while (parse_decoration_option(arg, "prefix", &opts->prefix) ||
1409+
parse_decoration_option(arg, "suffix", &opts->suffix) ||
1410+
parse_decoration_option(arg, "separator", &opts->separator))
1411+
;
1412+
}
1413+
1414+
static void free_decoration_options(const struct decoration_options *opts)
1415+
{
1416+
free(opts->prefix);
1417+
free(opts->suffix);
1418+
free(opts->separator);
1419+
}
1420+
13871421
static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
13881422
const char *placeholder,
13891423
void *context)
@@ -1645,6 +1679,23 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
16451679
return 2;
16461680
}
16471681

1682+
if (skip_prefix(placeholder, "(decorate", &arg)) {
1683+
struct decoration_options opts = { NULL };
1684+
size_t ret = 0;
1685+
1686+
if (*arg == ':') {
1687+
arg++;
1688+
parse_decoration_options(&arg, &opts);
1689+
}
1690+
if (*arg == ')') {
1691+
format_decorations(sb, commit, c->auto_color, &opts);
1692+
ret = arg - placeholder + 1;
1693+
}
1694+
1695+
free_decoration_options(&opts);
1696+
return ret;
1697+
}
1698+
16481699
/* For the rest we have to parse the commit header. */
16491700
if (!c->commit_header_parsed) {
16501701
msg = c->message =

t/t4205-log-pretty-formats.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,33 @@ test_expect_success 'clean log decoration' '
576576
test_cmp expected actual1
577577
'
578578

579+
test_expect_success 'pretty format %decorate' '
580+
git checkout -b foo &&
581+
git commit --allow-empty -m "new commit" &&
582+
git tag bar &&
583+
git branch qux &&
584+
585+
echo " (HEAD -> foo, tag: bar, qux)" >expect1 &&
586+
git log --format="%(decorate)" -1 >actual1 &&
587+
test_cmp expect1 actual1 &&
588+
589+
echo "HEAD -> foo, tag: bar, qux" >expect2 &&
590+
git log --format="%(decorate:prefix=,suffix=)" -1 >actual2 &&
591+
test_cmp expect2 actual2 &&
592+
593+
echo "[ HEAD -> foo; tag: bar; qux ]" >expect3 &&
594+
git log --format="%(decorate:prefix=[ ,suffix= ],separator=%x3B )" \
595+
-1 >actual3 &&
596+
test_cmp expect3 actual3 &&
597+
598+
# Try with a typo (in "separator"), in which case the placeholder should
599+
# not be replaced.
600+
echo "%(decorate:prefix=[ ,suffix= ],separater=; )" >expect4 &&
601+
git log --format="%(decorate:prefix=[ ,suffix= ],separater=%x3B )" \
602+
-1 >actual4 &&
603+
test_cmp expect4 actual4
604+
'
605+
579606
cat >trailers <<EOF
580607
Signed-off-by: A U Thor <[email protected]>
581608
Acked-by: A U Thor <[email protected]>

0 commit comments

Comments
 (0)