MaYiding

Fix: PDF依赖缺失提示框右侧边框未对齐

使用 unicodedata 计算字符串终端显示宽度,替代原来按字符数填充的方式,
正确处理中文、全角标点和 emoji 等宽字符,使提示框右侧 ║ 对齐。

Co-Authored-By: Claude <noreply@anthropic.com>
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 import os 5 import os
6 import sys 6 import sys
7 import platform 7 import platform
  8 +import unicodedata
8 from pathlib import Path 9 from pathlib import Path
9 from loguru import logger 10 from loguru import logger
10 from ctypes import util as ctypes_util 11 from ctypes import util as ctypes_util
@@ -12,9 +13,48 @@ from ctypes import util as ctypes_util @@ -12,9 +13,48 @@ from ctypes import util as ctypes_util
12 BOX_CONTENT_WIDTH = 62 13 BOX_CONTENT_WIDTH = 62
13 14
14 15
  16 +def _display_width(text: str) -> int:
  17 + """计算字符串在终端中的显示宽度(中文/emoji 等宽字符占 2 列)。"""
  18 + width = 0
  19 + chars = list(text)
  20 + n = len(chars)
  21 + i = 0
  22 + while i < n:
  23 + ch = chars[i]
  24 + cp = ord(ch)
  25 +
  26 + # 零宽:组合标记 / 格式字符(含 Zero Width Joiner 等)
  27 + if unicodedata.category(ch) in ('Mn', 'Me', 'Cf'):
  28 + i += 1
  29 + continue
  30 +
  31 + # East Asian Fullwidth / Wide(中文汉字、全角标点等)
  32 + if unicodedata.east_asian_width(ch) in ('F', 'W'):
  33 + width += 2
  34 + i += 1
  35 + continue
  36 +
  37 + # 补充平面 emoji(U+1F000 及以上,如 📄🍎📖🐧🪟)
  38 + if cp >= 0x1F000:
  39 + width += 2
  40 + i += 1
  41 + continue
  42 +
  43 + # 文本符号 + VS16 (U+FE0F) → emoji 呈现,宽 2 列(如 ⚠️)
  44 + if i + 1 < n and ord(chars[i + 1]) == 0xFE0F:
  45 + width += 2
  46 + i += 2 # 跳过当前字符和 VS16
  47 + continue
  48 +
  49 + width += 1
  50 + i += 1
  51 + return width
  52 +
  53 +
15 def _box_line(text: str = "") -> str: 54 def _box_line(text: str = "") -> str:
16 """Render a single line inside the 66-char help box.""" 55 """Render a single line inside the 66-char help box."""
17 - return f"║ {text:<{BOX_CONTENT_WIDTH}}║\n" 56 + padding = max(0, BOX_CONTENT_WIDTH - _display_width(text))
  57 + return f"║ {text}{' ' * padding}║\n"
18 58
19 59
20 def _get_platform_specific_instructions(): 60 def _get_platform_specific_instructions():