]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/repo: fix table alignment for UTF-8 characters
authorJiang Xin <worldhello.net@gmail.com>
Sat, 15 Nov 2025 13:36:11 +0000 (08:36 -0500)
committerJunio C Hamano <gitster@pobox.com>
Mon, 17 Nov 2025 00:04:24 +0000 (16:04 -0800)
The output table from "git repo structure" is misaligned when displaying
UTF-8 characters (e.g., non-ASCII glyphs). E.g.:

    | 仓库结构   | 值  |
    | -------------- | ---- |
    | * 引用       |      |
    |   * 计数     |   67 |

The previous implementation used simple width formatting with printf()
which didn't properly handle multi-byte UTF-8 characters, causing
misaligned table columns when displaying repository structure
information.

This change modifies the stats_table_print_structure function to use
strbuf_utf8_align() instead of basic printf width specifiers. This
ensures proper column alignment regardless of the character encoding of
the content being displayed.

Also add test cases for strbuf_utf8_align(), a function newly introduced
in "builtin/repo.c".

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/repo.c
t/unit-tests/u-utf8-width.c

index 9d4749f79befa8e383424f9af1b28a6ffa9b9abe..e3adb353a24ae881944340352a4d601972e0404c 100644 (file)
@@ -292,14 +292,20 @@ static void stats_table_print_structure(const struct stats_table *table)
        int name_col_width = utf8_strwidth(name_col_title);
        int value_col_width = utf8_strwidth(value_col_title);
        struct string_list_item *item;
+       struct strbuf buf = STRBUF_INIT;
 
        if (table->name_col_width > name_col_width)
                name_col_width = table->name_col_width;
        if (table->value_col_width > value_col_width)
                value_col_width = table->value_col_width;
 
-       printf("| %-*s | %-*s |\n", name_col_width, name_col_title,
-              value_col_width, value_col_title);
+       strbuf_addstr(&buf, "| ");
+       strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, name_col_title);
+       strbuf_addstr(&buf, " | ");
+       strbuf_utf8_align(&buf, ALIGN_LEFT, value_col_width, value_col_title);
+       strbuf_addstr(&buf, " |");
+       printf("%s\n", buf.buf);
+
        printf("| ");
        for (int i = 0; i < name_col_width; i++)
                putchar('-');
@@ -317,9 +323,16 @@ static void stats_table_print_structure(const struct stats_table *table)
                        value = entry->value;
                }
 
-               printf("| %-*s | %*s |\n", name_col_width, item->string,
-                      value_col_width, value);
+               strbuf_reset(&buf);
+               strbuf_addstr(&buf, "| ");
+               strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, item->string);
+               strbuf_addstr(&buf, " | ");
+               strbuf_utf8_align(&buf, ALIGN_RIGHT, value_col_width, value);
+               strbuf_addstr(&buf, " |");
+               printf("%s\n", buf.buf);
        }
+
+       strbuf_release(&buf);
 }
 
 static void stats_table_clear(struct stats_table *table)
index 3766f19726ed9d074ce14d2372199d5f3f8dd399..86e09c3574a331cc97b73ea46b7adc9a92e14092 100644 (file)
@@ -95,3 +95,40 @@ void test_utf8_width__strnwidth_cjk_with_ansi(void)
        /* "Hello"(5) + "世界"(4) + "!"(1) = 10 */
        cl_assert_equal_i(10, width);
 }
+
+/*
+ * Test the strbuf_utf8_align function with CJK characters
+ */
+void test_utf8_width__strbuf_utf8_align(void)
+{
+       struct strbuf buf = STRBUF_INIT;
+
+       /* Test left alignment with CJK */
+       strbuf_utf8_align(&buf, ALIGN_LEFT, 10, "你好");
+       /* Since "你好" is 4 display columns, we need 6 more spaces to reach 10 */
+       cl_assert_equal_s("你好      ", buf.buf);
+       strbuf_reset(&buf);
+
+       /* Test right alignment with CJK */
+       strbuf_utf8_align(&buf, ALIGN_RIGHT, 8, "世界");
+       /* "世界" is 4 display columns, so we need 4 leading spaces */
+       cl_assert_equal_s("    世界", buf.buf);
+       strbuf_reset(&buf);
+
+       /* Test center alignment with CJK */
+       strbuf_utf8_align(&buf, ALIGN_MIDDLE, 10, "中");
+       /* "中" is 2 display columns, so (10-2)/2 = 4 spaces on left, 4 on right */
+       cl_assert_equal_s("    中    ", buf.buf);
+       strbuf_reset(&buf);
+
+       strbuf_utf8_align(&buf, ALIGN_MIDDLE, 5, "中");
+       /* "中" is 2 display columns, so (5-2)/2 = 1 spaces on left, 2 on right */
+       cl_assert_equal_s(" 中  ", buf.buf);
+       strbuf_reset(&buf);
+
+       /* Test alignment that is smaller than string width */
+       strbuf_utf8_align(&buf, ALIGN_LEFT, 2, "你好");
+       /* Since "你好" is 4 display columns, it should not be truncated */
+       cl_assert_equal_s("你好", buf.buf);
+       strbuf_release(&buf);
+}