How to rewrite keybindings of Emacs minor mode keymap
Most minor mode will define some custom key bindings of their own. Most of time they have a keymap variable with the name modename-mode-map. For example, help-mode-map for Emacs Help system, flyspell-mode-map for spell checker. Most of the time they are works fine. But some of them will conflict with my global keybindings.
For example, the flyspell-mode has keymap definition like this
(defvar flyspell-mode-map (let ((map (make-sparse-keymap))) (if flyspell-use-meta-tab (define-key map "\M-\t" 'flyspell-auto-correct-word)) (define-key map flyspell-auto-correct-binding 'flyspell-auto-correct-previous-word) (define-key map [(control ?\,)] 'flyspell-goto-next-error) (define-key map [(control ?\.)] 'flyspell-auto-correct-word) (define-key map [?\C-c ?$] 'flyspell-correct-word-before-point) map) "Minor mode keymap for Flyspell mode--for the whole buffer.")
I already defined C-c as coping text.
(global-set-key "\C-c" 'kill-ring-save)
When enable flyspell mode with "M-x flyspell-mode" command. The global set key binding C-c will be overwrite. I know how to add new key bindings to a minor mode map:
;; add or rewrite minor map key binding (add-hook 'ielm-mode-hook (lambda () (define-key ielm-map (kbd "<return>") 'ielm-return)))
See Rebind Ctrl-m and Enter in Emacs
But how to disable a minor mode key binding? You see the "defvar flyspell-mode-map" is always executed when loading flyspell-mode. So redefine the minor mode key map aren't gonna work.
(add-hook 'flyspell-mode-hook (lambda () (defvar flyspell-mode-map (let ((map (make-sparse-keymap))) (if flyspell-use-meta-tab (define-key map "\M-\t" 'flyspell-auto-correct-word)) (define-key map flyspell-auto-correct-binding 'flyspell-auto-correct-previous-word) (define-key map [(control ?\,)] 'flyspell-goto-next-error) (define-key map [(control ?\.)] 'flyspell-auto-correct-word) ;(define-key map [?\C-c ?$] 'flyspell-correct-word-before-point) map) "Minor mode keymap for Flyspell mode--for the whole buffer.") ) )
We comment out the key binding which conflict with us. It won't work because in flyspell.el it will be redefined again. Do a global key set also not work:
(add-hook 'flyspell-mode-hook (lambda () (defvar flyspell-mode-map (let ((map (make-sparse-keymap))) (if flyspell-use-meta-tab (define-key map "\M-\t" 'flyspell-auto-correct-word)) (define-key map flyspell-auto-correct-binding 'flyspell-auto-correct-previous-word) (define-key map [(control ?\,)] 'flyspell-goto-next-error) (define-key map [(control ?\.)] 'flyspell-auto-correct-word) ;(define-key map [?\C-c ?$] 'flyspell-correct-word-before-point) map) "Minor mode keymap for Flyspell mode--for the whole buffer.") (global-set-key "\C-c" 'kill-ring-save) ) )
If we look at the documentation of global-set-key: M-x describe-function global-set-key.
Note that if KEY has a local binding in the current buffer, that local binding will continue to shadow any global binding that you make with this function.
At the end, I find the answer, but its unexpected, the right way is to redefine C-c in the minor mode key map, it still gonna shadowing the global binding, but with our command.
(add-hook 'flyspell-mode-hook (lambda () (define-key flyspell-mode-map "\C-c" 'kill-ring-save) ) )
This resolve my problem, but the better solution I want is prevent the minor mode from defining particular key binding at all.
Emacs
Search in Emacs
Configuring Emacs
Editing in Emacs
Basic Editings