Unify terminal display-width helpers

key_help, selector and control each carried their own East Asian width
and truncation logic with slightly different rules, and cli clipped tmux
labels by code point, so a CJK display name ran twice as wide as an
ASCII one before its ellipsis appeared.

Move the cell-width helpers into herdr_hub.text, make truncate_label
cell-aware, and sanitise control characters before curses draws a row
so an escape sequence in a remote error cannot be rendered as ^[ and
misalign the list.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 03:09:28 +00:00
co-authored by Claude Fable 5.1
parent d2228ed5fb
commit ac6bb30f47
7 changed files with 194 additions and 136 deletions
+10 -8
View File
@@ -22,10 +22,12 @@ from herdr_hub.selector import (
SelectorResult,
build_main_rows,
filter_rows,
)
from herdr_hub.text import (
display_width,
input_display_line,
pad_terminal_text,
terminal_display_width,
truncate_terminal_text,
pad_display,
truncate_display,
)
@@ -62,11 +64,11 @@ class FakeScreen:
class SelectorCatalogTests(unittest.TestCase):
def test_terminal_display_width_counts_cjk_and_combining_characters(self) -> None:
self.assertEqual(terminal_display_width("Rename: work"), 12)
self.assertEqual(terminal_display_width("显示名称: 工作"), 14)
self.assertEqual(terminal_display_width("e\N{COMBINING ACUTE ACCENT}"), 1)
self.assertEqual(truncate_terminal_text("主机abc", 5), "主机a")
self.assertEqual(terminal_display_width(pad_terminal_text("主机", 6)), 6)
self.assertEqual(display_width("Rename: work"), 12)
self.assertEqual(display_width("显示名称: 工作"), 14)
self.assertEqual(display_width("e\N{COMBINING ACUTE ACCENT}"), 1)
self.assertEqual(truncate_display("主机abc", 5), "主机a")
self.assertEqual(display_width(pad_display("主机", 6)), 6)
self.assertEqual(input_display_line("名称", "abcdefgh", 9), "名称: …gh")
def test_rows_merge_open_running_stopped_and_new_sessions(self) -> None: