Add utf8_fprintf helper that returns correct number of columns
authorJiang Xin <worldhello.net@gmail.com>
Sat, 9 Feb 2013 06:31:09 +0000 (14:31 +0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 11 Feb 2013 19:29:45 +0000 (11:29 -0800)
Since command usages can be translated, they may include utf-8
encoded strings, and the output in console may not align well any
more. This is because strlen() is different from strwidth() on utf-8
strings.

A wrapper utf8_fprintf() can help to return the correct number of
columns required.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Reviewed-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
parse-options.c
utf8.c
utf8.h

index c1c66bd408c50685c06fe7ff1e1c6a78c26be1b1..670bf09b452e5e74a76df17535ea53b133d26091 100644 (file)
@@ -3,6 +3,7 @@
 #include "cache.h"
 #include "commit.h"
 #include "color.h"
+#include "utf8.h"
 
 static int parse_options_usage(struct parse_opt_ctx_t *ctx,
                               const char * const *usagestr,
@@ -491,7 +492,7 @@ static int usage_argh(const struct option *opts, FILE *outfile)
                        s = literal ? "[%s]" : "[<%s>]";
        else
                s = literal ? " %s" : " <%s>";
-       return fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
+       return utf8_fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
 }
 
 #define USAGE_OPTS_WIDTH 24
@@ -550,7 +551,7 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
                if (opts->long_name)
                        pos += fprintf(outfile, "--%s", opts->long_name);
                if (opts->type == OPTION_NUMBER)
-                       pos += fprintf(outfile, "-NUM");
+                       pos += utf8_fprintf(outfile, _("-NUM"));
 
                if ((opts->flags & PARSE_OPT_LITERAL_ARGHELP) ||
                    !(opts->flags & PARSE_OPT_NOARG))
diff --git a/utf8.c b/utf8.c
index 5c61bbe1131e7bbdd939c8b815bd5222b872e3fb..c7bda66e3800abfd49eea2d6fafd95a2403a6b90 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -430,6 +430,27 @@ int same_encoding(const char *src, const char *dst)
        return !strcasecmp(src, dst);
 }
 
+/*
+ * Wrapper for fprintf and returns the total number of columns required
+ * for the printed string, assuming that the string is utf8.
+ */
+int utf8_fprintf(FILE *stream, const char *format, ...)
+{
+       struct strbuf buf = STRBUF_INIT;
+       va_list arg;
+       int columns;
+
+       va_start(arg, format);
+       strbuf_vaddf(&buf, format, arg);
+       va_end(arg);
+
+       columns = fputs(buf.buf, stream);
+       if (0 <= columns) /* keep the error from the I/O */
+               columns = utf8_strwidth(buf.buf);
+       strbuf_release(&buf);
+       return columns;
+}
+
 /*
  * Given a buffer and its encoding, return it re-encoded
  * with iconv.  If the conversion fails, returns NULL.
diff --git a/utf8.h b/utf8.h
index 93ef60042c2fad93184b573f30e771ecddc842be..3ca85c7737bff0b3df449cc9dc32f32230b522e1 100644 (file)
--- a/utf8.h
+++ b/utf8.h
@@ -8,6 +8,7 @@ int utf8_strwidth(const char *string);
 int is_utf8(const char *text);
 int is_encoding_utf8(const char *name);
 int same_encoding(const char *, const char *);
+int utf8_fprintf(FILE *, const char *, ...);
 
 int strbuf_add_wrapped_text(struct strbuf *buf,
                const char *text, int indent, int indent2, int width);