为什么在 xterm + tmux 中按 Ctrl-h 会发送“^?”?

为什么在 xterm + tmux 中按 Ctrl-h 会发送“^?”?

xterm:

$ echo $TERM
xterm-256color
$ stty -a
speed 38400 baud; rows 52; columns 91; line = 0;
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany
-imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

gnome-terminal:

$ echo $TERM
xterm-256color
$ stty -a
speed 38400 baud; rows 57; columns 100; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc ixany imaxbel
iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

当在室外时tmuxCtrl--v Ctrl输出h^H在里面tmux,我开始了解^?if run from xterm。从它内部screen运行xterm仍然输出^H。这背后的原因是什么?应该输出^H还是^??如何补救?

答案1

原因是,在您的 xterm 中,^H是该erase字符,并且tmux显然将该erase字符转换为它模拟的终端的相应控制字符 ( ^?),以便擦除按预期进行煮熟模式(例如,当您键入 时会发生什么cat)。如果您使用带有^?擦除字符(由密钥生成)的终端,然后使用用作擦除字符(由密钥生成)Backspace的终端恢复会话,则需要进行转换。不幸的是,这在某些情况下会产生明显的副作用,例如,如果您输入+ 。^HBackspaceCtrlH

唯一好的补救措施是确保所有终端(真实的或 tmux 中的)使用相同的erase字符,这应该是^?(这是当今的标准)。看来你的 xterm 配置错误。 AFAIK,这不是默认配置。

无论如何,您需要确保使用一个TERM值来表示kbs=\177。然而这是不是xterm-256color来自官方 ncurses的案例。因此,您要么需要选择不同的TERM值,要么需要修复kbs条目xterm-256color(这可以由最终用户使用:infocmp > file、 修改file,然后 来完成tic file)。有些Linux发行版没有这个问题;例如,Debian 通过debian/xterm.ti其源代码包中的一个文件修复了这个问题ncurses,给出:

$ infocmp xterm-256color | grep kbs
        kbs=\177, kcbt=\E[Z, kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC,

您还应该有:

$ appres XTerm | grep backarrowKeyIsErase:
*backarrowKeyIsErase:   true

请注意,您可以stty erase '^?'在 xterm 中执行此操作(在执行其他操作之前),但这只是一种解决方法(并且可能会破坏密钥的行为Backspace)。默认情况下,您实际上应该具有erase = ^?(如所示stty -a)!

如果问题和Backspace/或Delete仍然存在,我建议一致的 BackSpace 和删除配置安妮·巴雷塔 (Anne Baretta) 的文件。

答案2

这里或其他地方的解决方案都不适合我。有效的是将以下内容添加到我的$HOME/.tmux.conf文件中:

bind-key -n Bspace send-keys C-h

这使得 tmux在按下时Ctrl发送。HBackspace


我在下面提供了一些评论、背景和咆哮,所以请随意停止阅读这里。 -:)


我不同意vinc17的观点,即“唯一好的补救措施”是使退格/擦除字符仅是^?。用户应该能够按照他或她认为合适的方式进行配置。

自实际终端出现以来,对于我们许多使用 Unix 的人来说,一个常见的解决方案是使用 ^H 表示 Backspace 和 ^?用于 DEL(即在光标之后删除,而不是之前删除)。 Ctrl-H 和 Backspace 之间的区别过去和现在并不总是必要的,特别是对于 CLI/终端程序。

我一直在使用 ^H / ^? 的映射自 80 年代末以来,在许多机器上,以及自从真实终端“消亡”以来,对于终端程序和虚拟控制台,我一直使用 Backspace / DEL 键(分别),并且不想在我的所有机器和那些机器上重新配置我的擦除字符。我的客户(很多很多机器)要使用 Backspace 发送 ^?工作。

我根据各种帖子尝试了各种方法,让 tmux 发送 Ctrl-H 进行退格键。特别是,“bind-key -n Ch send-keys Ch”不起作用让我感到沮丧,因为我在 Terminator 中使用 tmux,并且我知道我的 Terminator 设置为在按下 Backspace 键时发送 Ctrl-H。我花了很长时间才偶然发现一篇列出可用 tmux 键名称的帖子,这是我找到 Bspace 键名称的地方,幸运的是,它可以让 ^H 字符正确地通过 tmux(Ubuntu 16.04 上的 tmux 版本 2.1-3build1)。 02)。

答案3

由于 xfce4-terminal 中滚动缓慢而切换到 xterm 后,我遇到了同样的问题。在 ~/.Xresources 中,我设置了 XTerm*ptyInitialErase: true .请参阅 xterm 手册页。此设置将^Hvs.留给^?伪终端。为了测试这一点,我执行了 Ctrl-V Ctrl-H,确实输出了^H

相关内容