14

Qt supports Emacs-style keybindings, however for only up to four keys. To make a point why this limit should be increased it would be useful to show examples of Emacs-style keybindings with even more keys than that. Are there any known examples for this or maybe even a way to programmatically find long key sequences defined in Emacs keymaps?

edit: I thought this was common knowledge, but a key sequence is a set of keys as read in by read-key-sequence. Try F1 k for your candidate and see whether it describes your command or an unrelated one preceding it.

wasamasa
  • 21,803
  • 1
  • 65
  • 97
  • The only ones I can think of off the top of my head are conversions from terminal escape sequences, which doesn't apply to Qt. Going above 3 real keys is unusual. – Gilles 'SO- stop being evil' Jan 15 '18 at 19:08
  • Thank you for providing the context/reason for the question and the link. At first sight - before reading it, I was incorrectly guessing that the question might be off-topic and not helpful for anyone. – Drew Jan 15 '18 at 19:32
  • The problem with this question is that nobody can answer it for sure. Everybody can answer it only for his/her emacs-configuration. It is not opinion based but it is kind of subjective. – Tobias Jan 15 '18 at 19:43
  • @Tobias True, but the variability can be bounded to the built-ins of specific Emacs versions on specific platforms, as [mkcms demonstrates](https://emacs.stackexchange.com/a/38114/15748) with `emacs -q` and which is also true for `emacs -Q`. This in itself is a useful Q&A. – Basil Jan 15 '18 at 19:45
  • @Basil Okay one can derive a set of lower bounds of maximal key sequence lengths. Let's see whether we also get an upper bound;-)... – Tobias Jan 15 '18 at 19:47
  • @Basil About the upper bound;-) : I've stopped at 7000000: `(let ((seq "C-c ") (i 1)) (while t (setq seq (concat seq (make-string 1000 ?a)) i (+ i 1000)) (let ((key (kbd seq))) (message "length: %d" i) (global-set-key key (lambda () (interactive))) (if (lookup-key global-map key) (global-unset-key key) (error "Key sequence %s not set" key)))))` – Tobias Jan 15 '18 at 20:16
  • @Tobias Cool, my condolences. :) – Basil Jan 15 '18 at 20:29
  • 1
    Does this include prefix arguments? If I want to go a thousand lines down, I can say `C-u 1 0 0 0 C-n` which is six keys. – Stig Hemmer Jan 16 '18 at 08:22
  • 1
    @StigHemmer No. Do `F1 k C-u 1 0 0 0 C-n` and see that `C-u` is a key sequence on its own. – wasamasa Jan 16 '18 at 08:37

3 Answers3

23

I tested with the following script,

(key-description
 (car
  (sort
   (let (keyseqs)
     (mapatoms
      (lambda (sym)
        (when (commandp sym)
          (let ((where (where-is-internal sym nil nil t)))
            (when where
              (setq keyseqs (append keyseqs where)))))))
     keyseqs)
   (lambda (a b) (< (length b) (length a))))))

And the longest I get with my .emacs.d is C-x c C-x r i which is some helm command, and with emacs -q I get C-x a i l which runs the command inverse-add-mode-abbrev.

Basil
  • 12,019
  • 43
  • 69
mkcms
  • 1,340
  • 12
  • 13
  • 12
    Ha. Gives me `C-x M-c M-b u t t e r f l y` :) I'd forgotten that I'd done that... – phils Jan 15 '18 at 21:22
  • `where-is-internal` by far dominates CPU time here, but you can still easily shave a few cycles by destructively prepending the shorter list to the longer via `(setq keyseqs (nconc (where-is-internal sym nil nil t) keyseqs))`. – Basil Jan 15 '18 at 21:41
  • 1
    @phils I recognize the reference, but what exactly did you set that command to do? – Dan Is Fiddling By Firelight Jan 16 '18 at 15:38
  • @DanNeely, I guess you've never seen `M-x butterfly` ? I just bound it to that command for increased authenticity :) – phils Jan 16 '18 at 21:34
6

I can't answer about what the longest might be out there somewhere, but here's one bit of info that might help.

  1. I have some libraries that provide a set of related commands bound to keys in a keymap that I bind to a prefix key.

    Because I don't want to co-opt user keys etc., I typically bind such a prefix key under, say C-x or, for other-window commands, under C-x 4 (keymap ctl-x-4-map).

  2. The same considerations apply to groups of commands in such a keymap: they sometimes get their own keymap. And so on, recursively.

  3. I expect that at least some users might want to rebind any such keymaps (at any level) to their own, shorter, prefix keys, or they might want to bind specific commands to shorter key sequences. But I don't want to do that in the library itself, obviously.

Here's an example of one such fairly long key: C-x 4 j t . % * (seven keystrokes), which is bound to command icicle-bookmark-file-this-dir-all-tags-regexp-other-window in Bookmark+.

Anatomy:

  • On the C-x 4 prefix key (ctl-x-4-map).

  • On the j prefix key, which is for all commands for jumping to a bookmark.

  • On the t prefix key, which is for all commands for jumping to bookmarks that are tagged in some way.

  • On the . prefix key, which is for all commands for jumping to bookmarks that are for files in the current directory that are tagged in some way.

  • On the % prefix key, which is for all commands for jumping to bookmarks that are for things in the current directory that have tags that match a regexp you are prompted for.

  • On the * key, which is for all commands for jumping to bookmarks that are for things in the current directory that have tags, ALL of which match a regexp you are prompted for. (By contrast, C-x 4 j t . % + is for bookmarks SOME of whose tags match the regexp.)

All of that is conventional in Bookmark+ (and some of it corresponds to Dired conventions, BTW): j is for jump commands, t is for tagged, . is for current-directory, % is for regexp, and * is for all (+ is for some).


(Oh, and using @mkcms's sexp, I get C-x 4 j t f % *, which is equally long. The f stands for file. It's like C-x 4 j t . % *, but the candidate bookmarks for completion are all file bookmarks, not just those for files in the current directory (.).)

Drew
  • 75,699
  • 9
  • 109
  • 225
0

Magit adds long sequences as it allows options to be toggled. For example when you ask for the log you can select short or long options, if you want remote branches or not, if you want the graphical display of branches and so on. The basic request for a log is just a couple of keystrokes from the magit-status buffer but you can add many more.

The same applies to committing, two keystrokes for a basic commit, but lots of optional additions.

So the question is under specified, are you only considering a stock (whatever that means) emacs?

icarus
  • 1,904
  • 1
  • 10
  • 15
  • 1
    Far from it, I accept examples coming from anywhere. What you describe is a set of key sequences though, with every key sequence executing one command. To get an idea what a key sequence is, try using `F1 k` and see how many keys you can type until it describes the command. – wasamasa Jan 15 '18 at 20:09