This is an automated email from the ASF dual-hosted git repository.

jmclean pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 3274845137 [#7685] fix(cli): correct table alignment for multi-byte 
characters b… (#7719)
3274845137 is described below

commit 327484513795354ce889184b6dd9665ef2750052
Author: 신동재 <[email protected]>
AuthorDate: Thu Jul 17 15:24:18 2025 +0900

    [#7685] fix(cli): correct table alignment for multi-byte characters b… 
(#7719)
    
    [#7685] fix(cli): use display width to align table output for multibyte
    characters
    
    ---
    
    ## What changes were proposed in this pull request?
    
    - Replace `String.length()` checks with `LineUtil.getDisplayWidth()` to
    correctly calculate character width for multibyte characters.
    ---
    
    ## Why are the changes needed?
    
    Currently, table output in the CLI uses `String.length()` to calculate
    cell width. This causes misalignment when rendering multibyte characters
    such as Korean, Japanese, or Chinese characters.
    
    Fixes: #7685
    
    ---
    
    ## Does this PR introduce _any_ user-facing change?
    
    - Yes, Tables displayed in the CLI will now correctly align columns when
    using multibyte characters.
    
    ## How was this patch tested?
    
    - Not committed yet, but tested locally with unit tests.
    
    ```java
    @Test
    void testMultiByteCharacterTableFormat() {
      CommandContext mockContext = TestCliUtil.getMockContext();
    
      Column columnA = new Column(mockContext, "이름", 
Column.HorizontalAlign.LEFT, Column.HorizontalAlign.LEFT);
      Column columnB = new Column(mockContext, "설명", 
Column.HorizontalAlign.LEFT, Column.HorizontalAlign.LEFT);
    
      TableFormat<String> tableFormat =
          new TableFormat<String>(mockContext) {
            @Override
            public String getOutput(String entity) {
              return null;
            }
          };
    
      String eol = System.lineSeparator();
    
      String expected =
          "+--------+--------------+" + eol
              + "|  이름  |     설명     |" + eol
              + "+--------+--------------+" + eol
              + "| 홍길동 | 테스트입니다 |" + eol
              + "| 김철수 | 멀티바이트   |" + eol
              + "| 이영희 | 길이체크     |" + eol
              + "+--------+--------------+";
    
      String outputString = tableFormat.getTableFormat(columnA, columnB).trim();
      Assertions.assertEquals(expected, outputString);
    }
    ```
---
 .../apache/gravitino/cli/outputs/TableFormat.java  |  2 +-
 .../gravitino/cli/output/TestTableFormat.java      | 40 ++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git 
a/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java
index 7519150b13..b9c155ca87 100644
--- 
a/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java
+++ 
b/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java
@@ -470,7 +470,7 @@ public abstract class TableFormat<T> extends 
BaseOutputFormat<T> {
       throws IOException {
 
     osw.write(LineUtil.getSpaces(minPadding));
-    if (str.length() < maxLength) {
+    if (LineUtil.getDisplayWidth(str) < maxLength) {
       int leftPadding =
           align == Column.HorizontalAlign.LEFT
               ? 0
diff --git 
a/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java
 
b/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java
index 5b9cb88039..66d58bddc4 100644
--- 
a/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java
+++ 
b/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java
@@ -910,4 +910,44 @@ public class TestTableFormat {
             + "+--------+",
         output);
   }
+
+  @Test
+  void testMultiByteCharacterTableFormat() {
+    CommandContext mockContext = TestCliUtil.getMockContext();
+
+    Column columnA = new Column(mockContext, "이름");
+    Column columnB = new Column(mockContext, "설명");
+
+    columnA.addCell("홍길동").addCell("김철수").addCell("이영희");
+    columnB.addCell("테스트입니다").addCell("설명문구").addCell("멀티바이트");
+
+    TableFormat<String> tableFormat =
+        new TableFormat<String>(mockContext) {
+          @Override
+          public String getOutput(String entity) {
+            return null;
+          }
+        };
+
+    String outputString = tableFormat.getTableFormat(columnA, columnB).trim();
+
+    String eol = System.lineSeparator();
+
+    String expected =
+        "+--------+--------------+"
+            + eol
+            + "|  이름  |     설명     |"
+            + eol
+            + "+--------+--------------+"
+            + eol
+            + "| 홍길동 | 테스트입니다 |"
+            + eol
+            + "| 김철수 | 설명문구     |"
+            + eol
+            + "| 이영희 | 멀티바이트   |"
+            + eol
+            + "+--------+--------------+";
+
+    Assertions.assertEquals(expected.trim(), outputString.trim());
+  }
 }

Reply via email to