Skip to content

Commit a7f01c6

Browse files
pcloudsgitster
authored andcommitted
pretty: support truncating in %>, %< and %><
%>(N,trunc) truncates the right part after N columns and replace the last two letters with "..". ltrunc does the same on the left. mtrunc cuts the middle out. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent a575234 commit a7f01c6

File tree

5 files changed

+140
-5
lines changed

5 files changed

+140
-5
lines changed

Diff for: Documentation/pretty-formats.txt

+5-2
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,11 @@ The placeholders are:
164164
- '%x00': print a byte from a hex code
165165
- '%w([<w>[,<i1>[,<i2>]]])': switch line wrapping, like the -w option of
166166
linkgit:git-shortlog[1].
167-
- '%<(<N>)': make the next placeholder take at least N columns,
168-
padding spaces on the right if necessary
167+
- '%<(<N>[,trunc|ltrunc|mtrunc])': make the next placeholder take at
168+
least N columns, padding spaces on the right if necessary.
169+
Optionally truncate at the beginning (ltrunc), the middle (mtrunc)
170+
or the end (trunc) if the output is longer than N columns.
171+
Note that truncating only works correctly with N >= 2.
169172
- '%<|(<N>)': make the next placeholder take at least until Nth
170173
columns, padding spaces on the right if necessary
171174
- '%>(<N>)', '%>|(<N>)': similar to '%<(<N>)', '%<|(<N>)'

Diff for: pretty.c

+48-3
Original file line numberDiff line numberDiff line change
@@ -776,13 +776,21 @@ enum flush_type {
776776
flush_both
777777
};
778778

