3
votes

For example, with C-h k I can ask to Emacs "what does C-right do in this buffer?". If the current buffer was a Lisp buffer in my setup, Emacs would answer paredit-forward-slurp-sexp. From that, I can guess that the binding of C-right to paredit-forward-slurp-sexp is from the paredit mode map because the command name is prefixed by paredit, but that's a heuristic. How can I do that programmatically, i.e., how can I ask "where is the binding of C-right in this buffer coming from?"

Is writing a function that in this case checks current global map, current major mode map, paredit-mode-map, paredit-forward-mode-map, paredit-forward-slurp-mode-map, paredit-forward-slurp-sexp-mode-map the only way?

1

1 Answers

7
votes

Here's the code that you can adapt to your needs:

(defun bunch-of-keybindings (key)
  (list
   (minor-mode-key-binding key)
   (local-key-binding key)
   (global-key-binding key)))

Sample input:

(bunch-of-keybindings (kbd "C-c @ C-c"))

Output:

(((hs-minor-mode . hs-toggle-hiding)) 1 2)

The numbers mean that nothing matched in local and global map.

UPD: Added overlay-key-binding

Keymaps can also be attached to overlays, in which case they take priority when the cursor is inside the overlay. For instance, yasnippet does this. Here's a function to check for that:

(defun overlay-key-binding (key)
  (mapcar (lambda (keymap) (lookup-key keymap key))
          (cl-remove-if-not
           #'keymapp
           (mapcar (lambda (overlay)
                     (overlay-get overlay 'keymap))
                   (overlays-at (point))))))

So the updated list is:

(defun bunch-of-keybindings (key)
  (list
   (minor-mode-key-binding key)
   (local-key-binding key)
   (global-key-binding key)
   (overlay-key-binding key)))