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>
Nguyễn Thái Ngọc Duy committed
Apr 19, 2013 at 09:08 UTC
a7f01c6b4ddf9f2f6bdcb23fc7afb56695807cba
5 files changed
+140
-5
Documentation/pretty-formats.txt
+5
-2
@@ -164,8 +164,11 @@ The placeholders are:
164
- '%x00': print a byte from a hex code
165
- '%w([<w>[,<i1>[,<i2>]]])': switch line wrapping, like the -w option of
166
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.
172
- '%<|(<N>)': make the next placeholder take at least until Nth
173
columns, padding spaces on the right if necessary
174
- '%>(<N>)', '%>|(<N>)': similar to '%<(<N>)', '%<|(<N>)'
pretty.c
+48
-3
@@ -776,6 +776,13 @@ enum flush_type {
776
flush_both
777
};
778
779
+enum trunc_type {
780
+ trunc_none,
781
+ trunc_left,
782
+ trunc_middle,
783
+ trunc_right
784
+};
785
+
786
struct format_commit_context {
787
const struct commit *commit;
788
const struct pretty_print_context *pretty_ctx;
@@ -783,6 +790,7 @@ struct format_commit_context {
790
unsigned commit_message_parsed:1;
791
struct signature_check signature_check;
792
enum flush_type flush_type;
793
+ enum trunc_type truncate;
794
char *message;
795
char *commit_encoding;
796
size_t width, indent1, indent2;
@@ -1033,7 +1041,7 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
1041
1042
if (*ch == '(') {
1043
const char *start = ch + 1;
1036
- const char *end = strchr(start, ')');
1044
+ const char *end = start + strcspn(start, ",)");
1045
char *next;
1046
int width;
1047
if (!end || end == start)
@@ -1043,6 +1051,23 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
1051
return 0;
1052
c->padding = to_column ? -width : width;
1053
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
+
1071
return end - placeholder + 1;
1072
}
1073
return 0;
@@ -1309,9 +1334,29 @@ static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
1334
total_consumed++;
1335
}
1336
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
+ }
1358
strbuf_addstr(sb, local_sb.buf);
1314
- else {
1359
+ } else {
1360
int sb_len = sb->len, offset = 0;
1361
if (c->flush_type == flush_left)
1362
offset = padding - len;
t/t4205-log-pretty-formats.sh
+39
@@ -143,6 +143,45 @@ EOF
143
test_cmp expected actual
144
'
145
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
+
185
test_expect_success 'right alignment formatting' '
186
git log --pretty="format:%>(40)%s" >actual &&
187
# complete the incomplete line at the end
utf8.c
+46
@@ -421,6 +421,52 @@ void strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
421
free(tmp);
422
}
423
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
+
470
int is_encoding_utf8(const char *name)
471
{
472
if (!name)
utf8.h
+2
@@ -15,6 +15,8 @@ void strbuf_add_wrapped_text(struct strbuf *buf,
15
const char *text, int indent, int indent2, int width);
16
void strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
17
int indent, int indent2, int width);
18
+void strbuf_utf8_replace(struct strbuf *sb, int pos, int width,
19
+ const char *subst);
20
21
#ifndef NO_ICONV
22
char *reencode_string_iconv(const char *in, size_t insz,