如何绑定C- [真正?


10

C-[等效于美式英语键盘上的转义键,因此,任何对其进行绑定的尝试都会破坏M-行为。

Emacs是没有麻烦告诉<escape>,并C-[在GUI框架分开。以下工作正常,并且从开始的绑定M-仍然有效:

(global-set-key (kbd "<escape>") (lambda () (interactive) (message "<escape>")))

但是,如果我绑定

(global-set-key (kbd "C-[") (lambda () (interactive) (message "C-[")))

突然,emacs发疯了,像M-x断裂一样束缚。此外,按C-[拒绝触发绑定的lambda。有趣的是,C-x @ c [(将修饰符控件应用到方括号中)仍然说C-[ is undefined

有什么方法可以在C-[不破坏emacs的情况下进行绑定吗?

Answers:


7

您实际上无法C-[像使用那样在用户级地图上更改绑定global-set-key。但是,您可以在到达这些键盘映射之前将其更改为键盘事件。您可以说例如:

(define-key input-decode-map 
    (kbd "C-[") 
    [control-bracketleft])

然后[control-bracketleft]在您的键盘映射中使用。很简单,不是吗?

导演剪辑版

不幸的是,它并不是那么简单,并且该解决方案需要进行一些调整,这似乎非常痛苦。您已被警告。但首先让我们看看为什么用户级地图不能回答这个问题。在下文中,当我说“看到一些东西”而没有更高的精度时,我将参考emacs 26.1的Emacs Lisp手册。

C-[在很早的阶段就被解释为ASCII控制字符ESC(请参见21.7.1- 键盘事件)。此代码将其他地方扩展为更长序列的前缀。还有一个原因:ESC实际元前缀(见meta-prefix-char),并读取所有绑定 M-的东西将转化为一个序列开始用ESC。因此,仅更改全局地图是不够的:您需要先进行更改meta-prefix-char,然后再重新映射ESCmeta-prefix-char所使用的每张地图中的新地图,M-然后才能安全地进行映射C-[

那当然可以了:让我们使用input-decode-map。我们可能会尝试使用几张相似的地图(请参阅第21.8.3和22.14节),但让我们继续坚持下去。好吧...这有效!完成了,不是吗?

其实,不,故事还没有结束。只要您使用的是窗户系统,它就可以工作。如果由于运气不好而在紧急状态下被囚禁在Linux控制台中,那么您就会意识到这种情况变得多么严重:箭头键,Home当然还有M-绑定都是垃圾。为什么?因为当终端说出ESC(键入时会执行此操作C-[)时,它实际上表示 ESC,并启动了与传输非ASCII字符相同类型的序列。

观察灾难,您可能认为明智input-decode-map的做法是,以仅在窗口系统正在控制键盘的情况下激活的方式保护上述修改:

(let ((frame (framep (selected-frame))))
  (or (eq  t  frame)
      (eq 'pc frame)

      (define-key input-decode-map 
                  (kbd "C-[") 
                  [control-bracketleft])
     )))

然后,终端可以像往常一样工作。

现在,我们可以C-[在终端上处理吗?实际上,是的,在Linux控制台以及我可以使用的其他终端仿真器上,我们可以做到。但是随着新角色的出现,这使得这个故事很长。因为不再仅仅是emacs:终端现在扮演着中心角色。

让我们听听linux控制台怎么说。键入C-v某些键之前听到它平原。C-[ESC; 也是Esc。向上箭头听起来像ESC [ AM-a而是 ESC A。嗯...看起来像是emacs中的meta键绕行了,不是吗?无论如何。

除非我们已准备好根据字符事件(其中的方式将不区分之间的时间玩一些技巧 EscC-[),看来我们得无奈地告诉控制台其实我们不要吝啬ESC当我们键入C-[。此外,似乎很快C-[就不再是库存终端代码的唯一问题:修饰符大部分时间都被抹去了所传输的信息。我们出于与定制emacs相同的原因而需要定制终端:如果这样做,它将更加实用。

此时,您应该深入了解终端的文档眼睛:loadkeys(1)Linux控制台的手册页,“ 自定义键绑定”xterm(1)部分的xterm 以及其他终端的what-i-dont-know。在,您可以定义自定义转换设置/编辑当前配置文件... 然后键盘。以下是 播放后一个对话框后的摘录:KDE konsole~/.local/share/konsole/Test.keytab

key [+Ctrl+AnyModifier : "\EO*["

一旦你的终端发送ESC O 5 [C-[(如上面的配置),你可以回去emacs的。当然,您还没有完成。

要指示emacs给定终端使用什么方言,可以调整input-decode-map。是的,很幸运,这是我们在本文开头所修改的内容,并且是 term/xterm.el涉及xterm时的内容。进行调整的好地方是tty-setup-hook(请参阅第40.1.3节):

(add-hook 'tty-setup-hook 
   (lambda ()
    (let ((term (getenv "TERM")))
      (cond 
        (;; xterm-function-map not in doc, but in term/xterm.el
         (boundp 'xterm-function-map) 
         (map-my-term-codes xterm-function-map))

        ((equal term "linux")
         (map-my-term-codes input-decode-map))
        )
      )))

请注意,只有在终端中时,此挂钩才会运行。因此,您不能在此处插入窗口系统初始化的代码。这里是翻译功能本身:

(defun map-my-term-codes (map)
      (define-key map (kbd "M-O 5 [") 
                      [control-bracketleft])
      )

然后您可以休息一下:这是旅程的终点​​。当然,如果您不关心终端,那将很快,因为您将跳过所有痛苦的部分。但是您会承认它还很不完整。

最后两个注意事项:

  • 我选择ESC O 5 [编码C-[。这只是一个例子:我不会假装这是一个选择。只有5 一部分,即意味着C-,似乎遵守了某种既定惯例

  • 配置linux控制台会留下不好的味道:如果不使用现有的中间符号似乎无法进行绑定,而我需要的符号 则不存在。我在大多数互联网示例中都在F21- F246范围内使用了符号,但这并不是很令人满意。可以使用一些不相关的绑定,但是不会提供系统的架构。

编辑

  • Esc在另一篇文章:如何删除与ESC前缀键的绑定中完成了这种具有自己个性的案例
  • 这是要提供的配置的一部分loadkeys。我将其放在/root/custom.kmap中,并在需要时加载它(这种情况很少见)。我的实际配置还映射了箭头和修饰符的不同组合,但是它相当长,选择符号和序列是有问题的,而且我不确定键盘的键码是否会与您的键盘匹配。因此,让我们将其保持在适当的水平:这只是一个例证。

    keymaps 0-127
    
    # http://tldp.org/HOWTO/Keyboard-and-Console-HOWTO-15.html
    # web+man:keymaps
    # web+man:loadkeys
    
    # escape
    keycode  1  = F100
        alt keycode  1 = Escape # keep the Escape behavior somewhere          
    
    # keycode  26 = bracketleft
        control keycode 26 = F115 # Control_bracketleft does not exist          
    
    string F100     = "\033OO" # map this to [escape] in map-my-term-codes
    string F115     = "\033O5["
    

1
谢谢,这是一个很好的答案。但可以肯定的是,即使是这样的好答案,也不必将其排在首页的顶部34次。每次碰碰都有一个很小的成本,由社区来承担:检查垃圾邮件,查找是否有新的有趣内容等。也许您可以将一些较小的改进组合在一起?或者只是坚持拥有的东西。从经验上来讲,没有完美的职位,在某些时候您只需要继续前进。
吉尔(Gilles)'所以

@吉尔斯知道了,对此表示抱歉。我不知道有什么问题可以随意调整。
香槟

0

以下解决方案有点笨拙,但似乎可行:

~/.xbindkeysrc包含以下内容:

"xvkbd -xsendevent -text '\[Control_L]\[F13]'"
  m:0x14 + c:34

"xvkbd -xsendevent -text '\[Control_L]\[F14]'"
  m:0x14 + c:35

现在xbindkeys将转化C-[C-<f13>C-]C-<f14>,这样他们就可以在Emacs自由的约束。你可能会想绑定abort-recursive-edit比其他东西C-],例如C-S-g

缺点是,现在C-[除了Emacs之外,每个应用程序都已损坏,可以通过添加一些逻辑来测试是否将键组合发送到emacs来解决此问题。


FWIW,我认为没有什么特别的C-]
马拉巴巴

是的,我也没有,但是由于某种奇怪的原因,C-]在启动Xbindkeys之后我的绑定停止工作了,所以我也反弹了那个。
克里斯托夫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.