

终端模拟器下宽字符退格
source link: http://maskray.me/blog/2016-03-22-terminal-emulator-fullwidth-backspace
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

折腾完https://maskray.me/blog/2016-03-13-terminal-emulator-fullwidth-color-emoji后发现canonical mode下emoji字符退格只后退了一列,后发现所有宽字符都有问题,因此做了一番调研。
Canonical/noncanonical mode
早期Unix有cooked/cbreak/raw mode三种模式,raw mode和cbreak模式区别在于signal和输入输出处理,输入都是以字符为单位,即read(STDIN_FILENO, buf, 1)
在键入一个字符后即返回。Cooked mode与它们差别较大,最重要的区别是终端输入以行为单位进行,并自带一个基础行编辑器,可以使用退格和WERASE(默认为^W
)删除光标前的单词。
termios引入后对输入输出行为(input/output/local modes)有了更精细的控制,通过一些选项可以定制出原始的cooked/cbreak/raw mode三种模式。Local modes中的ICANON
最为重要,区分canonical/noncanonical mode,canonical mode与早期cooked mode类似,带行编辑器,一些字符如CR EOF EOL ERASE KILL NL WERASE等有特殊含义,下面介绍几个比较重要的。更多介绍参见The Linux Programming Interface 62.4 Terminal Special Characters。
通常为^D
,可以用ctrl d
输入,作用是使得read()
立即返回该行所有字符,若位于行首则返回0。很多地方把它视为到达文件结束位置的信号,并不再继续读入。但实际上终端输入并没有被关闭,仍可以继续读取字符。
编译运行上面C程序,试试输入若干字符后按^D
的输出。
ERASE
stty -a
中erase =
显示当前ERASE字符设置,通常为^?
或^H
。终端模拟器vte是^?
,退格键发送^?
;xterm是^H
,退格键发送^H
。倘若终端ERASE字符与之不同则可能导致退格不删除字符反而输入了一个^?
或^H
。
通常为^C
,若local modes中ISIG
开启,则前台进程组会收到SIGINT。
通常为^\
,若local modes中ISIG
开启,则前台进程组会收到SIGQUIT。
通常为^Z
,若local modes中ISIG
开启,则前台进程组会收到SIGTSTP,默认会停止成为后台任务,shell回到前台。
对于readline等使用noncanonical mode的应用程序,它们会检测TERM
环境变量获取terminfo信息,从中找出不同功能对应的输出字符序列。
\b
字符的解析方式是光标左移一格。
在canonical mode下当前行仅有一个两个宽字符时,按下退格,光标左移一格并擦除了该字符,但继续按退格也无法回到行首,产生显示问题。
原因是内核tty驱动似乎没有考虑字符宽度信息,只给pseudoterminal master发送一个\b
,终端模拟器收到\b
后将光标左移了一格。再次按退格时,内核tty驱动判断该行已空,因此不再发送\b
,光标也就无法退回到行首。
介绍一个测试方式:在pseudoterminal的slave端运行canonical mode的cat
程序,输入退格,可以在master端看到内核发来"\b \b"
三个字符,即后退一格,空格擦除,再后退一格。可以用下面的方法查看:
termite -e cat
创建一个termite终端运行cat
,然后找出termite在pseudoterminal pair的master端的fd:
之后用strace -e read -p $(pgrep -n termite) |& grep 13
,在termite窗口键入退格,观察master端fd读到的数据。
这很可能是内核的问题,简易的修复方式是头痛医脚,修改使用pseudoterminal的程序(如终端模拟器、tmux)的代码。对于canonical mode并开启IUTF8
时,从pseudoterminal master处读到\b
时,判断左侧字符是否为宽字符,是则左移2格(目前尚无更宽的字符)。我做了两个patch:
于是这是我第一次和第二次创建PKGBUILD……
- https://blog.nelhage.com/2009/12/a-brief-introduction-to-termios-termios3-and-stty/
info '(libc) Terminal Modes'
Recommend
-
27
作者: HelloGitHub-ChungZH 当你逐渐厌倦了 cmd 的枯燥黑屏、powershell 的单调蓝底,可以来尝...
-
14
终端模拟器下使用双倍宽度多色Emoji字体 2017年8月更新。 多色Emoji字体 Cairo支持 较新的FreeType支持多色,但cairo-1.14.6没有默认开启支持。
-
8
理解 Linux 终端、终端模拟器和伪终端 2 你可能听说过 TTY 和 PTY 这些缩写,也在 /dev 目录下看到过 /dev/tty[n] 设备,大概知道它们和 Linux 终端...
-
5
Wez:Rust编写的类似Powershell的终端模拟器 WezTerm 是一个 GPU 加速的跨平台终端模拟器和多路复用器,可在 Linux、macOS、Windows 10 和 FreeBS...
-
8
1 万 Star!基于 Android 平台的开源 Linux 终端模拟器-51CTO.COM 1 万 Star!基于 Android 平台的开源 Linux 终端模拟器 2022-02-14 10:29:40 Termux[1] 是一款基于 Android 平台的开源 Linux 终端模拟器...
-
6
在 Microsoft Build 2019 的大会上,微软给我们带来了一款全新设计的终端模拟器 Microsoft Terminal. 虽然过度好看的宣传片和实际的效果有着巨大的落差,但是也不影响它在 Windows 阵营里取得最高的颜值称号。
-
8
Fig CLI命令...
-
4
号称当前最快的终端模拟器alacrity 作者: dreamfly 分类: software 发布时间: 2022-10-12 09:39 作为一个后端程序员,我们每天都要和终端打交道,...
-
4
超级强大的终端模拟器-rust开发的支持gpu渲染采用lua配置的多路复用模拟器 对于后端开发人员来说,每天接触最多的就是终端了,而一款趁手的工具对于工作效率来说至关重要,可以起到事半功倍的效果。 wezterm就是一款不可多得非常好用的终端模...
-
8
EPLAN2022十天入门-退格键妙用&课程总结 01/17 15:41 作者:工控PLC布道师 阅读需 1 分钟 加...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK