通过SecureCRT/putty/WSL的终端,连接Ubuntu服务器的emacs,C-; 功能无作用

服务器是Ubuntu 18.04,

手动安装的emacs 29.1

GNU Emacs 29.1
Copyright (C) 2023 Free Software Foundation, Inc.
GNU Emacs comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of GNU Emacs
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING.

在阅读网页 https://book.emacs-china.org/#org67e621c 的时候, 做了以下配置

(package-install 'embark)
(global-set-key (kbd "C-;") 'embark-act)
(setq prefix-help-command 'embark-prefix-help-command)

按下 Ctrl + ;,没有任何作用。 通过putty、SecureCRT、Wsl的终端去连接服务器,打开emacs后,Ctrl + ; 都是没有任何功能的。

在windows下面,安装windows版本的emacs, Ctrl + ; 则是有作用的。

这个问题和 emacs 版本无关,大概率是终端模拟器的问题,很多终端模拟器会劫走一些热键。。。

以前用 windows 时候试过很多终端模拟器,最后发现 mintty 可以把 ctrl+; 之类的热键给传过去。也许 alacritty 也行,没试过。

但用这种终端的话,你需要自己安装配置 ssh 客户端。

估计是要终端要xterm才行。

可以试试:

export TERM=xterm-256color
emacs -nw  -q

你需要两件事:终端能够传送这个按键,以及emacs能够理解这个按键。

有些键是没有标准传送方法的,参考 https://www.leonerd.org.uk/hacks/fixterms/. 如果你用这个CSI u 编码,可以让你的终端模拟器发送这些编码;比方说我用 iTerm2,配置里面有 ^; (control-;的意思)发送 ^[[59;5u (前面第一个符号是ESC)。 出于兼容性考虑,我并没有给所有按键都适用这个编码。(哪位知道shell下面怎么识别CSI u编码?)

然后在emacs 里面需要在 tty-setup-hook里面加上一些配置。

  ;; CSI u style coding for C-. and C-M-. keys
  (cl-loop for c from ?! to ?~ do
           (let* ((s (format "%d" c))
                  (spaced (replace-regexp-in-string "\\([0-9]\\)" "\\1 " s)))
             (cl-loop for b in
                      '(("5" . "C-") ("7" . "C-M-")) do
                      (define-key input-decode-map
                        (kbd (concat "M-[ " spaced "; " (car b) " u"))
                        (kbd (concat (cdr b) (char-to-string c)))))))

这样emacs就可以识别CSI u编码了。另外我没有改 M-*这种按键的编码,他们一般是用ESC *这种方式传递的。

我这个方法不完美,但是在shell下面普通的按键没有受影响。

1 个赞

SecureCRT里面,Terminal选择的就是 xterm,Color Mode是Ansi With 256 color。

进去后使用 emacs -nw -q 后, 按C-h k,再按C-;没有任何提示,好像是没有接收到

测试了一下,使用Git里面自带的 Git Bash,可以把按键C-; 传送过去.

测试,使用alacritty,按键传送失败。

注意一点的是,要直接使用Git的Git bash才行。如果是搜索mintty,然后打开mintty,是无法连接到远程服务器的。连接的时候报错。

看的不是很明白,

自己做了一个测试,用SecureCRT连接 Ubuntu服务器。输入命令showkey -a ,可以检测接收到的按键值


Press any keys - Ctrl-D will terminate this program

^[       27 0033 0x1b
^Q       17 0021 0x11
^W       23 0027 0x17
^E        5 0005 0x05
^R       18 0022 0x12
^T       20 0024 0x14
^Y       25 0031 0x19
^U       21 0025 0x15
                  9 0011 0x09
^O       15 0017 0x0f
^P       16 0020 0x10
^[       27 0033 0x1b
^]       29 0035 0x1d
^\       28 0034 0x1c
^A        1 0001 0x01
^S       19 0023 0x13
^F        6 0006 0x06
^G        7 0007 0x07
^H        8 0010 0x08
^J       10 0012 0x0a
^K       11 0013 0x0b
^L       12 0014 0x0c
^J       10 0012 0x0a
^Z       26 0032 0x1a
^X       24 0030 0x18
^C        3 0003 0x03
^V       22 0026 0x16
^B        2 0002 0x02
^N       14 0016 0x0e
^M       13 0015 0x0d
^_       31 0037 0x1f

按下的按键顺序是 Esc,C-q,C-w,C-e,(后面都是有C-,为了方便,把C-省略掉),r,t,y,u,i,o,p,[,[,],, a,s,(因为C-d会退出,这里没有按),f,g,h,j,k,l,(;和’没有相应),Enter z,x,c,v,b,n,m,(,和.也没有响应),/

==================================== 可以得出几点

  1. 按下Ctrl+Key,实际发的是 ^Key,但不是所有的都是这样发的。
  2. 按下Ctrl+i , 实际发的键值为0x09,这个对应的是 水平制表符。
  3. 按下Ctrl+; , Ctrl + ’ , Ctrl + , , Ctrl + . ,都是没有响应的
  4. Esc按键实际发的键值是,0x1b,而实际按Ctrl + [ ,也是发送该键值
  5. 按下 Enter,发的键值是 0x0d,对应的是 ^M,和按下Ctrl + m 发的键值一样 而按下 Ctrl + Enter ,发的键值是 0x0a,对应的是 ^J,和按下Ctrl + j 发的键值是一样的。

下图是Ascii码值

下面是 git bash连接 Ubuntu服务器。输入命令showkey -a ,可以检测接收到的按键值 ,

Press any keys - Ctrl-D will terminate this program

^[       27 0033 0x1b
^Q       17 0021 0x11
^W       23 0027 0x17
^E        5 0005 0x05
^R       18 0022 0x12
^T       20 0024 0x14
^Y       25 0031 0x19
^U       21 0025 0x15
                  9 0011 0x09
^O       15 0017 0x0f
^P       16 0020 0x10
^[       27 0033 0x1b
^]       29 0035 0x1d
^\       28 0034 0x1c
^A        1 0001 0x01
^S       19 0023 0x13
^F        6 0006 0x06
^G        7 0007 0x07
^H        8 0010 0x08
^J       10 0012 0x0a
^K       11 0013 0x0b
^L       12 0014 0x0c
^M       13 0015 0x0d
^Z       26 0032 0x1a
^X       24 0030 0x18
^C        3 0003 0x03
^V       22 0026 0x16
^B        2 0002 0x02
^N       14 0016 0x0e
^M       13 0015 0x0d
^[[1;5l          27 0033 0x1b
         91 0133 0x5b
         49 0061 0x31
         59 0073 0x3b
         53 0065 0x35
        108 0154 0x6c
^[[1;5n          27 0033 0x1b
         91 0133 0x5b
         49 0061 0x31
         59 0073 0x3b
         53 0065 0x35
        110 0156 0x6e
^_       31 0037 0x1f


按键顺序和上面是一样的。 Esc,C-q,C-w,C-e,(后面都是有C-,为了方便,把C-省略掉),r,t,y,u,i,o,p,[,[,],, a,s,(因为C-d会退出,这里没有按),f,g,h,j,k,l,(;和’没有相应),Enter z,x,c,v,b,n,m,(,和.这里有响应),/

==================================== 可以得出几点

  1. 按下Ctrl+; , Ctrl + ’ , 都是没有响应的 ,和上面的结果一致。但是实际用git bash 连接服务器,emacs里面的C+; 是有功能的。
  2. Ctrl + , , Ctrl + . 是有响应的,但是在上面的测试是没有响应的。 Ctrl + , 发的是**(^[[1;5l)** ,对应的键值 0x1b,0x5b,0x31,0x3b,0x35,0x6c ,查找AscII表可以得知对应的按键分别为 (Esc),([),(1),(;),(5),(l) Ctrl + . 发的是**(^[[1;5n)**,对应的键值 0x1b,0x5b,0x31,0x3b,0x35,0x6e ,查找AscII表可以得知对应的按键分别为 (Esc),([),(1),(;),(5),(n)

综上所述,可以得出结论

  1. git bash 可以发送 C-; ,但是不能被showkey识别,可以被emacs识别
  2. SecureCRT,不确定是否可以发送 C-; ,因为不能被showkey识别,也不能被 emacs识别。
  • 可能原因1,SecureCRT 不能发送 C-;,被SecureCRT拦截了。(没有证据是这方面原因)

  • 可能原因2,SecureCRT 能发送 C-; ,Emacs本身配置原因无法识别。(感觉这个站不住脚,因为同样的服务器,同一个emacs,用git bash连接就可以识别到C-;)

  • 疑问1,为什么showkey无法识别C-;

  • 疑问2,假如是SecureCRT的原因,尝试了很多种方式,都不知道怎么配置。SecureCRT本身具有按键映射的功能,但是不知道要把C-;映射成什么键。

  • 疑问3,假如是emacs配置的原因,为什么用不同的方式连接,结果不一样呢。

1 个赞

无法连接服务器是 ssh 命令的问题,不是 mintty 的问题。前几年我也是被折磨的够呛,试了好多 terminal 最后才发现 git for windows 带的 mintty 可以完美的发送各种按键组合。最后用的是 conemu + mintty + Gnuwin 这套组合,用的还行。

总之,应该不是 emacs 的问题。secureCRT 的话,如果你买了正版,那你可以继续折腾,否则的建议尽早别折腾了,小心收到律师函。。。

使用mintty,在ssh 到remote host后,echo -ne “\e[>4;1m”, 再showkey -a试试。

也许可用改键工具绕过这个问题, 按c-;实际发送F13-F24到终端里的emacs,在自定义f13-f24的行为与c-;一致即可,参考 key-echo: 单按修饰键来触发Emacs命令 - #11,来自 wsug