为什么我不能改变paredit键绑定

sno*_*ape 6 emacs elisp keyboard-shortcuts paredit

我正在尝试使用paredit中的一些函数,而不加载所有的键绑定.看看paredit.el,我找到的唯一键盘映射是paredit-mode-map,所以我尝试了这个.

(setq paredit-mode-map (make-sparse-keymap))
(define-key paredit-mode-map (kbd "<C-M-left>") 'paredit-backward)
Run Code Online (Sandbox Code Playgroud)

它没有改变键绑定(用Ch k检查),但变量paredit-mode-map被改变了.

我也试过了

(eval-after-load "paredit"
  '(progn
     (setq paredit-mode-map (make-sparse-keymap))
     (define-key paredit-mode-map (kbd "<C-M-left>") 'paredit-backward)))
Run Code Online (Sandbox Code Playgroud)

然后打开和关闭paredit,结果相同.

以前,直接对键映射进行更改一直对我有用.这里发生了什么?

编辑:

我通过这样做成功地更改了键盘映射:

; Remove old paredit bindings
(defun take-from-list (condp list)
  "Returns elements in list satisfying condp"
  (delq nil
    (mapcar (lambda (x) (and (funcall condp x) x)) list)))
(setq minor-mode-map-alist 
      (take-from-list 
        (lambda (x) (not (eq (car x) 'paredit-mode))) 
        minor-mode-map-alist))

; Create new paredit-mode-map
(setq paredit-mode-map (make-sparse-keymap))
(define-key paredit-mode-map (kbd "<C-kp-enter>") 'paredit-backward)

; Add the new paredit-mode-map to minor-mode-map-alist
(setq minor-mode-map-alist (append
                (list (append (list 'paredit-mode) paredit-mode-map))
                minor-mode-map-alist))
Run Code Online (Sandbox Code Playgroud)

因此,似乎minor-mode-map-alist是用于查找的变量.我敢肯定,有更优雅的方式来改变键绑定,但我想了解更多的键绑定在Emacs是如何工作的.

lun*_*orn 5

Paredit uses a different way of defining the keymap. Whereas most minor modes define the keymap in the variable definition, Paredit calls paredit-define-keys on top-level, and thus forcibly initializes the keymap.

In other words, you cannot prevent Paredit from setting up its bindings. You need to remove all keybindings in the keymap with (define-key paredit-mode-map … nil) to get rid of these.

Edit: You cannot “reset” keymaps by assigning a new keymap to the variable. (setq paredit-mode-map …) will change the variable paredit-mode-map, it will not change the actual keymap being used by Paredit mode.

The binding of this variable is only evaluated once at definition time, i.e. during the evaluation of define-minor-mode. This macro internally calls add-minor-mode, and passes to this function the current value of the keymap variable. All future use of the mode refers to this keymap only. The keymap variable is never again evaluated by the minor mode, thus changing its binding has no effect whatsoever.

If you want to change the keymap, you have to re-bind the variable before define-minor-mode is evaluated, i.e. before the corresponding library is loaded. Changing it in an eval-after-load form is hence completely useless.

通常,在加载库之前更改 keymap 变量效果很好,因为大多数模式在defvar. defvar但是,如果变量已经有值,则不会更改它的值。因此,如果变量已经有一个键映射,它就不会被触及。

但是,正如我所说,Paredit 不尊重这种模式,而是强行将其绑定添加到键映射。因此改变它是没有意义的,因为 Paredit 无论如何都会添加它的绑定。

正如我所说,您必须通过取消定义每个键来手动清除现有的键映射。

TL;DR:使用 Smartparens,真的!它涵盖了 Paredit 的所有内容,它灵活、强大、可扩展,总之它很好。它可以让你选择你想要的任何键绑定。

  • Smartparens 在哲学上与 paredit 不同。Paredit 将您的心态转变为以性为中心。Smartparens 似乎并不关心。就我个人而言,我很难适应 paredit 的理念,但现在我已经适应了,我再也不会回去了。 (3认同)
  • “力”是准确的。不过,我从被迫中受益。 (3认同)