Skip to content

Commit 02edd56

Browse files
René Scharfegitster
authored andcommitted
Implement wrap format %w() as if it is a mode switch
I always considered line wrapping to be more similar to a colour, i.e. a state that one can change and that is applied to all following text until the next state change, except that it's always reset at the end of the format string. Here's a patch to implement this behaviour, using Dscho's strbuf_add_wrapped_text() Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 00d3947 commit 02edd56

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

pretty.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ struct format_commit_context {
445445
enum date_mode dmode;
446446
unsigned commit_header_parsed:1;
447447
unsigned commit_message_parsed:1;
448+
size_t width, indent1, indent2;
448449

449450
/* These offsets are relative to the start of the commit message. */
450451
struct chunk author;
@@ -458,6 +459,7 @@ struct format_commit_context {
458459
struct chunk abbrev_commit_hash;
459460
struct chunk abbrev_tree_hash;
460461
struct chunk abbrev_parent_hashes;
462+
size_t wrap_start;
461463
};
462464

463465
static int add_again(struct strbuf *sb, struct chunk *chunk)
@@ -595,6 +597,35 @@ static void format_decoration(struct strbuf *sb, const struct commit *commit)
595597
strbuf_addch(sb, ')');
596598
}
597599

600+
static void strbuf_wrap(struct strbuf *sb, size_t pos,
601+
size_t width, size_t indent1, size_t indent2)
602+
{
603+
struct strbuf tmp = STRBUF_INIT;
604+
605+
if (pos)
606+
strbuf_add(&tmp, sb->buf, pos);
607+
strbuf_add_wrapped_text(&tmp, sb->buf + pos,
608+
(int) indent1, (int) indent2, (int) width);
609+
strbuf_swap(&tmp, sb);
610+
strbuf_release(&tmp);
611+
}
612+
613+
static void rewrap_message_tail(struct strbuf *sb,
614+
struct format_commit_context *c,
615+
size_t new_width, size_t new_indent1,
616+
size_t new_indent2)
617+
{
618+
if (c->width == new_width && c->indent1 == new_indent1 &&
619+
c->indent2 == new_indent2)
620+
return;
621+
if (c->wrap_start && c->wrap_start < sb->len)
622+
strbuf_wrap(sb, c->wrap_start, c->width, c->indent1, c->indent2);
623+
c->wrap_start = sb->len;
624+
c->width = new_width;
625+
c->indent1 = new_indent1;
626+
c->indent2 = new_indent2;
627+
}
628+
598629
static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
599630
void *context)
600631
{
@@ -645,6 +676,30 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
645676
return 3;
646677
} else
647678
return 0;
679+
case 'w':
680+
if (placeholder[1] == '(') {
681+
unsigned long width = 0, indent1 = 0, indent2 = 0;
682+
char *next;
683+
const char *start = placeholder + 2;
684+
const char *end = strchr(start, ')');
685+
if (!end)
686+
return 0;
687+
if (end > start) {
688+
width = strtoul(start, &next, 10);
689+
if (*next == ',') {
690+
indent1 = strtoul(next + 1, &next, 10);
691+
if (*next == ',') {
692+
indent2 = strtoul(next + 1,
693+
&next, 10);
694+
}
695+
}
696+
if (*next != ')')
697+
return 0;
698+
}
699+
rewrap_message_tail(sb, c, width, indent1, indent2);
700+
return end - placeholder + 1;
701+
} else
702+
return 0;
648703
}
649704

650705
/* these depend on the commit */
@@ -748,7 +803,9 @@ void format_commit_message(const struct commit *commit,
748803
memset(&context, 0, sizeof(context));
749804
context.commit = commit;
750805
context.dmode = dmode;
806+
context.wrap_start = sb->len;
751807
strbuf_expand(sb, format, format_commit_item, &context);
808+
rewrap_message_tail(sb, &context, 0, 0, 0);
752809
}
753810

754811
static void pp_header(enum cmit_fmt fmt,

0 commit comments

Comments
 (0)