tmux干扰了emacs命令吗?(windmove-default-keybindings)

5

(windmove-default-keybindings 'meta) 提供了在emacs窗口之间移动的命令(例如M-<up>移动到上面的窗口)。当在终端中运行emacs -nw时,它们可以正常工作,但在tmux中则失败。

单个命令可以正常工作,例如winmove-up;当运行它们时,会告诉我:

您可以使用M-<up>运行命令winmove-up

但是对于M-<up>本身,我得到:

ESC <up>未定义

任何其他前缀键(shiftcontrol)都有同样的问题。

这是在Ubuntu 12.04和14.04下的tmux 1.9a/emacs 23.3.1和tmux 2.0/emacs 24.5.1中发生的。在第一种情况下,我使用“gnome-terminal”。在第二种情况下,我通过ssh连接到服务器,TERM环境变量为“xterm”。一旦我启动tmux,它就变成了“screen-256color”;这是因为我使用了set -g default-terminal

有什么想法吗?


你在使用什么终端?它们甚至在 Putty 中对我也不起作用。 - Random832
我在家里的机器上使用gnome-terminal。当我通过ssh连接到服务器时,TERM环境变量显示“xterm”,而当我启动tmux时,则是“screen-256color”。我会将其添加在上面。 - Diagon
我在我的回答中增加了更多信息,关于添加新的终端类型“screen-xtermkeys-256color”和“tmux-xtermkeys-256color”。 - Random832
3个回答

4
通过@Random832的帮助,回答了这个问题并回答了这个问题的第一个答案,以及在这个问题的答案中提供了有关emacs如何处理功能键的有用信息。这里有两种方法: 方法 #1: 在您的.tmux.conf中使用xterm-keys on,但是,如果您使用256种颜色,则正确设置您的default-terminal
set -g xterm-keys on
set -g default-terminal "xterm-256color"

方法二:在终端运行cat,然后输入M-<up>等命令找到输出结果。在我的情况下,输出结果是:^[[1;3A(以及B、C、D)。然后,在你的.emacs文件中使用这段代码:

(add-hook 'term-setup-hook
  '(lambda ()
     (define-key function-key-map "\e[1;3A" [M-up])
     (define-key function-key-map "\e[1;3B" [M-down])
     (define-key function-key-map "\e[1;3C" [M-right])
     (define-key function-key-map "\e[1;3D" [M-left])))

注意,这种第二种方法同样适用于其他前缀键(ShiftControl),并且在screen中出现了同样的问题。
另请注意,除了在gnus文章摘要缓冲区中,所有似乎都能正常工作,其中M-M-的行为类似于<up><dn>(尽管M-<rt>M-<lft>正常工作)。

有很多其他不使用xterm-256color的原因。我稍后会更新一个自定义的terminfo条目。 - Random832
1
谢谢!我尝试了无数种方法来重新映射这些键(我正在使用屏幕并遇到同样的问题),你的第二种方法是我尝试过的唯一可行的方法。你让我免于终身的挫败感! - wvdschel

2

Emacs并不总是能够正确地翻译功能键上的修改器。

首先,尝试一下tmux选项set -g xterm-keys on是否会有任何不同。 (这可能需要一个新的terminfo条目才能完全工作;如果它做出了任何改变,即使是说一些其他内容而不是ESC <up>,请在评论中说明)

另外,在xterm-keys关闭的情况下,尝试使用此答案中的按键映射:

(define-key input-decode-map "\e\eOA" (kbd "<M-up>"))
(define-key input-decode-map "\e\eOB" (kbd "<M-down>"))
< p > xterm-keys 解决方案的优点是,如果它可以工作,它也将适用于 shift 和 ctrl。 < p > 不必修改 function-key-map,启用 xterm-keys 后,您可以安装具有适当键的新 terminfo 条目:
# Note: tmux does translate Home and End (\EOH, \EOF) to \E[1~, \E[4~
# But leaves the modified versions (\E[1;?H etc) alone.

xterm+modkeys|xterm-style modifier keys,
    kb2=\EOE, kent=\EOM,
    kind=\E[1;2B, kri=\E[1;2A,
    kf13=\E[1;2P, kf14=\E[1;2Q, kf15=\E[1;2R, kf16=\E[1;2S,
    kf17=\E[15;2~, kf18=\E[17;2~, kf19=\E[18;2~, kf20=\E[19;2~,
    kf21=\E[20;2~, kf22=\E[21;2~, kf23=\E[23;2~, kf24=\E[24;2~,
    kf25=\E[1;5P, kf26=\E[1;5Q, kf27=\E[1;5R, kf28=\E[1;5S,
    kf29=\E[15;5~, kf30=\E[17;5~, kf31=\E[18;5~, kf32=\E[19;5~,
    kf33=\E[20;5~, kf34=\E[21;5~, kf35=\E[23;5~, kf36=\E[24;5~,
    kf37=\E[1;6P, kf38=\E[1;6Q, kf39=\E[1;6R, kf40=\E[1;6S,
    kf41=\E[15;6~, kf42=\E[17;6~, kf43=\E[18;6~, kf44=\E[19;6~,
    kf45=\E[20;6~, kf46=\E[21;6~, kf47=\E[23;6~, kf48=\E[24;6~,
    kf49=\E[1;3P, kf50=\E[1;3Q, kf51=\E[1;3R, kf52=\E[1;3S,
    kf53=\E[15;3~, kf54=\E[17;3~, kf55=\E[18;3~, kf56=\E[19;3~,
    kf57=\E[20;3~, kf58=\E[21;3~, kf59=\E[23;3~, kf60=\E[24;3~,
    kf61=\E[1;4P, kf62=\E[1;4Q, kf63=\E[1;4R,
    kDC=\E[3;2~, kDC3=\E[3;3~, kDC4=\E[3;4~, kDC5=\E[3;5~, kDC6=\E[3;6~, kDC7=\E[3;7~,
    kDN=\E[1;2B, kDN3=\E[1;3B, kDN4=\E[1;4B, kDN5=\E[1;5B, kDN6=\E[1;6B, kDN7=\E[1;7B,
    kEND=\E[1;2F, kEND3=\E[1;3F, kEND4=\E[1;4F, kEND5=\E[1;5F, kEND6=\E[1;6F, kEND7=\E[1;7F,
    kHOM=\E[1;2H, kHOM3=\E[1;3H, kHOM4=\E[1;4H, kHOM5=\E[1;5H, kHOM6=\E[1;6H, kHOM7=\E[1;7H,
    kIC=\E[2;2~, kIC3=\E[2;3~, kIC4=\E[2;4~, kIC5=\E[2;5~, kIC6=\E[2;6~, kIC7=\E[2;7~,
    kLFT=\E[1;2D, kLFT3=\E[1;3D, kLFT4=\E[1;4D, kLFT5=\E[1;5D, kLFT6=\E[1;6D, kLFT7=\E[1;7D,
    kNXT=\E[6;2~, kNXT3=\E[6;3~, kNXT4=\E[6;4~, kNXT5=\E[6;5~, kNXT6=\E[6;6~, kNXT7=\E[6;7~,
    kPRV=\E[5;2~, kPRV3=\E[5;3~, kPRV4=\E[5;4~, kPRV5=\E[5;5~, kPRV6=\E[5;6~, kPRV7=\E[5;7~,
    kRIT=\E[1;2C, kRIT3=\E[1;3C, kRIT4=\E[1;4C, kRIT5=\E[1;5C, kRIT6=\E[1;6C, kRIT7=\E[1;7C,
    kUP=\E[1;2A, kUP3=\E[1;3A, kUP4=\E[1;4A, kUP5=\E[1;5A, kUP6=\E[1;6A, kUP7=\E[1;7A,

screen-xtermkeys|screen with xterm-style modifier keys,
    use=xterm+modkeys, use=screen,

screen-xtermkeys-256color|screen with xterm keys and 256 colors,
    use=xterm+modkeys, use=screen-256color,

tmux-xtermkeys|tmux with xterm-style modifier keys,
    use=xterm+modkeys, use=tmux,

tmux-xtermkeys-256color|tmux with xterm keys and 256 colors,
    use=xterm+modkeys, use=tmux-256color,

使用tic -x tmux-xtermkeys.ti进行编译,然后根据需要将TERM设置为适当的{tmux,screen}-xtermkeys{,-256color}。我包含了screen,原因有两个:首先,emacs默认不将tmux视为256色终端。其次,某些系统的terminfo数据库版本过旧,无法包含tmux信息(删除这些条目以使文件能够编译)。
最好使用screen terminfo条目而不是xterm条目,因为tmux曾经推荐使用screen,并且它的仿真更加匹配。在某些情况下,您可能会注意到一件事情,即应该处于突出显示模式的文本将以斜体形式呈现。如果是这样,请升级您的terminfo数据。
这也适用于支持这些键的其他应用程序(即大多数现在在xterm中工作的地方)。

感谢您的建议... 在两台机器上,set -g xterm-keys确实会更改M-<up>的输出,将字母“3A”输出到缓冲区(但光标不会改变位置,回显区域中也没有任何内容)。 M-<dn>输出“3B”,M-<rt>是“3C”,M-<lft>是“3D”。 我即将检查您的第二个建议。(请注意,我已编辑我的问题以包括有关TERM环境变量的信息)。 - Diagon
Random832 - 好的,我明白你的意思。我会留意一下,但到目前为止,无论是在我的家用电脑还是服务器上,我都没有遇到任何关于set -g default-terminal "xterm-256color"的问题。特别是,我没有在突出显示模式下的文本中看到斜体字的问题。感谢您详尽的回答。如果/当我需要测试您的terminfo条目时,我会在这里报告。 (这让我想起了很久以前与termcap文件的斗争,令人噩梦般的回忆。) - Diagon
哦,好的。根据你最后提供的链接,这个问题应该在tmux 2.1中得到修复,因此使用xterm-256color可能是一个简单的临时解决方案,即使一些小问题出现也没关系。 - Diagon

0

只有这个对我起作用:

在init.el中

;; Try to move direction, which is supplied as arg
;; If cannot move that direction, send a tmux command to do appropriate move
(defun windmove-emacs-or-tmux(dir tmux-cmd)
  (interactive)
  (if (ignore-errors (funcall (intern (concat "windmove-" dir))))
      nil                       ;; Moving within emacs
    (shell-command tmux-cmd)) ;; At edges, send command to tmux
  )

;Move between windows with custom keybindings
(global-set-key (kbd "C-k")
        '(lambda () (interactive) (windmove-emacs-or-tmux "up"  "tmux select-pane -U")))
(global-set-key (kbd "C-j")
        '(lambda () (interactive) (windmove-emacs-or-tmux "down"  "tmux select-pane -D")))
(global-set-key (kbd "C-l")
        '(lambda () (interactive) (windmove-emacs-or-tmux "right" "tmux select-pane -R")))
(global-set-key (kbd "C-h")
        '(lambda () (interactive) (windmove-emacs-or-tmux "left"  "tmux select-pane -L")))

在 .tmux.conf 文件中:
bind -n C-h run "(tmux display-message -p '#{pane_current_command}' | grep -iqE '(^|\/)g?(view|emacs?)(diff)?$' && tmux send-keys C-h) || tmux select-pane -L"
bind -n C-j run "(tmux display-message -p '#{pane_current_command}' | grep -iqE '(^|\/)g?(view|emacs?)(diff)?$' && tmux send-keys C-j) || tmux select-pane -D"
bind -n C-k run "(tmux display-message -p '#{pane_current_command}' | grep -iqE '(^|\/)g?(view|emacs?)(diff)?$' && tmux send-keys C-k) || tmux select-pane -U"
bind -n C-l run "(tmux display-message -p '#{pane_current_command}' | grep -iqE '(^|\/)g?(view|emacs?)(diff)?$' && tmux send-keys C-l) || tmux select-pane -R"
bind -n C-\ run "(tmux display-message -p '#{pane_current_command}' | grep -iqE '(^|\/)g?(view|emacs?)(diff)?$' && tmux send-keys 'C-\\') || tmux select-pane -l"

https://blog.kdheepak.com/emacsclient-and-tmux-split-navigation.html


1
好的,这个问题的重点是如何使用meta/control/shift-arrow来执行这些命令,而不是将它们重新定义为其他东西。我还要补充的是,我有一个更复杂的版本,可以在tmux窗格<-->emacs窗口之间移动。我发现的问题是:(1)如果在emacs中发生了某些缓慢的事情,那么虽然我可以移动到另一个tmux窗口,但emacs正在处理,所以我仍然被冻结在emacs窗格中。(2)如果我用sudo emacs,它就不起作用了。(3)我会混淆在emacs或tmux中,并错误地交换命令。 - Diagon
@Diagon 我有这个版本,它还可以防止溢出 https://github.com/rofrol/.emacs.d/blob/7f16ff865dc8628a33cab86359773ff226ab1c9e/lisp/rofrol-system.el#L191 https://github.com/rofrol/dotfiles/blob/0f09a13cf13db049e00790e0237edfa92eb66d3f/bin/tmux_navigate.sh https://github.com/rofrol/dotfiles/blob/0f09a13cf13db049e00790e0237edfa92eb66d3f/.tmux.conf#L36 - rofrol
我喜欢这行代码:(ignore-errors (funcall (intern (concat "windmove-" dir)))。我想我会用它! :) 你所说的“防止溢出”是什么意思? - Diagon
溢出 - 当您在顶部窗格时,Shift-up将无法进入底部窗格。 - rofrol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接