如何让 ctrl 和 shift 箭头键在 emacs 中工作?

如何让 ctrl 和 shift 箭头键在 emacs 中工作?

我最近开始使用 tmux(之前是 screen 用户),我很喜欢它,除了一个小问题。我在 tmux 会话中使用 emacs,并且习惯使用 Shift-箭头键在 emacs 窗口(而不是 tmux 窗口)之间移动。当在 tmux 中运行时,这些绑定似乎完全停止工作(就像它们根本没有注册到 emacs 一样)。如果我退出 tmux 并在 shell 中运行 emacs,它们就可以正常工作。

我正在使用 iTerm2,通过 ssh 连接到 Linux 机器,并在那里运行 tmux/emacs。我在 .emacs 中设置了 Shift-箭头键绑定,如下所示:

(global-set-key "\M-[1;2A" 'windmove-up)
(global-set-key "\M-[1;2B" 'windmove-down)
(global-set-key "\M-[1;2C" 'windmove-right)
(global-set-key "\M-[1;2D" 'windmove-left)

当不在 tmux 中运行时,我可以通过在 emacs 中执行 Cq 然后按按键序列来确认这些是 Shift-箭头组合键的正确字符序列。在 tmux 中,即使这样也不起作用,因为它似乎看不到任何来自 Shift-箭头按键的输入(它只是位于 Cq 提示符处)。

查看 tmux 的键绑定,我认为没有任何东西绑定到 Shift-箭头键,即使是,它们也只会在输入前缀后注册(在我的例子中绑定到 Co)。

关于如何让 tmux 中的 Shift-箭头键再次工作有什么想法吗?

答案1

首先,确保您的术语在每个位置都是正确的:

  • xtermxterm-256color- 本地 shell 中运行的某些内容(例如)iTerm2窗户
  • xterm- SSH 连接到 Linux 系统后 shell 中的内容
    这应该与您在本地使用的内容相同iTerm2,因为 SSH 应该将其传递到远程端(而且重要的是,远程端不应该盲目地覆盖 shell 初始化文件中的值)。
  • screenscreen-256color-你的外壳内运行的东西(例如)多路复用器在 Linux 系统上
    您应该始终screen在内部使用基于 - 的 TERM多路复用器

xterm立即在外面有一个学期多路复用器会允许多路复用器识别修改后的箭头键,但除非您还xterm-keys打开了其窗口选项,否则它不会传递它们。将其放入~/.tmux.confLinux 系统中:

set-window-option -g xterm-keys on

移位键的序列现在应该可以通过Emacs,在里面运行多路复用器,通过 SSH 连接,在iTerm2窗户。

答案2

xterm-keys首先,您必须在 tmux 配置中启用。所以将以下内容放入~/.tmux.conf

setw -g xterm-keys on

但是,这会破坏其他组合键。要修复它们,请将以下内容放入您的~/.emacs~/.emacs.d/init.el配置中

;; handle tmux's xterm-keys
;; put the following line in your ~/.tmux.conf:
;;   setw -g xterm-keys on
(if (getenv "TMUX")
    (progn
      (let ((x 2) (tkey ""))
    (while (<= x 8)
      ;; shift
      (if (= x 2)
          (setq tkey "S-"))
      ;; alt
      (if (= x 3)
          (setq tkey "M-"))
      ;; alt + shift
      (if (= x 4)
          (setq tkey "M-S-"))
      ;; ctrl
      (if (= x 5)
          (setq tkey "C-"))
      ;; ctrl + shift
      (if (= x 6)
          (setq tkey "C-S-"))
      ;; ctrl + alt
      (if (= x 7)
          (setq tkey "C-M-"))
      ;; ctrl + alt + shift
      (if (= x 8)
          (setq tkey "C-M-S-"))

      ;; arrows
      (define-key key-translation-map (kbd (format "M-[ 1 ; %d A" x)) (kbd (format "%s<up>" tkey)))
      (define-key key-translation-map (kbd (format "M-[ 1 ; %d B" x)) (kbd (format "%s<down>" tkey)))
      (define-key key-translation-map (kbd (format "M-[ 1 ; %d C" x)) (kbd (format "%s<right>" tkey)))
      (define-key key-translation-map (kbd (format "M-[ 1 ; %d D" x)) (kbd (format "%s<left>" tkey)))
      ;; home
      (define-key key-translation-map (kbd (format "M-[ 1 ; %d H" x)) (kbd (format "%s<home>" tkey)))
      ;; end
      (define-key key-translation-map (kbd (format "M-[ 1 ; %d F" x)) (kbd (format "%s<end>" tkey)))
      ;; page up
      (define-key key-translation-map (kbd (format "M-[ 5 ; %d ~" x)) (kbd (format "%s<prior>" tkey)))
      ;; page down
      (define-key key-translation-map (kbd (format "M-[ 6 ; %d ~" x)) (kbd (format "%s<next>" tkey)))
      ;; insert
      (define-key key-translation-map (kbd (format "M-[ 2 ; %d ~" x)) (kbd (format "%s<delete>" tkey)))
      ;; delete
      (define-key key-translation-map (kbd (format "M-[ 3 ; %d ~" x)) (kbd (format "%s<delete>" tkey)))
      ;; f1
      (define-key key-translation-map (kbd (format "M-[ 1 ; %d P" x)) (kbd (format "%s<f1>" tkey)))
      ;; f2
      (define-key key-translation-map (kbd (format "M-[ 1 ; %d Q" x)) (kbd (format "%s<f2>" tkey)))
      ;; f3
      (define-key key-translation-map (kbd (format "M-[ 1 ; %d R" x)) (kbd (format "%s<f3>" tkey)))
      ;; f4
      (define-key key-translation-map (kbd (format "M-[ 1 ; %d S" x)) (kbd (format "%s<f4>" tkey)))
      ;; f5
      (define-key key-translation-map (kbd (format "M-[ 15 ; %d ~" x)) (kbd (format "%s<f5>" tkey)))
      ;; f6
      (define-key key-translation-map (kbd (format "M-[ 17 ; %d ~" x)) (kbd (format "%s<f6>" tkey)))
      ;; f7
      (define-key key-translation-map (kbd (format "M-[ 18 ; %d ~" x)) (kbd (format "%s<f7>" tkey)))
      ;; f8
      (define-key key-translation-map (kbd (format "M-[ 19 ; %d ~" x)) (kbd (format "%s<f8>" tkey)))
      ;; f9
      (define-key key-translation-map (kbd (format "M-[ 20 ; %d ~" x)) (kbd (format "%s<f9>" tkey)))
      ;; f10
      (define-key key-translation-map (kbd (format "M-[ 21 ; %d ~" x)) (kbd (format "%s<f10>" tkey)))
      ;; f11
      (define-key key-translation-map (kbd (format "M-[ 23 ; %d ~" x)) (kbd (format "%s<f11>" tkey)))
      ;; f12
      (define-key key-translation-map (kbd (format "M-[ 24 ; %d ~" x)) (kbd (format "%s<f12>" tkey)))
      ;; f13
      (define-key key-translation-map (kbd (format "M-[ 25 ; %d ~" x)) (kbd (format "%s<f13>" tkey)))
      ;; f14
      (define-key key-translation-map (kbd (format "M-[ 26 ; %d ~" x)) (kbd (format "%s<f14>" tkey)))
      ;; f15
      (define-key key-translation-map (kbd (format "M-[ 28 ; %d ~" x)) (kbd (format "%s<f15>" tkey)))
      ;; f16
      (define-key key-translation-map (kbd (format "M-[ 29 ; %d ~" x)) (kbd (format "%s<f16>" tkey)))
      ;; f17
      (define-key key-translation-map (kbd (format "M-[ 31 ; %d ~" x)) (kbd (format "%s<f17>" tkey)))
      ;; f18
      (define-key key-translation-map (kbd (format "M-[ 32 ; %d ~" x)) (kbd (format "%s<f18>" tkey)))
      ;; f19
      (define-key key-translation-map (kbd (format "M-[ 33 ; %d ~" x)) (kbd (format "%s<f19>" tkey)))
      ;; f20
      (define-key key-translation-map (kbd (format "M-[ 34 ; %d ~" x)) (kbd (format "%s<f20>" tkey)))

      (setq x (+ x 1))
      ))
    )
  )      

我也有我的解决方案archlinux 维基

答案3

tmux 常见问题解答用于包含以下条目:

如何让 ctrl 和 shift 箭头键在 emacs 中工作?

terminal-init-screen中的函数是term/screen.el为新帧调用的,但它不配置任何功能键。

如果 tmuxxterm-keys选项打开,则定义与 xterm 相同的键就足够了。添加以下内容init.el.emacs执行此操作:

(defadvice terminal-init-screen
  ;; The advice is named `tmux', and is run before `terminal-init-screen' runs.
  (before tmux activate)
  ;; Docstring.  This describes the advice and is made available inside emacs;
  ;; for example when doing C-h f terminal-init-screen RET
  "Apply xterm keymap, allowing use of keys passed through tmux."
  ;; This is the elisp code that is run before `terminal-init-screen'.
  (if (getenv "TMUX")
    (let ((map (copy-keymap xterm-function-map)))
    (set-keymap-parent map (keymap-parent input-decode-map))
    (set-keymap-parent input-decode-map map))))

并确保.tmux.conf包含“ set -g xterm-keys on”。

或者,screen.el可以将文件复制到加载路径并进行自定义。

我打开了tmux问题 #1349请求恢复常见问题解答条目。

答案4

一般情况下,出现此类问题的原因是终端仿真器发送的内容与客户端应用程序期望的内容不匹配。

不同的终端仿真器具有不同程度的可定制性,因此熟悉特定终端仿真器的仿真可调参数是必要的。

客户端应用程序取决于$TERM用于在terminfo(或termcap)数据库中查找终端(模拟器)功能的值。

在您的情况下,您的 emacs 绑定使用显式序列,因此$TERM和 terminfo 无关:需要一个特定的终端模拟器 - 正如您已经想到的,一个xterm兼容的终端模拟器。

相关内容