From 7a03a10a3a746dd8565a3a0e6126f60523b41738 Mon Sep 17 00:00:00 2001 From: Jiang Xin Date: Sat, 15 Nov 2025 08:36:11 -0500 Subject: [PATCH] builtin/repo: fix table alignment for UTF-8 characters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Junio C Hamano --- builtin/repo.c | 21 +++++++++++++++++---- t/unit-tests/u-utf8-width.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/builtin/repo.c b/builtin/repo.c index 9d4749f79b..e3adb353a2 100644 --- a/builtin/repo.c +++ b/builtin/repo.c @@ -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) diff --git a/t/unit-tests/u-utf8-width.c b/t/unit-tests/u-utf8-width.c index 3766f19726..86e09c3574 100644 --- a/t/unit-tests/u-utf8-width.c +++ b/t/unit-tests/u-utf8-width.c @@ -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); +}