Reputation: 611
I want to use a minor mode which rebinds a major-mode key that I definitely want to keep. How can I rebind the key without deleting it from the minor-mode map globally? I know I can use define-key
for that, but I would like to keep the binding for other buffers/major modes.
Can anyone help?
Upvotes: 19
Views: 1975
Reputation: 4937
In my case, company-mode
was overriding the cider-repl-mode
bindings for M-p
and M-n
when the Company completions menu was showing. The keymap for the completions menu is company-active-map
, but there's no minor mode corresponding to it (company-mode
is for when the menu is not active), so I couldn't use any of the existing answers.
Here's what I came up with instead:
(add-hook 'cider-repl-mode-hook
(lambda ()
(make-local-variable 'company-active-map)
(setq company-active-map (copy-tree company-active-map))
(define-key company-active-map (kbd "M-p") nil)
(define-key company-active-map (kbd "M-n") nil)))
Upvotes: 3
Reputation: 1508
Here's a function to handle all the cumbersome bits.
(defun local-set-minor-mode-key (mode key def)
"Overrides a minor mode keybinding for the local
buffer, by creating or altering keymaps stored in buffer-local
`minor-mode-overriding-map-alist'."
(let* ((oldmap (cdr (assoc mode minor-mode-map-alist)))
(newmap (or (cdr (assoc mode minor-mode-overriding-map-alist))
(let ((map (make-sparse-keymap)))
(set-keymap-parent map oldmap)
(push `(,mode . ,map) minor-mode-overriding-map-alist)
map))))
(define-key newmap key def)))
Thereafter you can do
(local-set-minor-mode-key '<minor-mode> (kbd "key-to-hide") nil)
Upvotes: 14
Reputation: 28531
It's a bit cumbersome to do. You can do something like:
(add-hook '<major-mode>-hook
(lambda ()
(let ((oldmap (cdr (assoc '<minor-mode> minor-mode-map-alist)))
(newmap (make-sparse-keymap)))
(set-keymap-parent newmap oldmap)
(define-key newmap [<thekeyIwanttohide>] nil)
(make-local-variable 'minor-mode-overriding-map-alist)
(push `(<minor-mode> . ,newmap) minor-mode-overriding-map-alist))))
Upvotes: 16