fetch: align per-ref summary report in UTF-8 locales
fetch does printf("%-*s", width, "foo") where "foo" can be a utf-8 string, but width is in bytes, not columns. For ASCII it's fine as one byte takes one column. For utf-8, this may result in misaligned ref summary table. Introduce gettext_width() function that returns the string length in columns (currently only supports utf-8 locales). Make the code use TRANSPORT_SUMMARY(x) where the length is compensated properly in non-English locales. 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
Sep 4, 2012 at 17:39 UTC
754395d3052fc0d46948b2ff7006b3c6701785c8
4 files changed
+26
-10
builtin/fetch.c
+7
-8
@@ -255,9 +255,8 @@ static int update_local_ref(struct ref *ref,
255
if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
256
if (verbosity > 0)
257
strbuf_addf(display, "= %-*s %-*s -> %s",
258
- TRANSPORT_SUMMARY_WIDTH,
259
- _("[up to date]"), REFCOL_WIDTH,
260
- remote, pretty_ref);
258
+ TRANSPORT_SUMMARY(_("[up to date]")),
259
+ REFCOL_WIDTH, remote, pretty_ref);
260
return 0;
261
}
262
@@ -271,7 +270,7 @@ static int update_local_ref(struct ref *ref,
270
*/
271
strbuf_addf(display,
272
_("! %-*s %-*s -> %s (can't fetch in current branch)"),
274
- TRANSPORT_SUMMARY_WIDTH, _("[rejected]"),
273
+ TRANSPORT_SUMMARY(_("[rejected]")),
274
REFCOL_WIDTH, remote, pretty_ref);
275
return 1;
276
}
@@ -282,7 +281,7 @@ static int update_local_ref(struct ref *ref,
281
r = s_update_ref("updating tag", ref, 0);
282
strbuf_addf(display, "%c %-*s %-*s -> %s%s",
283
r ? '!' : '-',
285
- TRANSPORT_SUMMARY_WIDTH, _("[tag update]"),
284
+ TRANSPORT_SUMMARY(_("[tag update]")),
285
REFCOL_WIDTH, remote, pretty_ref,
286
r ? _(" (unable to update local ref)") : "");
287
return r;
@@ -317,7 +316,7 @@ static int update_local_ref(struct ref *ref,
316
r = s_update_ref(msg, ref, 0);
317
strbuf_addf(display, "%c %-*s %-*s -> %s%s",
318
r ? '!' : '*',
320
- TRANSPORT_SUMMARY_WIDTH, what,
319
+ TRANSPORT_SUMMARY(what),
320
REFCOL_WIDTH, remote, pretty_ref,
321
r ? _(" (unable to update local ref)") : "");
322
return r;
@@ -357,7 +356,7 @@ static int update_local_ref(struct ref *ref,
356
return r;
357
} else {
358
strbuf_addf(display, "! %-*s %-*s -> %s %s",
360
- TRANSPORT_SUMMARY_WIDTH, _("[rejected]"),
359
+ TRANSPORT_SUMMARY(_("[rejected]")),
360
REFCOL_WIDTH, remote, pretty_ref,
361
_("(non-fast-forward)"));
362
return 1;
@@ -554,7 +553,7 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map)
553
result |= delete_ref(ref->name, NULL, 0);
554
if (verbosity >= 0) {
555
fprintf(stderr, " x %-*s %-*s -> %s\n",
557
- TRANSPORT_SUMMARY_WIDTH, _("[deleted]"),
556
+ TRANSPORT_SUMMARY(_("[deleted]")),
557
REFCOL_WIDTH, _("(none)"), prettify_refname(ref->name));
558
warn_dangling_symref(stderr, dangling_msg, ref->name);
559
}
gettext.c
+13
-2
@@ -4,6 +4,8 @@
4
5
#include "git-compat-util.h"
6
#include "gettext.h"
7
+#include "strbuf.h"
8
+#include "utf8.h"
9
10
#ifndef NO_GETTEXT
11
# include <locale.h>
@@ -27,10 +29,9 @@ int use_gettext_poison(void)
29
#endif
30
31
#ifndef NO_GETTEXT
32
+static const char *charset;
33
static void init_gettext_charset(const char *domain)
34
{
32
- const char *charset;
33
-
35
/*
36
This trick arranges for messages to be emitted in the user's
37
requested encoding, but avoids setting LC_CTYPE from the
@@ -128,4 +129,14 @@ void git_setup_gettext(void)
129
init_gettext_charset("git");
130
textdomain("git");
131
}
132
+
133
+/* return the number of columns of string 's' in current locale */
134
+int gettext_width(const char *s)
135
+{
136
+ static int is_utf8 = -1;
137
+ if (is_utf8 == -1)
138
+ is_utf8 = !strcmp(charset, "UTF-8");
139
+
140
+ return is_utf8 ? utf8_strwidth(s) : strlen(s);
141
+}
142
#endif
gettext.h
+5
@@ -30,10 +30,15 @@
30
31
#ifndef NO_GETTEXT
32
extern void git_setup_gettext(void);
33
+extern int gettext_width(const char *s);
34
#else
35
static inline void git_setup_gettext(void)
36
{
37
}
38
+static inline int gettext_width(const char *s)
39
+{
40
+ return strlen(s);
41
+}
42
#endif
43
44
#ifdef GETTEXT_POISON
transport.h
+1
@@ -106,6 +106,7 @@ struct transport {
106
#define TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND 256
107
108
#define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
109
+#define TRANSPORT_SUMMARY(x) (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x)
110
111
/* Returns a transport suitable for the url */
112
struct transport *transport_get(struct remote *, const char *);