Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an emacs encyclopedia of keybindings?

Tags:

emacs

Here's a common scenario in Emacs: I want to bind a function to a key, but I'm not sure whether it's likely to conflict with an existing keybinding (easy to check), or a keybinding in a "popular" module (hard to check, what's "popular"?)

It would be nice to have an encyclopedia: If I looked up C-c C-t, I would see that it's bound to:

  • org-todo in org-mode
  • sgml-tag in sgml-mode
  • ...

Is there any such thing? I know I can use C-c A through C-c-Z etc., but sometimes it's nice not to have to press and release the Ctrl key.

like image 504
zellyn Avatar asked Apr 10 '13 23:04

zellyn


1 Answers

I've never come across a resource for this sort of thing. Package authors are totally free to add and change keybindings, both in their own keymaps and in the global keymap. It would be hard to maintain an index.

Emacs can load features dynamically, so the active key commands are dynamic too, and are subject to the features you have installed and required. For instance, if you don't require paredit you won't be able to inspect its keymap.

M-x describe-bindings will tell you about the key bindings Emacs currently has loaded. This is a long list! The show-key-bindings function below will trim this down to bindings that use modifier keys.

(defun get-bindings ()
  (with-temp-buffer
    (describe-buffer-bindings (current-buffer))
    (buffer-string)))

(defun format-binding (b)
  (let ((ws (split-string b))) 
    (apply 'format "%s\t%s" (butlast ws) (last ws))))

(defun binding? (str)
  (string-match-p (rx bol (any "C" "M" "H" "S")) str))

(defun join-string-lines (lines)
  (mapconcat 'identity lines "\n"))

(defun show-key-bindings ()
  "Show the active keybindings for the current buffer."
  (interactive)
  (let* ((bs  (split-string (get-bindings) "\n" t))
         (fmt (mapcar 'format-binding (remove-if-not 'binding? bs))))
    (save-excursion
      (let ((help-window-select t))
        (with-help-window  "*active bindings*"
          (princ (join-string-lines fmt)))))))

Just to recap, there are a few functions you can use to set up bindings:

  • global-set-key

    Use this when you want some command to be always available.

  • local-set-key

    Sets the key biding for the current buffer. I like to use this in my hooks to make a keybinding available for a specific mode.

  • define-key

    Adds a command to a keymap. The keymap must already be bound, so this tends to be too brittle to use in your config.

If you're concerned about accidentally overriding a mode's bindings in you emacs config, the easiest thing to do is figure out whether you really need the command to be global. Use local-set-key where you can.

You could also look into packages like key-chord (M-x package-install key-chord) or define your own minor modes with custom keymaps if you find that you're running out of keys.


With some virtuosic shell scripting or elisp, it should be possible to parse a list of elisp files and extract the keybindings they define. I might look into that later.

In the meantime, the following unix shell command will find all the references to the above key-binding forms in a directory tree. You can run this in your .emacs.d to inspect the keybindings set in your elpa packages.

tree -fxi -P '*.el' | xargs egrep -s 'local-set-key|define-key|global-set-key'
like image 87
Chris Barrett Avatar answered Oct 02 '22 14:10

Chris Barrett