779+
enum trunc_type {
780+
trunc_none,
781+
trunc_left,
782+
trunc_middle,
783+
trunc_right
784+
};
785+
779786
struct format_commit_context {
780787
const struct commit *commit;
781788
const struct pretty_print_context *pretty_ctx;
782789
unsigned commit_header_parsed:1;
783790
unsigned commit_message_parsed:1;
784791
struct signature_check signature_check;
785792
enum flush_type flush_type;
793+
enum trunc_type truncate;
786794
char *message;
787795
char *commit_encoding;
788796
size_t width, indent1, indent2;
@@ -1033,7 +1041,7 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
10331041

10341042
if (*ch == '(') {
10351043
const char *start = ch + 1;
1036-
const char *end = strchr(start, ')');
1044+
const char *end = start + strcspn(start, ",)");
10371045
char *next;
10381046
int width;
10391047
if (!end || end == start)
@@ -1043,6 +1051,23 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
10431051
return 0;
10441052
c->padding = to_column ? -width : width;
10451053
c->flush_type = flush_type;
1054+
1055+
if (*end == ',') {
1056+
start = end + 1;
1057+
end = strchr(start, ')');
1058+
if (!end || end == start)
1059+
return 0;
1060+
if (!prefixcmp(start, "trunc)"))
1061+
c->truncate = trunc_right;
1062+
else if (!prefixcmp(start, "ltrunc)"))
1063+
c->truncate = trunc_left;
1064+
else if (!prefixcmp(start, "mtrunc)"))
1065+
c->truncate = trunc_middle;
1066+
else
1067+
return 0;
1068+
} else
1069+
c->truncate = trunc_none;
1070+
10461071
return end - placeholder + 1;
10471072
}
10481073
return 0;
@@ -1309,9 +1334,29 @@ static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
13091334
total_consumed++;
13101335
}
13111336
len = utf8_strnwidth(local_sb.buf, -1, 1);
1312-
if (len > padding)
1337+
if (len > padding) {
1338+
switch (c->truncate) {
1339+
case trunc_left:
1340+
strbuf_utf8_replace(&local_sb,
1341+
0, len - (padding - 2),
1342+
"..");
1343+
break;
1344+
case trunc_middle:
1345+
strbuf_utf8_replace(&local_sb,
1346+
padding / 2 - 1,
1347+
len - (padding - 2),
1348+
"..");
1349+
break;
1350+
case trunc_right:
1351+
strbuf_utf8_replace(&local_sb,
1352+
padding - 2, len - (padding - 2),
1353+
"..");
1354+
break;
1355+
case trunc_none:
1356+
break;
1357+
}
13131358
strbuf_addstr(sb, local_sb.buf);
1314-
else {
1359+
} else {
13151360
int sb_len = sb->len, offset = 0;
13161361
if (c->flush_type == flush_left)
13171362
offset = padding - len;

Diff for: t/t4205-log-pretty-formats.sh

+39
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,45 @@ EOF
143143
test_cmp expected actual
144144
'
145145

146+
test_expect_success 'left alignment formatting with trunc' '
147+
git log --pretty="format:%<(10,trunc)%s" >actual &&
148+
# complete the incomplete line at the end
149+
echo >>actual &&
150+
qz_to_tab_space <<\EOF >expected &&
151+
message ..
152+
message ..
153+
add bar Z
154+
initial Z
155+
EOF
156+
test_cmp expected actual
157+
'
158+
159+
test_expect_success 'left alignment formatting with ltrunc' '
160+
git log --pretty="format:%<(10,ltrunc)%s" >actual &&
161+
# complete the incomplete line at the end
162+
echo >>actual &&
163+
qz_to_tab_space <<\EOF >expected &&
164+
..sage two
165+
..sage one
166+
add bar Z
167+
initial Z
168+
EOF
169+
test_cmp expected actual
170+
'
171+
172+
test_expect_success 'left alignment formatting with mtrunc' '
173+
git log --pretty="format:%<(10,mtrunc)%s" >actual &&
174+
# complete the incomplete line at the end
175+
echo >>actual &&
176+
qz_to_tab_space <<\EOF >expected &&
177+
mess.. two
178+
mess.. one
179+
add bar Z
180+
initial Z
181+
EOF
182+
test_cmp expected actual
183+
'
184+
146185
test_expect_success 'right alignment formatting' '
147186
git log --pretty="format:%>(40)%s" >actual &&
148187
# complete the incomplete line at the end

Diff for: utf8.c

+46
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,52 @@ void strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
421421
free(tmp);
422422
}
423423

424+
void strbuf_utf8_replace(struct strbuf *sb_src, int pos, int width,
425+
const char *subst)
426+
{
427+
struct strbuf sb_dst = STRBUF_INIT;
428+
char *src = sb_src->buf;
429+
char *end = src + sb_src->len;
430+
char *dst;
431+
int w = 0, subst_len = 0;
432+
433+
if (subst)
434+
subst_len = strlen(subst);
435+
strbuf_grow(&sb_dst, sb_src->len + subst_len);
436+
dst = sb_dst.buf;
437+
438+
while (src < end) {
439+
char *old;
440+
size_t n;
441+
442+
while ((n = display_mode_esc_sequence_len(src))) {
443+
memcpy(dst, src, n);
444+
src += n;
445+
dst += n;
446+
}
447+
448+
old = src;
449+
n = utf8_width((const char**)&src, NULL);
450+
if (!src) /* broken utf-8, do nothing */
451+
return;
452+
if (n && w >= pos && w < pos + width) {
453+
if (subst) {
454+
memcpy(dst, subst, subst_len);
455+
dst += subst_len;
456+
subst = NULL;
457+
}
458+
w += n;
459+
continue;
460+
}
461+
memcpy(dst, old, src - old);
462+
dst += src - old;
463+
w += n;
464+
}
465+
strbuf_setlen(&sb_dst, dst - sb_dst.buf);
466+
strbuf_attach(sb_src, strbuf_detach(&sb_dst, NULL),
467+
sb_dst.len, sb_dst.alloc);
468+
}
469+
424470
int is_encoding_utf8(const char *name)
425471
{
426472
if (!name)

Diff for: utf8.h

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ void strbuf_add_wrapped_text(struct strbuf *buf,
1515
const char *text, int indent, int indent2, int width);
1616
void strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
1717
int indent, int indent2, int width);
18+
void strbuf_utf8_replace(struct strbuf *sb, int pos, int width,
19+
const char *subst);
1820

1921
#ifndef NO_ICONV
2022
char *reencode_string_iconv(const char *in, size_t insz,

0 commit comments

Comments
 (0)