Skip to content
This repository was archived by the owner on Aug 23, 2025. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 48 additions & 15 deletions bind-key.el
Original file line number Diff line number Diff line change
Expand Up @@ -168,16 +168,19 @@ or operates on menu data structures, so you should write it so it
can safely be called at any time."
(let ((namevar (make-symbol "name"))
(keyvar (make-symbol "key"))
(kmapvar (make-symbol "kmap"))
(kdescvar (make-symbol "kdesc"))
(bindingvar (make-symbol "binding")))
`(let* ((,namevar ,key-name)
(,keyvar (if (vectorp ,namevar) ,namevar
(read-kbd-macro ,namevar)))
(kmap (if (and ,keymap (symbolp ,keymap)) (symbol-value ,keymap) ,keymap))
(,kmapvar (or (if (and ,keymap (symbolp ,keymap))
(symbol-value ,keymap) ,keymap)
global-map))
(,kdescvar (cons (if (stringp ,namevar) ,namevar
(key-description ,namevar))
(if (symbolp ,keymap) ,keymap (quote ,keymap))))
(,bindingvar (lookup-key (or kmap global-map) ,keyvar)))
(,bindingvar (lookup-key ,kmapvar ,keyvar)))
(let ((entry (assoc ,kdescvar personal-keybindings))
(details (list ,command
(unless (numberp ,bindingvar)
Expand All @@ -186,27 +189,57 @@ can safely be called at any time."
(setcdr entry details)
(add-to-list 'personal-keybindings (cons ,kdescvar details))))
,(if predicate
`(define-key (or kmap global-map) ,keyvar
`(define-key ,kmapvar ,keyvar
'(menu-item "" nil :filter (lambda (&optional _)
(when ,predicate
,command))))
`(define-key (or kmap global-map) ,keyvar ,command)))))
`(define-key ,kmapvar ,keyvar ,command)))))

;;;###autoload
(defmacro unbind-key (key-name &optional keymap)
"Unbind the given KEY-NAME, within the KEYMAP (if specified).
See `bind-key' for more details."
`(progn
(bind-key ,key-name nil ,keymap)
(setq personal-keybindings
(cl-delete-if #'(lambda (k)
,(if keymap
`(and (consp (car k))
(string= (caar k) ,key-name)
(eq (cdar k) ',keymap))
`(and (stringp (car k))
(string= (car k) ,key-name))))
personal-keybindings))))
(let ((namevar (make-symbol "name"))
(kdescvar (make-symbol "kdesc")))
`(let* ((,namevar ,key-name)
(,kdescvar (cons (if (stringp ,namevar) ,namevar
(key-description ,namevar))
(if (symbolp ,keymap) ,keymap (quote ,keymap)))))
(bind-key--remove (if (vectorp ,namevar) ,namevar
(read-kbd-macro ,namevar))
(or (if (and ,keymap (symbolp ,keymap))
(symbol-value ,keymap) ,keymap)
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
(defmacro bind-key* (key-name command &optional predicate)
Expand Down