8

すべてのキーバインドをロードせずに、paredit の関数をいくつか使用しようとしています。paredit.el を見てみると、キーマップが paredit-mode-map しかなかったので、これを試してみました。

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

キーバインドは変更されませんでしたが (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)))

次に、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))

したがって、minor-mode-map-alist はルックアップに使用される変数のようです。キーバインドを変更するもっと洗練された方法があると確信していますが、emacs でキーバインドがどのように機能するかをもっと理解したいと思いました。

4

3 に答える 3

5

Paredit は、キーマップを定義する別の方法を使用します。ほとんどのマイナー モードは変数定義でキーマップを定義しますが、Paredit はトップレベルで呼び出しparedit-define-keysキーマップを強制的に初期化します。

つまり、Paredit がバインディングをセットアップするのを防ぐことはできません。(define-key paredit-mode-map … nil)これらを取り除くには、キーマップ内のすべてのキーバインディングを削除する必要があります。

編集: 新しいキーマップを変数に割り当ててキーマップを「リセット」することはできません。(setq paredit-mode-map …)は変数を変更しますがparedit-mode-map、Paredit モードで使用されている実際のキーマップは変更しません。

この変数のバインディングは、定義時、つまり の評価中に一度だけ評価ます。このマクロは内部的に を呼び出し、キーマップ変数の現在の値をこの関数に渡します。モードの将来の使用はすべて、このキーマップのみを参照します。キーマップ変数はマイナー モードによって再度評価されることはありません。したがって、そのバインディングを変更しても何の効果もありません。define-minor-modeadd-minor-mode

キーマップを変更したい場合は、変数が評価される前に、つまり対応するライブラリがロードされる前に、変数を再バインドする必要があります。 define-minor-modeしたがって、フォームで変更してもeval-after-loadまったく役に立ちません。

通常、ほとんどのモードは の本体内でキーマップを定義するため、ライブラリをロードする前にキーマップ変数を変更するとうまくいきますdefvardefvarただし、変数にすでに値がある場合、変数の値は変更されません。したがって、変数にすでにキーマップがある場合、それは変更されません。

しかし、前述したように、Paredit はこのパターンを尊重せず、代わりにそのバインディングを強制的にキーマップに追加します。したがって、Paredit はバインディングを追加するため、変更しても意味がありません。

前述したように、すべてのキーを定義解除して、既存のキーマップを手動でクリアする必要があります。

TL;DR: Smartparens を使用してください。Paredit のすべてをカバーし、柔軟性があり、強力で、拡張性があり、要するに優れています。また、必要なキーバインドを選択できます。

于 2013-05-17T16:42:26.863 に答える
3

自分だけのマイナーモードを作ってみませんか?Paredit モードが行うのはキー バインディングを提供することだけなので、そのキーマップを壊しても何もしません。paredit コマンドは、Paredit モードを使用するかどうかに関係なく使用できます。(誰もあなたにキー割り当てを「強制」しません!)

(defvar snowape-mode-map (make-sparse-keymap))
(define-minor-mode snowape-mode
  "Minor mode for snowape's favorite pareditoid key bindings.
\\<snowape-mode-map>"
  :lighter " Snowape")
(define-key snowape-mode-map (kbd "C-M-<left>") 'paredit-backward)
...

local-set-keyまたは、お気に入りのモード フックで使用することもできます。

(add-hook 'lisp-mode-hook
  (defun lisp-mode-snowape-setup ()
    (local-set-key (kbd "C-M-<left>") 'paredit-backward)))
于 2013-06-13T14:14:54.843 に答える