怎样删除一个key binding

之前在emacs执行了这段代码:

(add-hook 'org-mode-hook (lambda () 
  (define-key org-mode-map (kbd "RET") 'org-mac-grab-link)))

但这样很不方便, 因为grab-link用的不多, 但是回车键就用不了了. 现在想disable, 除了重启还有什么办法么? 我试了好多种做法, 没一种可以. 下面是我试过的.

  (global-unset-key (kbd "RET")) ; 不起作用
  (global-set-key (kbd "RET") nil) ; 不起作用
  (add-hook 'org-mode-hook (lambda () 
    (define-key org-mode-map (kbd "RET") nil))) ; 不起作用
(define-key (kbd "RET") nil) ; 不起作用
  ; (unset-key (kbd "RET")) ; 没这个命令
(eval-after-load "org" (global-unset-key (kbd "RET"))) ; 不起作用

顺便想问问, 它们为什么不起作用呢? 是不是global-unset-key对于某一个mode下的keybinding是无效的? 但是我根据某个链接, 按了<C-e>, 据说这样就会把major mode key转为global key, 但就算这样, global-unset-key还是不行. define-key怎么也不行呢?

1 个赞

原理在 lazy-load/lazy-load.el at cd9819069c8d25cf34a844ba151c261387aeaa01 · manateelazycat/lazy-load · GitHub

本质是 (define-key keymap key nil)

想问下需要安装这个么? 需要再装emacs么?

Emacs 的按键绑定本质上都是用的 define-key,通过在各个 keymap 里建立相应的映射来完成绑定,不同的 keymap 代表着不同的优先级。

移除的是全局映射表里的 RET,你想要移除 org-mode-map 下的,但是又不想要重启 Emacs 的话,(define-key org-mode-map (kbd "RET") nil) C-x C-e 就可以了。

把文件关闭在重新打开就可以生效了。

2 个赞

是的, 执行了org-reload就可以了, 感谢! 不过还有个问题, 为什么直接(define-key org-mode-map (kbd "RET") nil))不行, 而要

(add-hook 'org-mode-hook (lambda () 
    (define-key org-mode-map (kbd "RET") nil)))

才可以呢? 我的理解是, add-hook是条件触发, 类似vim中的autocmd, 如果没有add-hook, 那就是无条件触发, 那不就应该起作用么?

add-hook 是你打开 org 文件的时候触发,因为你打开 org 文件的时候会启动 org-mode,org-mode 会执行 org-mode-hook 里的东西。

(define-key org-mode-map (kbd "RET") nil)

直接扔文件里无法生效的话,应该是 1. 找不到 org-mode-map,应该直接报错才对,是可以通过

(with-eval-after-load 'info
 (define-key org-mode-map (kbd "RET") nil))

进行按键设置的,2. 至于你的问题为什么没有成功,我猜测是因为你配置里

的存在,打开文件后他会继续进行重新绑定 'org-mac-grab-link 到 org-mode-map 的 RET 上。

最后,你能碰巧成功,估计是先执行了 (define-key org-mode-map (kbd “RET”) 'org-mac-grab-link)), 再执行 (define-key org-mode-map (kbd “RET”) nil) 的结果。

1 个赞

明白了, 感谢!

补充: (define-key org-mode-map (kbd “RET”) 'newline)比较好, 否则回车换行都不行.

我也安利一下我自己写的一个宏,绑定按键比较多的话会比较方便,名字不喜欢的话可以改成自己喜欢的:

宏名: zerolee-set-key,接受任意数量参数,参数可以为: keymap 或 按键绑定

keymap:  符号 或者 长度为 1 的列表
按键绑定:长度大于等于二的列表,形式为(字符串或者数组 ... command)
比如 (zerolee-set-key ("C-s" #'isearch-forward-regexp))
绑定全局快捷键 C-s 到 #'isearch-forward-regexp
上述快捷键也可以如下这样定义:
(zerolee-set-key
    (current-global-map)
    ("C-s" #'isearch-forward-regexp))
连续的 keymap 表示接下来的按键绑定依次在这些 keymap 下进行绑定:
(zerolee-set-key
    lisp-interaction-mode-map
    emacs-lisp-mode-map
    ("C-c <return>" #'emacs-lisp-macroexpand)
    ("C-s" #'isearch-forward-regexp))
在 lisp-interaction-mode-map 下绑定 "C-c <return>" 到 emacs-lisp-macroexpand, "C-s" 到 isearch-forward-regexp
再在 emacs-lisp-mode-map 绑定 绑定 "C-c <return>" 到 emacs-lisp-macroexpand, "C-s" 到 isearch-forward-regexp

按键绑定列表的长度大于二,除最后一个元素为 command 外,其余皆为 key,
整个列表则表示所有的 key 都绑定为 command
(zerolee-set-key
   paredit-mode-map
   ("M-s" "M-r" nil))
将 paredit-mode-map 下的 "M-s", "M-r" 绑定为 nil
keymap, 按键绑定之间的次序,出现次数没有限制
(zerolee-set-key
    ("C-s" #'isearch-forward-regexp)
    lisp-interaction-mode-map
    emacs-lisp-mode-map
    ("C-c <return>" #'emacs-lisp-macroexpand)
    paredit-mode-map
   ("M-s" "M-r" nil))
表示绑定 #'isearch-forward-regexp 到全局 C-s, 在 lisp-interaction-mode-map 和 emacs-lisp-mode-map 下绑定 "C-c <return>"  到 #'emacs-lisp-macroexpand,取消 paredit-mode-map 下的 M-s,M-r

源码:

(defun zerolee-slots->set-key (keymaps slot)
  (cl-loop for keymap in keymaps
           append
           (cl-loop with command = (car (last slot))
                    for key in (butlast slot)
                    if (stringp key)
                    collect `(define-key ,keymap (kbd ,key) ,command)
                    else
                    collect `(define-key ,keymap ,key ,command))))

(defmacro zerolee-set-key (&rest slots)
  `(progn
     ,@(cl-loop with keymaps = '((current-global-map))
                with last-is-keymap = nil
                for slot in slots
                if (or (atom slot) (and (consp slot) (= (length slot) 1)))
                do (if last-is-keymap
                       (push slot keymaps)
                     (setq keymaps (list slot)
                           last-is-keymap t))
                else
                append (progn
                         (setq last-is-keymap nil)
                         (zerolee-slots->set-key keymaps slot)))))
3 个赞

use-package 的话,还可以用 unbind-key

直接用 elisp 的话,还可以参考 Purcell 设置 paredit 的配置:

1 个赞