Skip to content

Commit 7cc13c7

Browse files
torvaldsgitster
authored andcommitted
pretty: expand tabs in indented logs to make things line up properly
A commit log message sometimes tries to line things up using tabs, assuming fixed-width font with the standard 8-place tab settings. Viewing such a commit however does not work well in "git log", as we indent the lines by prefixing 4 spaces in front of them. This should all line up: Column 1 Column 2 -------- -------- A B ABCD EFGH SPACES Instead of Tabs Even with multi-byte UTF8 characters: Column 1 Column 2 -------- -------- Ä B åäö 100 A Møøse once bit my sister.. Tab-expand the lines in "git log --expand-tabs" output before prefixing 4 spaces. This is based on the patch by Linus Torvalds, but at this step, we require an explicit command line option to enable the behaviour. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 594730e commit 7cc13c7

File tree

6 files changed

+79
-2
lines changed

6 files changed

+79
-2
lines changed

Documentation/pretty-options.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ people using 80-column terminals.
4242
verbatim; this means that invalid sequences in the original
4343
commit may be copied to the output.
4444

45+
--expand-tabs::
46+
Perform a tab expansion (replace each tab with enough spaces
47+
to fill to the next display column that is multiple of 8)
48+
in the log message before showing it in the output.
49+
4550
ifndef::git-rev-list[]
4651
--notes[=<ref>]::
4752
Show the notes (see linkgit:git-notes[1]) that annotate the

commit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ struct pretty_print_context {
147147
int preserve_subject;
148148
struct date_mode date_mode;
149149
unsigned date_mode_explicit:1;
150+
unsigned expand_tabs_in_log:1;
150151
int need_8bit_cte;
151152
char *notes_message;
152153
struct reflog_walk_info *reflog_info;

log-tree.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ void show_log(struct rev_info *opt)
683683
ctx.fmt = opt->commit_format;
684684
ctx.mailmap = opt->mailmap;
685685
ctx.color = opt->diffopt.use_color;
686+
ctx.expand_tabs_in_log = opt->expand_tabs_in_log;
686687
ctx.output_encoding = get_log_output_encoding();
687688
if (opt->from_ident.mail_begin && opt->from_ident.name_begin)
688689
ctx.from_ident = &opt->from_ident;

pretty.c

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,72 @@ void pp_title_line(struct pretty_print_context *pp,
16291629
strbuf_release(&title);
16301630
}
16311631

1632+
static int pp_utf8_width(const char *start, const char *end)
1633+
{
1634+
int width = 0;
1635+
size_t remain = end - start;
1636+
1637+
while (remain) {
1638+
int n = utf8_width(&start, &remain);
1639+
if (n < 0 || !start)
1640+
return -1;
1641+
width += n;
1642+
}
1643+
return width;
1644+
}
1645+
1646+
static void strbuf_add_tabexpand(struct strbuf *sb,
1647+
const char *line, int linelen)
1648+
{
1649+
const char *tab;
1650+
1651+
while ((tab = memchr(line, '\t', linelen)) != NULL) {
1652+
int width = pp_utf8_width(line, tab);
1653+
1654+
/*
1655+
* If it wasn't well-formed utf8, or it
1656+
* had characters with badly defined
1657+
* width (control characters etc), just
1658+
* give up on trying to align things.
1659+
*/
1660+
if (width < 0)
1661+
break;
1662+
1663+
/* Output the data .. */
1664+
strbuf_add(sb, line, tab - line);
1665+
1666+
/* .. and the de-tabified tab */
1667+
strbuf_addchars(sb, ' ', 8 - (width % 8));
1668+
1669+
/* Skip over the printed part .. */
1670+
linelen -= tab + 1 - line;
1671+
line = tab + 1;
1672+
}
1673+
1674+
/*
1675+
* Print out everything after the last tab without
1676+
* worrying about width - there's nothing more to
1677+
* align.
1678+
*/
1679+
strbuf_add(sb, line, linelen);
1680+
}
1681+
1682+
/*
1683+
* pp_handle_indent() prints out the intendation, and
1684+
* the whole line (without the final newline), after
1685+
* de-tabifying.
1686+
*/
1687+
static void pp_handle_indent(struct pretty_print_context *pp,
1688+
struct strbuf *sb, int indent,
1689+
const char *line, int linelen)
1690+
{
1691+
strbuf_addchars(sb, ' ', indent);
1692+
if (pp->expand_tabs_in_log)
1693+
strbuf_add_tabexpand(sb, line, linelen);
1694+
else
1695+
strbuf_add(sb, line, linelen);
1696+
}
1697+
16321698
void pp_remainder(struct pretty_print_context *pp,
16331699
const char **msg_p,
16341700
struct strbuf *sb,
@@ -1653,8 +1719,9 @@ void pp_remainder(struct pretty_print_context *pp,
16531719

16541720
strbuf_grow(sb, linelen + indent + 20);
16551721
if (indent)
1656-
strbuf_addchars(sb, ' ', indent);
1657-
strbuf_add(sb, line, linelen);
1722+
pp_handle_indent(pp, sb, indent, line, linelen);
1723+
else
1724+
strbuf_add(sb, line, linelen);
16581725
strbuf_addch(sb, '\n');
16591726
}
16601727
}

revision.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,6 +1915,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
19151915
revs->verbose_header = 1;
19161916
revs->pretty_given = 1;
19171917
get_commit_format(arg+9, revs);
1918+
} else if (!strcmp(arg, "--expand-tabs")) {
1919+
revs->expand_tabs_in_log = 1;
19181920
} else if (!strcmp(arg, "--show-notes") || !strcmp(arg, "--notes")) {
19191921
revs->show_notes = 1;
19201922
revs->show_notes_given = 1;

revision.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ struct rev_info {
133133
show_notes_given:1,
134134
show_signature:1,
135135
pretty_given:1,
136+
expand_tabs_in_log:1,
136137
abbrev_commit:1,
137138
abbrev_commit_given:1,
138139
zero_commit:1,

0 commit comments

Comments
 (0)