reddit / emacs

Creating and displaying cheatsheets of keybindings

andyjda · 2022-11-02 23:49
I've been thinking it'd be nice to have this feature, and it shouldn't be too hard to implement. But before I go and start working on it (which wouldn't be in a while, because of previous obligations), I want to check if there's already something that does this, or comes close. Here's the behavior I'd like: with a simple command, I can open a new buffer that shows me a "cheatsheet" with all the keybindings I've saved before, along with their command-name and a brief description. Additional nice features would be: * ability to group keybindings by modes * ability to filter by the current active mode(s), so that only keys/commands related to it are shown * ability to save keybindings interactively * ability to save keybindings easily from a mode's keymap. Something like: in the \*Help\* buffer's description of the mode, select any commands, and save them to the cheatsheet Often it is enough to do a quick `describe-mode` to find the name of the function I'm looking for, but I think this feature could be particularly helpful for major modes like `magit` or `org`, which can have quite complex keymaps. It could also help people who are just starting out with Emacs. Do you know if a feature along these lines already exists? I found [this cheatsheet package](https://github.com/mykyta-shyrin/cheatsheet) that comes quite close, although it lacks some of the features I'd like and (most importantly) does not automatically save cheatsheets between sessions. I haven't taken a good look at the code there yet, but I think I might use it as my starting point. Would people be interested in this features? Any advice/critique is appreciated :)
tapesales · 2022-11-03 01:12
I normally either hit C-h m for help on whatever modes are active, which prints the keybindings too. Or I hit C-h b b, OR I do M-x <mode-prefix> then call embark-act then embark-collect. Doomers can do: M-x <mode-prefix> C-; S to collect the M-x results into a buffer for perusal. This implies that you've got which-key and marginalia installed as well.
andyjda · 2022-11-03 01:31
maybe I wasn't using which-key right, but I had it installed for a couple of days and didn't get much value out of it. Most of the time, I'm hitting key-bindings I know, so the which-key pop-up is just distracting. And then when I need to find a specific key-binding (for an action that I know is possible but whose keys I forgot), it doesn't help to see *all of the currently available bindings*; that's usually a very long list: say I'm org-mode and I want to remember they keys for insert today's date: the prefix C-c [is followed by countless other combinations](https://orgmode.org/worg/orgcard.html). Maybe which-key becomes useful once it's integrated with all those other packages you mentioned but I'd like to 1) keep my config simple 2) when I'm looking for a specific key combination, find it as soon as possible, ideally with just a single command
FrozenOnPluto · 2022-11-03 02:52
Multiple decade user here — For all day every day keys, I’ll forget my childrens names before my keybinds. c-h m for less common lookups M-x (with vertico, etc) for less commonly used stuff that I don’t have binds for or never remember the binds. Like indent-region or org-whatevwr-roam-insert Org notes for things I need reference notes And a huge stack of hydra (popup menus) I made for lesser used things that I want my own discoverability or menus for.. stuff not keybind or my memory worthy but use all the time :) I have alt-spacebar to jump to a top level menu, that offers submenus for org and note keeping stuff, coding stuff, general utils, fast open variou note files, that sort of thing; The util submenu goes to tools like side by side diffing of direcvtories, etc.. things I use once in awhile, but don't need on keybind, but do want to be able to just discover it by picking through a menu. So I never use cheat sheets, because I’ve got my own discoverability systems. Love the idea just no use for it for myself. edit: Fixed some typos (writing on phone)
andyjda · 2022-11-03 03:12
Thanks. I think even for someone who’s been using Emacs for a long time, this could be helpful when trying out a new package. I also usually resort to C-h m, but if the key map is large or complex I feel that finding the right command takes longer than it should. Plus, I often completely forget the name of the command I’m looking for (I just have a general idea of what it does), so even with a good completion framework, M-x can only take me so far 😆
FrozenOnPluto · 2022-11-03 03:18
Thats the rub; I see that as.. theres no way to automagically create the cheatsheet in advance, you'd have to pick and choose to record the good bits over time, as you discover them. So your'e really talking like bookmarks perhaps, or in my case.. I keep such hints in org notes. (I forget the framework name, but theres one that automagically guess hyperlinks and functions to call based on context.. maybe that could help out too.) So if going through the effort of recording (or flagging) your favorite bits, well, I keep a org note perhaps, and assign that a hydra menu key or a keybind, that I would use often enough to never forget \_that\_ (plus maybe a load-time hint.. so if you've not used Emacs in a year, then when it comes up it'd say 'hey, hit this keybind to bring up your notes') But, if you just wanted to make a package that formalized this process.. a way to perhaps 'mark' favorite help pages, function names, notes, whatevers, and then presented that list in some nice way, could work; could even just be an org file, that your package appends to. Or maybe bookmark+ or something.
andyjda · 2022-11-03 03:26
Good point about org mode. But the advantage of making a package specifically made for this could be that it’d be easier to record the “cheats.” There could be something like “add the latest executed command to cheat sheet” or like I said, the user could quickly add new cheats from a mode’s Help buffer. I was thinking of doing it just in org mode but I think it wouldn’t be as seamless
howardthegeek · 2022-11-03 04:03
So I've been playing around with the cheat sheet project that you mentioned, and it seems like it would work for what you're looking for. You save all the key bindings you want in your .init.el file. Were you looking for a more interactive way to add the key bindings?
FrozenOnPluto · 2022-11-03 04:16
Sure; record last key or a browser of recent keys could be cute. Then a nice table display buffer.
andyjda · 2022-11-03 04:23
>You save all the key bindings you want in your .init.el file. Yeah this approach is fine but I think a more interactive one might be better. And offer shortcuts in some cases (like if I'm looking at a particular Help buffer). Also, since the cheats are saved in a plist, I figured it'd be better to just automatically store the plist itself, in init or in its own file (probably better, to avoid clutter)
dalanicolai · 2022-11-03 05:38
I have also written a package, similar to cheatsheet, which can be found at [https://github.com/dalanicolai/emacs-key-guide](https://github.com/dalanicolai/emacs-key-guide). Although I did not write it too long ago, I forgot if I was aware of the cheatsheet package; probably not, because I guess then I would not have written it from scratch. Anyway, as you will see, the README contains development notes, but I remember to have done a bit more work on the package than written in those notes. I remember to have more or less finished the package, but I have not (yet) had time to work (more) on its documentation. I remember that I was working on adding 'default' sections that a user could add to the cheat sheet, e.g. a 'navigation' section or a 'edit' section etc. Examples of cheat-sheet definitions are found at the beginning of the `key-guide.el` file. Also, the key-guide buffer supports hydra and which-key style formatting. It also works with evil, where it also shows the keybindings when entering visual-state (unlike which-key). It also contains all kinds of handy function to help you quickly create a 'key guide'. The 'key guide' can be defined by only providing keys, and the function names would be added automatically. It also works the other way around (which makes more sense, as you'd probably usually want to fix the function names, and automatically 'adapt/update' the keybindings). I have just added a screenshot to the README, see [here](https://raw.githubusercontent.com/dalanicolai/emacs-key-guide/main/key-guide-demo.png). Finally, if you want to try it, just evaluate the `key-guide.el` file and press `C-.` to toggle the key guide (in any buffer you'd like to show a guide; each guide it bound to a specific buffer, and auto-hides/shows when switching buffers). Of course, just send me questions if you have any...
[deleted] · 2022-11-03 06:02
[deleted]
deaddyfreddy · 2022-11-03 10:33
as for keymaps and modes, `which-key` has some useful functions, like `which-key-show-keymap`, `which-key-dump-bindings`, `which-key-show-major-mode` etc
JDRiverRun · 2022-11-03 12:48
I have bound `("C-h B" . embark-bindings)`. This is a great way to browse available bindings in any mode, with narrowing. E.g. type 'org' in an org-buffer.
andyjda · 2022-11-03 13:21
I haven’t used embark before; I’ll give it a try. What are the options/commands for narrowing the key bindings?
andyjda · 2022-11-03 13:59
Does which-key offer any way to narrow keybindings by what they do, rather than their mode or prefix? In my experience which-key is basically the same as inspecting a mode’s keymap. It’s useful, but if I’m looking for a specific command, it’s annoying to have to sift through so much information. Right now my go-to is to use a search engine to search for a description of the command I’d like. I don’t think there’s a way to fix that in Emacs, but I could make sure to save that command so it’d be easier to find next time
JDRiverRun · 2022-11-03 14:37
First, note that embark does [much more](https://karthinks.com/software/fifteen-ways-to-use-embark/) than show available bindings. But `embark-bindings` provides a completing-read list of bindings, with nice styling. I use vertico with orderless style and marginalia (which adds docstring 1st line), so it looks [like this](https://user-images.githubusercontent.com/93749/199742558-1e8931c4-e979-469a-b648-2a22f9fad7b6.png). But whatever options you use for minibuffer-based narrowing should "just work". The other cool embark feature I use for things like this — while in `embark-bindings`, you can embark *from there* (`C-,` for me), the hit `S` to snapshot your current narrowed results, and get your own custom cheat sheet exported to a long-lived buffer. E.g. if I'm working on org tables, I might `C-h B` to bring up embark-bindings, enter `org table !edit` to get all the bindings for org table (except edit ones), `S`napshot the results to a buffer, then refer to it to [recall table bindings](https://gist.github.com/jdtsmith/ade7fcc687174b9ea4b4725cae00d2a3?permalink_comment_id=4357227#gistcomment-4357227).
invsblduck · 2022-11-03 15:09
I think which-key in fact helps solve this problem for most. I will explain my opinion as to why, but I don't want to deter or detract you from the great journey of learning and hacking and making your own! I have never written an emacs package :) First of all, one of the ways I use which-key for discoverability is by using its help facility (`C-h h`), which on my system brings every choice inside helm, IIRC, allowing me to usually fuzzy-find anything I'm looking for very quickly and press `RET` (to your point of `C-c` or `C-x` prefixes hiding a lot of gems:)). The home-grown cheatsheet likely loses workflow efficiency as it blossoms with content and you need to maintain it. You will spend time reorganizing into categories, eventually you will need to search it to find what you're looking for, and of course the hardest part is being able to discover the bindings in the first place so they can be captured into the sheet! Using a dedicated bind to open the cheat sheet, then having to search it, then eventually applying the desired binding (if it exists in the sheet) in the target buffer is more steps than using which-key, IMO. Fortunately, which-key is pretty configurable -- you can disable it from showing until you explicitly [activate which-key manually](https://github.com/justbur/emacs-which-key#manual-activation). According to the GitHub page, it was originally a rewrite of [guide-key](https://github.com/kai2nenobu/guide-key). Good luck!!
deaddyfreddy · 2022-11-03 16:39
> Does which-key offer any way to narrow keybindings by what they do, rather than their mode or prefix? Do you know any heuristics which allow telling "what they do"? I can't think of any reliable, emacs internals have a lot of inconsistent parts. > It’s useful, but if I’m looking for a specific command, it’s annoying to have to sift through so much information. Sometimes I use `counsel-M-x` + `ivy-rich`, the former allows narrowing commands using regexes (depends on your setup) and shows their shortcuts, the latter shows their description.
hmelman · 2022-11-03 17:08
I think which-key helps a lot. If you know a prefix key it's sufficient; e.g., on M-s or M-g or C-x r. Your counter-example of using it in org-mode is valid, but I think it's more a function or org having a million bindings which kinda breaks any help system. For org, I think the best bet is an existing org-mode cheatsheet, but I'm not much of an org user. You can change which-key's sorting to be by command name instead of key binding, that might help you find things easier. If there are commands I don't know I tend to use M-x and a completion system to narrow to the command and some annotation mechanism to show the keybinding. Currently I'm using vertico and marginalia for this and orderless helps matching a lot. Helm, Ivy/Counsel, smex and others work just fine too. If I lookup the same command a few times, the binding tends to stick and if not, I'll probably bind it to something which I'm more likely to remember. If you want to search for a binding instead of a command name there's counsel-descbinds in the ivy world or embark-bindings in the vertico and similar world. The standard describe-bindings on C-h b will open a buffer that you can use C-s on. I now find that when I learn a new package I often make a transient for its commands and bind it to an easy key. it doesn't take too long and going through this process helps me learn what commands the package offers and using the transient helps me learn the bindings I assigned (usually mirroring the packages bindings). You could do this with hydra too, I prefer using a transient. Now that transient.el ship with emacs 28, some packages are including their own which is great (e.g., rg.el).
andyjda · 2022-11-03 18:21
>I don't want to deter or detract you from the great journey of learning and hacking and making your own! I have never written an emacs package :) thanks :) part of the reason I'm exploring if there's currently-existing solutions is that I had started writing a [rudimentary package for another feature](https://github.com/andyjda/emacs-configuration/blob/dev/.emacs.d/custom/modes/shell-output-mode.el), only to then find out it already was built into Emacs (in that case, the built-in commands `find` and `grep` mostly did the job). You're right that the cheatsheet idea has its flaws, and I haven't explored `which-key` much. I will take a better look at it. Maybe I can make some edits on top of that package to achieve something along the lines of what I'm looking for
andyjda · 2022-11-03 18:25
>Do you know any heuristics which allow telling "what they do"? I don't 😂 that's why I have to resort to a search engine. The idea of the cheatsheet could be that the heuristic is just "I remember using this command before, maybe I saved it". And then if the command wasn't saved, the user would go about the usual business to figure out what it was, but they'd then be able to save it with just a few keystrokes, ideally making things easier for themselves next time. Not a perfect, but it could be an improvement. I do need to look more into `which-key`, `embark`, and `counsel` though: it seems these would help a lot. I'm just weary of adding too many things too much complexity for a relatively simple feature
andyjda · 2022-11-03 18:27
Good point! Actually the transient UI looks pretty much like what I was looking for. Maybe the cheatsheet idea would be just to provide functions that make it easier to create a transient based on a particular mode, and add/edit its commands. Do you think that would make sense? Let me know if you have any advice on creating transients, I haven't done it before
andyjda · 2022-11-03 18:29
Thanks! Looks really useful; I'll have to set aside some time to look into this
andyjda · 2022-11-03 18:32
Thanks, this looks great! Am I right in thinking this is quite similar to [which-key](https://github.com/justbur/emacs-which-key)? Does it provide features for narrowing down the list of available bindings, or save some shortcuts to a particular view?
hmelman · 2022-11-03 21:05
I don't see a need for an api, just define them in your init.el or in a file that it loads. Here's one I use for help: ;;; A Help TRANSIENT on C-S-h (transient-define-prefix hrm-help-transient () "Help commands that I use. A subset of C-h with others thrown in." ["Help Commands" ["Mode & Bindings" ("m" "Mode" describe-mode) ("M" "Minor Modes" consult-minor-mode-menu) ("b" "Major Bindings" which-key-show-full-major-mode) ("B" "Minor Bindings" which-key-show-full-minor-mode-keymap) ("d" "Descbinds" describe-bindings) ; counsel-descbinds or embark-bindings ("t" "Top Bindings " which-key-show-top-level) ] ["Describe" ("C" "Command" helpful-command) ("f" "Function " helpful-callable) ("v" "Variable" helpful-variable) ("k" "Key" helpful-key) ("s" "Symbol" helpful-symbol) ; was helpful-symbol, counsel provides a small useful keymap ("l" "Library" apropos-library) ] ["Info on" ("C-c" "Command" Info-goto-emacs-command-node) ("C-f" "Function" info-lookup-symbol) ; counsel-info-lookup-symbol ("C-v" "Variable" info-lookup-symbol) ; counsel-info-lookup-symbol ("C-k" "Key" Info-goto-emacs-key-command-node) ("C-s" "Symbol" info-lookup-symbol) ; or .? was counsel-info-lookup-symbol ] ["Goto Source" ("" "" ignore) ("F" "Function" find-function-other-frame) ("V" "Variable" find-variable-other-frame) ("K" "Key" find-function-on-key-other-frame) ("" "" ignore) ("L" "Library" find-library-other-frame) ] ["Apropos" ("ac" "Command" apropos-command) ("af" "Function" apropos-function) ("av" "Variable" apropos-variable) ("ad" "Documentation" apropos-documentation) ("as" "Symbol" consult-apropos) ; adds completion over 'apropos ] ] [ ["Internals" ("I" "Input Method" describe-input-method) ("G" "Language Env" describe-language-environment) ("S" "Syntax" describe-syntax) ("T" "Categories" describe-categories) ("O" "Coding System" describe-coding-system) ("o" "Coding Briefly" describe-current-coding-system-briefly) ("T" "Display Table" describe-current-display-table) ("e" "Echo Messages" view-echo-area-messages) ("H" "Lossage" view-lossage) ] ["Describe" ("." "At Point " helpful-at-point) ("c" "Key Briefly" describe-key-briefly) ("p" "Key Map" describe-keymap) ("A" "Face" describe-face) ; counsel-describe-face ("w" "Where Is" where-is) ("=" "Position" what-cursor-position) ("g" "Shortdoc Group" shortdoc-display-group) ] ["Info Manuals" ("C-i" "Info" info) ("C-4" "Other Window" info-other-window) ("C-e" "Emacs" info-emacs-manual) ("C-l" "Elisp" info-elisp-manual) ("C-r" "Manual" info-display-manual) ] ["External" ("N" "Man" consult-man) ("W" "Dictionary" lookup-word-at-point) ("D" "Dash" dash-at-point) ] ] ) (global-set-key (kbd "C-S-h") 'hrm-help-transient)
dalanicolai · 2022-11-03 22:52
Well it is akin to which-key, but instead of showing all keybindings, you can configure which key-bindings to show in which situation, and categorize by function. I would say it is mostly a 'complement' to which-key (as which key does already very well what it does). It is more like hydra/transient, but it does not define a separate keymap. Its main purpose is to show 'top-level' keys (also when switching evil-state) and serve as 'cheatsheet' for looking them up, or for getting suggestions about available commands. You can very quickly create a cheat sheet while reading about keybindings in any documentation. As I wrote it some months ago, I forgot the details of the implementation/features. However, you'll find development notes in the README (which b.t.w. is an .org file, and you should 'interactively' read it in Emacs), and subsequently, while 'extending' the functionality with features you like, you can/will have a more detailed look at what the code does exactly. I think maybe you should start with thinking about how you would like to be able to 'define' the key guides (the exact structure of their definitions), and then just try to add support for that structure (you will then find out what the current code does, I guess. This was also the last stage of what I have been working on).
invsblduck · 2022-11-03 23:30
This is interesting. Quick off-topic: `<off_topic>`I actually live and breathe on `C-c C-e` all day, five days per week, to get my Tech job done. That is: Sending bash code to the `*shell*` buffer (inferior shell process w/comint). I've become really proficient with comint, but I've crossed the threshold where I need `shell-mode` to do even more (such as handle multiple shell process buffers, say one per eyebrowse layout, and then `C-c C-e` would use the correct one that's "local" to the layout). I haven't been willing to bite the bullet and learn elisp well enough to think I am going to improve Shell mode substantially, but I've already hacked parts of it for my own use.`</off_topic>` Ok, I figured out what `C-h h` invokes on my system: [helm-descbinds](https://github.com/emacs-helm/helm-descbinds). See [screenshot](https://imgur.com/a/dt8cAKo). So maybe you don't need `which-key` in the handy deactivated config I linked above—you just need something like helm-descbinds until you develop your ideal cheat-sheet app.
00-11 · 2022-11-04 01:56
[Key See](https://www.emacswiki.org/emacs/KeySee) -- [`keysee.el`](https://www.emacswiki.org/emacs/download/keysee.el)
oantolin · 2022-11-05 16:50
The command /u/JDRiverRun explained shows all current bindings, but Embark also has a couple of other helpful commands to browse through keybindings with narrowing via Emacs's completion system: - `embark-prefix-help-command`: this is not a command you use directly, instead you do `(setq prefix-help-command 'embark-prefix-help-command)` and that way after you type a key prefix when you press `C-h` you get a list of the bindings under that prefix. This is what I use instead of which-key, since I find it much faster to find the command I want by narrowing (typing a few characters of the command name), than by reading a couple of pages of which-key display. - `embark-bindings-in-keymap`: this prompts you for a variable storing a keymap, and then shows you the bindings in that keymap.
andyjda · 2022-11-11 21:19
Only getting back to this now, but thanks a lot! This looks very close to what I was thinking of, and it adds a lot of cool features as well. This post has given me a lot of packages to explore, so I'll take a look at those first. If I decide to build a new solution, I'll let you know: this package looks like it'd be a great starting point