诅咒 - 某些表情符号(标志)使终端输出变形

Tom*_*ony 5 unicode curses ncurses python-curses

当我将某些表情符号(特别是标志)输出到 Curses 的子窗口中时,它会使输出变形,即使是在该子窗口之外的输出也是如此。

跑步:


import curses

def draw_screen(stdscr):

    event = 0
    stdscr.clear()
    stdscr.refresh()

    while (event != ord('q')):

        emojis = ["", "", ""]
        # emojis = ["", "", ""]

        for i, emoji in enumerate(emojis):
            box1 = stdscr.subwin(11, 11, 0, i*12)
            box1.box()
            box1.addstr(0, 4, emoji)

        event = stdscr.getch()

if __name__ == "__main__":
    curses.wrapper(draw_screen)
Run Code Online (Sandbox Code Playgroud)

产生:

在此处输入图片说明

如果你只为心切换表情符号,它工作正常:

在此处输入图片说明

我知道国旗表情符号是一系列区域指示符,但我认为这应该可行,但我不确定如何修复它。

我已经在 Mac OS 10.13 和 10.14 上的 iTerm 和终端中对此进行了测试。

(我还注意到其他一些多点表情符号(?)在原始 Python 中打印得很好,但在诅咒中被分成两个单独的表情符号来组成它们。我不确定这是否相关。)

Tho*_*key 8

ncurses 使用操作系统的wcwidth函数来确定字符的显示宽度。Terminal.app 假设 U+1F1FA 和 U+1F1F8 使用两列,而看起来wcwidth它们各只有一列。绿色心脏U + 1F49A由两个处理wcwidth和Terminal.app作为双宽度。您可以通过在表情符号前后附加一个字符来查看这一点:在 ncurses 被误导的情况下,结果显示会显示重叠字符。

重叠的插图

直到 Unicode 9 (2016),根据 Unicode 的 EastAsianWidth 文件,这些特定代码都是“中性宽度”Unicode 技术报告 #11 Unicode 字符属性“东亚宽度”(来自 1999 年)暗示(从未提供明确定义)“中性宽度”字符的实际宽度取决于上下文,即,如果它们与双角字符,它们应该被视为双角字符。例如,它说

窄(和中性)字符始终映射到混合宽度集中的半角字符

但仅在“全角”(两列)和“窄角”(一列)字符的混合方面指代“混合宽度”。

wcwidth函数通常(MacOS 可能也不例外)为给定的代码点返回相同的宽度,而忽略区域设置。

Unicode 8 中,这些是相关的行(一系列值):

1F1E6..1F1FF;N   # So    [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
1F400..1F579;N   # So   [378] RAT..JOYSTICK
Run Code Online (Sandbox Code Playgroud)

Unicode 9 中, U+1F49A 是“全宽”,但其他两个是中性的:

1F1E6..1F1FF;N   # So    [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
1F442..1F4FC;W   # So   [187] EAR..VIDEOCASSETTE
Run Code Online (Sandbox Code Playgroud)

我没有看到那些后来通过Unicode 12(当前)发生了变化。

鉴于所有这些,它看起来像是字体和/或 wcwidth 中的错误,这是惯性导致的(在 Apple 开始wcwidth同意其字体之前,您无能为力)。

顺便说一下,您可能会发现有关在与问题相关的两个区域指标符号之间使用零宽度连接器 (ZWJ) 的建议

  • 谢谢@Thomas 的详细回复。这一切都说得通,并且符合我对问题症结的直觉(但与实际细节一致!)。我曾希望可能有一些其他的 Unicode 字符我可以用来“填充”它(一个 Unicode 字符,它具有 wcwidth 但在终端/iTerm 中没有显示宽度)。 (3认同)