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
+8 -2
View File
@@ -44,6 +44,7 @@ from .selector import (
SessionSelector,
StopSessionOutcome,
)
from .text import display_width, truncate_display
DEFAULT_SOCKET_NAME = "herdr-hub"
@@ -199,13 +200,18 @@ def validate_remote_target(target: str | None) -> None:
def truncate_label(label: str, limit: int = 48) -> str:
"""Clip a tmux window label to ``limit`` terminal cells.
tmux renders names by cell, so clipping by code point let CJK names run
twice as wide as ASCII ones before the ellipsis appeared.
"""
clean = "".join(
character if ord(character) >= 32 and ord(character) != 127 else "?"
for character in label
)
if len(clean) <= limit:
if display_width(clean) <= limit:
return clean
return clean[: limit - 1] + "…"
return truncate_display(clean, limit - 1) + "…"
def display_target(target: str) -> str: