6

When deciding on which key binding I want for a specific command, it would be very nice to know if any of my installed mode maps (global, major and minor) have already used this key binding for some command, and if so, what command.

I have looked at helm-descbinds, but it only searches in the currently active modes rather than all of them.

Is there a way to search all of the modes, regardless if they are active?

Drew
  • 75,699
  • 9
  • 109
  • 225
whacka
  • 383
  • 1
  • 6
  • 2
    How do you plan on searching a keymap that hasn't been instantiated and only exists in the form of code that would need to be evaluated or parsed first? – wasamasa Aug 27 '15 at 17:34
  • I hoped that there would be some list of major modes installed that Emacs could loop through, or perhaps parse the source to check any set-key commands. Though even just the ability to search through all instantiated modes (not necessarily active modes) would still be a huge improvement to manually checking a keybind in each buffer. – whacka Aug 27 '15 at 18:34
  • I took the liberty to edit your post to make the terminology that it uses more precise. See [this post](http://emacs.stackexchange.com/q/3555/504) for more info. – itsjeyd Oct 31 '15 at 16:04

2 Answers2

5

As mentioned by others, you can of course not look for bindings in maps that haven't been loaded yet (due to autoloading for example). There are however a few heuristics which can help you find known keymaps:

  1. all known minor mode maps are stored in minor-mode-map-alist, regardless of whether the minor mode is active or not;
  2. by convention, the vast majority of mode maps have names ending in "-mode-map".

Following this latter heuristic, one can devise the following command, which looks for a given key binding in all keymaps found in the obarray with names ending in "-mode-map". The results are displayed in a buffer.
Try loading as many packages as you can before you use it, so that more keymaps can be examined.

(require 's)

(defun list-known-bindings (key)
  (interactive "kList known bindings for key: ")
  (with-current-buffer (get-buffer-create "*known bindings*")
    (erase-buffer)
    (mapatoms (lambda (sym)
                (when (or (eq sym 'global-map)
                          (and (boundp sym)
                               (symbol-value sym)
                               (s-ends-with-p "-mode-map" (symbol-name sym))
                               (keymapp (symbol-value sym))))
                  (let ((binding (lookup-key (symbol-value sym) key t)))
                    (when (and binding
                               (not (numberp binding)))
                      (insert (format "%-40s `%s'\n"
                                      (format "`%s'" sym)
                                      (if (keymapp binding)
                                          "KEYMAP"
                                        binding))))))))
    (sort-lines nil (point-min) (point-max))
    (goto-char (point-min))
    (insert
     (format "Known bindings for key: %s\n\n" (key-description key))
     (format "%-40s %s" "Map" "Binding\n")
     (s-repeat 40 "-") " " (s-repeat 30 "-") "\n") 
    (display-buffer (current-buffer))))
François Févotte
  • 5,917
  • 1
  • 24
  • 37
  • Thanks! This seems to cover a good range of bindings. My only issue is that the modes aren't sorted (which makes the ones I care about hard to see). I tried to implement that but it turns out that I don't know how to sort association lists. How would one implement that? – whacka Aug 28 '15 at 01:56
  • Sorting association lists is another matter, and I think you would be better off asking for this in a separate question. For that matter, I wouldn't be surprised if there already was a few questions about alist manipulations around here. – François Févotte Aug 28 '15 at 06:28
  • The biggest problem in your question however seems to be the notion of "the ones I care about". How would you programmatically determine whether you care about a mode or not? – François Févotte Aug 28 '15 at 06:29
  • I just meant that it would be easier to look at particular modes in the output if it was in alphabetical order. Though it seems the keybindings I search for don't return a gigantic list anyway, so it's not a big deal. – whacka Aug 28 '15 at 15:18
  • I edited the code to sort the lines alphabetically. – François Févotte Aug 28 '15 at 18:50
  • How the function `list-known-bindings` work? It takes only a single key as a input. And hitting any key, say `y` produces the error `call-interactively: Wrong number of arguments: (lambda (key) (interactive "kList known bindings for key: P") (save-current-buffer (set-buffer (get-buffer-create "*known bindings*")) (erase-buffer) (mapatoms (function (lambda (sym) (if (or (eq sym (quote global-map)) (and (boundp sym) (symbol-value sym) (s-ends-with-p "-mode-map" (symbol-name sym)) (keymapp (symbol-value sym)))) (progn (let ((binding ...)) (if (and binding ...) (progn ...)))))))) (sort-lin.....` – Name Aug 28 '15 at 19:09
  • It works for me when I take out the `\nP` at the end of the interactive string. Thanks again for this, I didn't think to just sort the buffer content itself. Though just to clarify, when would `binding` be a keymap? – whacka Aug 28 '15 at 21:08
  • @Name sorry, there's a bug in this version. I edited the answer to fix it. – François Févotte Aug 29 '15 at 08:56
  • @whacka the binding is a keymap when it is only a prefix. For example, if you try to list the bindings for `C-c`, it can be a binding in itself in certain modes, but for others be a prefix (meaning the keymap binds squences beginning with `C-c`, like `C-c C-c`) – François Févotte Aug 29 '15 at 09:00
  • Ok, it should be mentioned that this functions uses some function from `s.el`. Perhaps writing a `(require ...)` would be helpful. – Name Aug 29 '15 at 09:14
0

Is there a way to search all of the modes, regardless if they are active?

No.

One brute force method is to load all the common modes you normally use and then test for the key bindings for each mode.

One command that can get you started is to get a list of available modes:

M-x apropos-command -mode$
Emacs User
  • 5,553
  • 18
  • 48
  • That command looks nice, thanks. I tried it as `M-x apropos-command mode-map$` and it gave me the list of all mode maps that were loaded at one point in the current Emacs session. Though I'm not sure how to parse this in a way that I could easily search for a specific key combination. – whacka Aug 27 '15 at 18:42
  • Not mode-map$ but just -map$ as in `M-x apropos-command -map$` will get you commands that end in *-map*. – Emacs User Aug 27 '15 at 19:27