Skip to content

Commit 27863e6

Browse files
🎨 Palette: Fix plan details alignment with emojis (#902)
* 🎨 Palette: Fix plan details alignment with emojis * 🎨 Palette: Fix plan details alignment with emojis Co-authored-by: abhimehro <84992105+abhimehro@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
1 parent 9f9b3b1 commit 27863e6

2 files changed

Lines changed: 9 additions & 3 deletions

File tree

.jules/palette.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,7 @@
5959

6060
**Learning:** When displaying data tables or CLI interfaces that calculate widths for alignment (e.g., using `len()` for padding calculations), emojis and full-width characters cause misalignment because they occupy 2 columns in the terminal but count as 1 character in Python's `len()`.
6161
**Action:** Always use a custom display width calculation (like `unicodedata.east_asian_width` or `_display_len`) when calculating padding around strings that may contain emojis or full-width characters to ensure perfect alignment.
62+
63+
## 2025-03-04 - CLI Table Alignment with Emojis
64+
**Learning:** Python's standard `len()` and f-string padding mechanisms fail to correctly align CLI tables when dealing with emojis and full-width characters. These characters typically take 2 terminal columns but count as 1 character in standard string length calculations, causing visual misalignment.
65+
**Action:** Use a custom display width calculation leveraging `unicodedata.east_asian_width` to manually calculate and apply padding lengths for strings containing emojis or CJK characters.

main.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ def print_plan_details(plan_entry: PlanEntry) -> None:
636636
# Calculate max width for alignment
637637
max_name_len = max(
638638
# Use the same default ("Unknown") as when printing, so alignment is accurate
639-
(len(sanitize_for_log(f.get("name", "Unknown"))) for f in folders),
639+
(_display_len(sanitize_for_log(f.get("name", "Unknown"))) for f in folders),
640640
default=0,
641641
)
642642
max_rules_len = max((len(f"{f.get('rules', 0):,}") for f in folders), default=0)
@@ -648,13 +648,15 @@ def print_plan_details(plan_entry: PlanEntry) -> None:
648648

649649
action_text = _get_action_text(folder)
650650

651+
padded_name = _pad_string(name, max_name_len, "<")
652+
651653
if USE_COLORS:
652654
print(
653-
f" • {Colors.BOLD}{name:<{max_name_len}}{Colors.ENDC} : {formatted_rules:>{max_rules_len}} {pluralize(rules_count, 'rule'):<5} {action_text}"
655+
f" • {Colors.BOLD}{padded_name}{Colors.ENDC} : {formatted_rules:>{max_rules_len}} {pluralize(rules_count, 'rule'):<5} {action_text}"
654656
)
655657
else:
656658
print(
657-
f" - {name:<{max_name_len}} : {formatted_rules:>{max_rules_len}} {pluralize(rules_count, 'rule'):<5} {action_text}"
659+
f" - {padded_name} : {formatted_rules:>{max_rules_len}} {pluralize(rules_count, 'rule'):<5} {action_text}"
658660
)
659661

660662
print("")

0 commit comments

Comments
 (0)