在Emacs 23.1.1中绑定M-<up> / M-<down>键

25

我正在尝试添加一项来自Eclipse的功能,在那里,Alt+[Up/Down]可以将行上下移位,但是我无法弄清如何正确地为这些按键分配功能。 我正在使用-nw模式(仅在shell窗口中),通常在screen会话中运行。

使用全局键绑定,我可以使字母组合生效,例如(kbd "M-m"),但我尝试过的所有箭头键组合都只给我一个不合理的消息,我总是得到:

"ESC <up> is undefined"

我尝试过什么:

(global-set-key (kbd "M-<up>") 'transpose-line-up)    
(global-set-key (kbd "<escape>-<up>") 'transpose-line-up)
(global-set-key [M-up] 'transpose-line-up)
(global-set-key [\e \M-O A] 'transpose-line-up)

并且 C-h c 只会返回:

ESC <up> (translated from ESC M-O A) is undefined

使用 ESCAlt 都不能实现,有没有什么办法可以使其正常工作呢?我更喜欢将它们设置为 Alt+向上/向下,因为这已经成为我的习惯了。

编辑

来自评论:

  • C-q 向上箭头 打印出 ^[OA

  • C-q Alt 向上箭头 打印出 ^[ 并将光标移到上一行。

  • C-h kAlt+向上)打印出 ESC <up> (translated from ESC M-O A) is undefined

感谢提供的建议,但它们都无法解决问题。


http://nex-3.com/posts/45-efficient-window-switching-in-emacs#comments 包含了一些有趣的评论技巧。 - jfs
7个回答

24

Emacs有一个复杂机制来处理各种终端类型上的功能键和修饰符编码的变化。在某些情况下,它并不能立即奏效。以下设置应该适用于您的终端:

(define-key input-decode-map "\e\eOA" [(meta up)])
(define-key input-decode-map "\e\eOB" [(meta down)])
(global-set-key [(meta up)] 'transpose-line-up)
(global-set-key [(meta down)] 'transpose-line-down)

只要你已经通过 input-decode-map 的步骤告诉Emacs关于转义序列,即终端用来编码这些按键组合的转义序列,那么你应该可以使用 (kbd "<M-up>")(kbd "<M-down>") 替代 [(meta up)][(meta down)]


我得到了一个错误提示: 符号的函数定义为空:transpose-line-up message - nsvir
@nsvir 我按照问题中的函数名称进行了跟踪。这不是一个标准命令,可能是Liam从某个包中获取或自己编写的。请注意,标准命令transpose-lines(C-x C-t)非常接近。 - Gilles 'SO- stop being evil'

9
我通常使用C-h k (key)(即describe-key)来查找Emacs如何引用(key),然后使用带有相同字符串的(kbd)来利用它。
在这种情况下,describe-key返回<M-up>,所以我会使用(global-set-key (kbd "<M-up>") 'transpose-line-up)(就像J.F. Sebastian一样)。
编辑:
在运行emacs -nw时(但不是通过screen),describe-key报告ESC <up>(从ESC M-[ A翻译),对于绑定它,(kbd "ESC <up>")是成功的。
在运行screen emacs -nw时,describe-key报告ESC <up> (translated from ESC M-O A),似乎与您看到的匹配,并且(kbd "ESC <up>")的绑定对我仍然有效。
(注:在Cygwin下测试,使用screen 4.00.03和Emacs 23.2.1。)

在“screen”模式下,<M-up>对我无效(我认为它对OP的情况也是如此)。 - jfs
和J.F. Sebastian上面的答案一样,我得到了与原始问题报告的相同错误。 - liam
啊,我没注意到问题的那部分。现在,“丑陋的解决方法”就更有意义了 :) - phils
经过进一步测试,我添加了一些额外的注释。总结是,我的原始方法在所有情况下都适用于我:使用describe-key查找要与(kbd)一起使用的内容。如果您能确认您是否已经这样做,那就太好了。 - phils
是的,我已经完成了这个任务。 (kbd "M-<up>") -> [M-up]。describe-key 返回:ESC <up>(从 ESC M-O A 翻译而来)未定义。使用该序列也无效。 - liam
这是我曾经遇到的最有用的emacs提示!我不仅不知道如何做到这一点,也从未想过要问如何做到这一点。给你50个虚拟赞! :) - JVMATL

6
(global-set-key [M-up] 'beginning-of-buffer)
(global-set-key [M-down] 'end-of-buffer)

在我的OSX系统中,我定义了使用Alt+上下箭头来快速跳转至文本缓冲区的顶部或底部。


在“屏幕”模式下,[M-up](我想OP的情况也是如此)对我无效。 - jfs
对我来说不起作用。仍然会出现“ESC<up>未定义”的错误。 - liam
是的,我仍然和 @liam 一样有同样的问题。 - rien333

4

丑陋的解决方法:

我输入了C-q <M-up>,它在emacs中的screen终端上产生了^[[1;3A

(global-set-key (kbd "<M-up>") 'transpose-line-up)
(global-set-key (kbd "^[[1;3A") 'transpose-line-up)

我遇到了一个错误:Lisp error: (void-function transpose-line-up),导致快捷键无法工作。

注意:C-q会执行命令quoted-insert


1st: ESC <up> 未定义2nd: 错误:键序列^[ [1;3A以非前缀键^开头 - liam
1
@liam:执行 (format-kbd-macro (read-key-sequence "按键?" nil t)),然后输入<M-up>或<M-down>。输出是什么? - jfs

2
以下内容适用于我的 macOS 10.11.6GNU Emacs 25.2.1 版本:
(global-set-key (kbd "ESC <down>") 'end-of-buffer)
(global-set-key (kbd "ESC <up>") 'beginning-of-buffer)

0
假设您已经定义了函数transpose-line-uptranspose-line-down(从您原始问题中的示例代码看来是这样):
(global-set-key [(meta up)] 'transpose-line-up)
(global-set-key [(meta down)] 'transpose-line-down)

0

适用于OSX终端:

(global-set-key (kbd "ESC <up>") 'transpose-line-up)
(global-set-key (kbd "ESC <down>") 'transpose-line-down)

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