unbind-key: Ensure that keys are removed from the keymap

* The removal from the keymap is performed by bind-key--remove
* Use the same argument normalization as bind-key
This commit is contained in:
Daniel Mendler 2021-02-10 14:13:36 +01:00
parent ec750952f4
commit 5ca7bc321d

View file

@ -199,17 +199,47 @@ can safely be called at any time."
(defmacro unbind-key (key-name &optional keymap) (defmacro unbind-key (key-name &optional keymap)
"Unbind the given KEY-NAME, within the KEYMAP (if specified). "Unbind the given KEY-NAME, within the KEYMAP (if specified).
See `bind-key' for more details." See `bind-key' for more details."
`(progn (let ((namevar (make-symbol "name"))
(bind-key ,key-name nil ,keymap) (kdescvar (make-symbol "kdesc")))
(setq personal-keybindings `(let* ((,namevar ,key-name)
(cl-delete-if #'(lambda (k) (,kdescvar (cons (if (stringp ,namevar) ,namevar
,(if keymap (key-description ,namevar))
`(and (consp (car k)) (if (symbolp ,keymap) ,keymap (quote ,keymap)))))
(string= (caar k) ,key-name) (bind-key--remove (if (vectorp ,namevar) ,namevar
(eq (cdar k) ',keymap)) (read-kbd-macro ,namevar))
`(and (stringp (car k)) (or (if (and ,keymap (symbolp ,keymap))
(string= (car k) ,key-name)))) (symbol-value ,keymap) ,keymap)
personal-keybindings)))) global-map))
(setq personal-keybindings
(cl-delete-if (lambda (k) (equal (car k) ,kdescvar))
personal-keybindings))
nil)))
(defun bind-key--remove (key keymap)
"Remove KEY from KEYMAP.
In contrast to `define-key', this function removes the binding from the keymap."
(define-key keymap key nil)
;; Split M-key in ESC key
(setq key (mapcan (lambda (k)
(if (and (integerp k) (/= (logand k ?\M-\0) 0))
(list ?\e (logxor k ?\M-\0))
(list k)))
key))
;; Delete single keys directly
(if (= (length key) 1)
(delete key keymap)
;; Lookup submap and delete key from there
(let* ((prefix (vconcat (butlast key)))
(submap (lookup-key keymap prefix)))
(unless (keymapp submap)
(error "Not a keymap for %s" key))
(when (symbolp submap)
(setq submap (symbol-function submap)))
(delete (last key) submap)
;; Delete submap if it is empty
(when (= 1 (length submap))
(bind-key--remove prefix keymap)))))
;;;###autoload ;;;###autoload
(defmacro bind-key* (key-name command &optional predicate) (defmacro bind-key* (key-name command &optional predicate)