@matheusbsbs / matheus-bagliano / commits / 02edd56b84
Fork 0

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>

René Scharfe committed Oct 17, 2009 at 23:04 UTC 02edd56b84f00c1a88c5602f5608033d4bc1cbff
1 file changed +57
pretty.c
+57
@@ -445,6 +445,7 @@ struct format_commit_context {
445 enum date_mode dmode;
446 unsigned commit_header_parsed:1;
447 unsigned commit_message_parsed:1;
448 + size_t width, indent1, indent2;
449
450 /* These offsets are relative to the start of the commit message. */
451 struct chunk author;
@@ -458,6 +459,7 @@ struct format_commit_context {
459 struct chunk abbrev_commit_hash;
460 struct chunk abbrev_tree_hash;
461 struct chunk abbrev_parent_hashes;
462 + size_t wrap_start;
463 };
464
465 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)
597 strbuf_addch(sb, ')');
598 }
599
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 +
629 static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
630 void *context)
631 {
@@ -645,6 +676,30 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
676 return 3;
677 } else
678 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;
703 }
704
705 /* these depend on the commit */
@@ -748,7 +803,9 @@ void format_commit_message(const struct commit *commit,
803 memset(&context, 0, sizeof(context));
804 context.commit = commit;
805 context.dmode = dmode;
806 + context.wrap_start = sb->len;
807 strbuf_expand(sb, format, format_commit_item, &context);
808 + rewrap_message_tail(sb, &context, 0, 0, 0);
809 }
810
811 static void pp_header(enum cmit_fmt fmt,