unicode - 诅咒 - 某些表情符号(标志)使终端输出变形
问题描述
当我将某些表情符号(特别是标志)输出到 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)
产生:
如果您仅将表情符号切换为心,则效果很好:
我知道国旗表情符号是一系列区域指示符号,但我认为这应该可行,但我不确定如何解决它。
我已经在 Mac OS 10.13 和 10.14 上的 iTerm 和终端中对此进行了测试。
(我还注意到其他一些多点表情符号()在原始 Python 中打印良好,但在诅咒中被分成两个独立的表情符号组成它们。我不确定这是否相关。)
解决方案
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
在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
我没有看到那些后来通过Unicode 12(当前)发生了变化。
wcwidth
考虑到所有这些,它看起来像是字体和/或 wcwidth 中的错误,这是由惯性带来的(在 Apple 开始同意其字体之前,您无能为力)。
顺便说一句,您可能会在与问题相关的两个区域指示符之间找到关于使用零宽度连接器 (ZWJ)的建议。
推荐阅读
- vba - Markdown to Word:如何将纯文本标题和交叉引用转换为链接的 Word-ones?
- java - 无法在 VSCode 中运行 Java?
- javascript - 如何仅在单击按钮的行更新按钮?
- javascript - 影响 nodejs 应用程序性能的正则表达式。如何在javascript中替换改进的正则表达式?
- jbpm - Flowable - 主动被动部署
- javascript - 为什么我的标签在我的侧边栏导航中不起作用?
- mongodb - NextAuth - AccessToken 未使用 MongoDB 和 Coinbase 刷新
- python - 如何将数据框附加到excel
- graph-theory - 计算泛洪期间生成的消息数量
- flutter - 如何在颤动中绘制曲线