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

liuxun 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 c0bdd468d [#5768] improvement(CLI): improve formatted output (#5770)
c0bdd468d is described below

commit c0bdd468df21a6b9a561f976f92c551c08333f0f
Author: Lord of Abyss <[email protected]>
AuthorDate: Sat Dec 7 12:27:15 2024 +0800

    [#5768] improvement(CLI): improve formatted output (#5770)
    
    ### What changes were proposed in this pull request?
    
    Enhanced the Gravitino CLI to support properly formatted output. Fixed
    alignment issues in formatted output when it includes Chinese
    characters.
    The bounding box length calculation is now based on the number of
    characters rather than the character display width . The correct output
    should look like this(Here are the results of my local tests):
    
    <img width="752" alt="image"
    
src="https://github.com/user-attachments/assets/ae880b4b-280d-4dc4-9a25-f0deb3867bbc";>
    
    Only change the implementation of the TableFormatImpl class, the same
    effect is achieved when the `catalog list --output table` command is
    supported
    
    ### Why are the changes needed?
    
    Fix: #5768
    
    ### Does this PR introduce _any_ user-facing change?
    
    NO.
    
    ### How was this patch tested?
    
    ```shell
    gcli catalog details --name <catalog>  --metalake <metalake> --output table
    gcli metalake details --name <metalake>  --output table
    gcli metalake list --output table
    ```
    
    ---------
    
    Co-authored-by: pancx <[email protected]>
---
 .../apache/gravitino/cli/outputs/TableFormat.java  | 55 +++++++++++++++++++---
 .../cli/integration/test/TableFormatOutputIT.java  | 50 ++++++++++++++++++++
 2 files changed, 98 insertions(+), 7 deletions(-)

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 a1975b9f3..8744467b9 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
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.regex.Pattern;
 import org.apache.gravitino.Catalog;
 import org.apache.gravitino.Metalake;
 
@@ -81,6 +82,12 @@ public class TableFormat {
 
   static final class TableFormatImpl {
     private int[] maxElementLengths;
+    // This expression is primarily used to match characters that have a 
display width of
+    // 2, such as characters from Korean, Chinese
+    private static final Pattern FULL_WIDTH_PATTERN =
+        Pattern.compile(
+            
"[\u1100-\u115F\u2E80-\uA4CF\uAC00-\uD7A3\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE6F\uFF00-\uFF60\uFFE0-\uFFE6]");
+    private int[][] elementOutputWidths;
     private final String horizontalDelimiter = "-";
     private final String verticalDelimiter = "|";
     private final String crossDelimiter = "+";
@@ -96,10 +103,9 @@ public class TableFormat {
         throw new IllegalArgumentException("Number of columns is not equal.");
       }
       maxElementLengths = new int[headers.size()];
+      elementOutputWidths = new int[rows.size()][headers.size()];
       updateMaxLengthsFromList(headers);
       updateMaxLengthsFromNestedList(rows);
-
-      // print headers
       printLine();
       System.out.println();
       for (int i = 0; i < headers.size(); ++i) {
@@ -115,9 +121,22 @@ public class TableFormat {
       for (int i = 0; i < rows.size(); ++i) {
         List<String> columns = rows.get(i);
         for (int j = 0; j < columns.size(); ++j) {
-          System.out.printf(
-              verticalDelimiter + indent + "%-" + maxElementLengths[j] + "s" + 
indent,
-              columns.get(j));
+          String column = columns.get(j);
+          // Handle cases where the width and number of characters are 
inconsistent
+          if (elementOutputWidths[i][j] != column.length()) {
+            if (elementOutputWidths[i][j] > maxElementLengths[j]) {
+              System.out.printf(
+                  verticalDelimiter + indent + "%-" + column.length() + "s" + 
indent, column);
+            } else {
+              int paddingLength =
+                  maxElementLengths[j] - (elementOutputWidths[i][j] - 
column.length());
+              System.out.printf(
+                  verticalDelimiter + indent + "%-" + paddingLength + "s" + 
indent, column);
+            }
+          } else {
+            System.out.printf(
+                verticalDelimiter + indent + "%-" + maxElementLengths[j] + "s" 
+ indent, column);
+          }
         }
         System.out.println(verticalDelimiter);
       }
@@ -130,20 +149,42 @@ public class TableFormat {
       String s;
       for (int i = 0; i < elements.size(); ++i) {
         s = elements.get(i);
-        if (s.length() > maxElementLengths[i]) maxElementLengths[i] = 
s.length();
+        if (getOutputWidth(s) > maxElementLengths[i]) maxElementLengths[i] = 
getOutputWidth(s);
       }
     }
 
     private void updateMaxLengthsFromNestedList(List<List<String>> elements) {
+      int rowIdx = 0;
       for (List<String> row : elements) {
         String s;
         for (int i = 0; i < row.size(); ++i) {
           s = row.get(i);
-          if (s.length() > maxElementLengths[i]) maxElementLengths[i] = 
s.length();
+          int consoleWidth = getOutputWidth(s);
+          elementOutputWidths[rowIdx][i] = consoleWidth;
+          if (consoleWidth > maxElementLengths[i]) maxElementLengths[i] = 
consoleWidth;
         }
+        rowIdx++;
       }
     }
 
+    private int getOutputWidth(String s) {
+      int width = 0;
+      for (int i = 0; i < s.length(); i++) {
+        width += getCharWidth(s.charAt(i));
+      }
+
+      return width;
+    }
+
+    private static int getCharWidth(char ch) {
+      String s = String.valueOf(ch);
+      if (FULL_WIDTH_PATTERN.matcher(s).find()) {
+        return 2;
+      }
+
+      return 1;
+    }
+
     private void printLine() {
       System.out.print(crossDelimiter);
       for (int i = 0; i < maxElementLengths.length; ++i) {
diff --git 
a/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java
 
b/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java
index 55cab8c5b..89034d642 100644
--- 
a/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java
+++ 
b/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java
@@ -62,6 +62,24 @@ public class TableFormatOutputIT extends BaseIT {
       gravitinoUrl
     };
     Main.main(create_catalog_args);
+
+    String[] create_catalog_with_comment_args = {
+      "catalog",
+      "create",
+      commandArg(GravitinoOptions.METALAKE),
+      "my_metalake",
+      commandArg(GravitinoOptions.NAME),
+      "postgres2",
+      commandArg(GravitinoOptions.PROVIDER),
+      "postgres",
+      commandArg(GravitinoOptions.PROPERTIES),
+      
"jdbc-url=jdbc:postgresql://postgresql-host/mydb,jdbc-user=user,jdbc-password=password,jdbc-database=db,jdbc-driver=org.postgresql.Driver",
+      commandArg(GravitinoOptions.URL),
+      gravitinoUrl,
+      commandArg(GravitinoOptions.COMMENT),
+      "catalog, 用于测试"
+    };
+    Main.main(create_catalog_with_comment_args);
   }
 
   @Test
@@ -160,6 +178,38 @@ public class TableFormatOutputIT extends BaseIT {
         output);
   }
 
+  @Test
+  public void testCatalogDetailsCommandFullCornerCharacter() {
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    PrintStream originalOut = System.out;
+    System.setOut(new PrintStream(outputStream));
+
+    String[] args = {
+      "catalog",
+      "details",
+      commandArg(GravitinoOptions.METALAKE),
+      "my_metalake",
+      commandArg(GravitinoOptions.NAME),
+      "postgres2",
+      commandArg(GravitinoOptions.OUTPUT),
+      "table",
+      commandArg(GravitinoOptions.URL),
+      gravitinoUrl
+    };
+    Main.main(args);
+    // Restore the original System.out
+    System.setOut(originalOut);
+    // Get the output and verify it
+    String output = new String(outputStream.toByteArray(), 
StandardCharsets.UTF_8).trim();
+    assertEquals(
+        "+-----------+------------+-----------------+-------------------+\n"
+            + "| catalog   | type       | provider        | comment           
|\n"
+            + 
"+-----------+------------+-----------------+-------------------+\n"
+            + "| postgres2 | RELATIONAL | jdbc-postgresql | catalog, 用于测试 |\n"
+            + 
"+-----------+------------+-----------------+-------------------+",
+        output);
+  }
+
   private String commandArg(String arg) {
     return String.format("--%s", arg);
   }

Reply via email to