Hacker News new | past | comments | ask | show | jobs | submit login
Improving Emacs Isearch Usability with Transient (yummymelon.com)
156 points by kickingvegas 9 months ago | hide | past | favorite | 64 comments



Oh this is actually very cool. I didn't know about Transient or that I can create a custom workflow menu. Will be really nice for, just like the article, those commands I don't remember or that have vast numbers of options.

Thank you for sharing, I found the article very useful.


I've been using Transient in a similar way, but for operations on specific filetypes I use vigorously. For example, I have a ruby transient which provides a single UI for my favourite refactoring functions across the LSP server and various Emacs packages I use. I find using transient this way allows me to streamline the more complex tasks I perform by giving me an easy to conceive UI which hides the detail when I'm knee deep in bugs - but all the power of Emacs is still there under the hood when I need it. I suspect many people would get further with Emacs if they learned use-package and transient instead of picking up Doom Emacs or Space Emacs (which was how I started; they are great projects in their own right but can be limiting due to their own DSL which is a departure from vanilla Emacs).


emacs' discoverability has been quite terrible. A couple years back I wrote half of a package to do ascii art before I discovered artist-mode. And I had been using emacs for close to a decade by then. This year I discovered ace-window had hidden keybindings (C-x o then instead of choosing the window you want, type '?' to get the dispatch menu). Again, I've been using ace-window for about a decade. Adding a transient dispatch menu to Isearch would be great. I'd also suggest a more global keybinding for hidden dispatch menu (I suggest M-? for dispatch menus when using the minibuffer and ? for other modes).

Also this blog post makes me want to make me transform my embark to using transient


C-h a (apropos-command) makes finding things with unexpected names a lot easier. I relied on C-h f (describe-function) for years, but that only matches function names. Apropos searches doc strings as well.


Yeah I probably use 5% (or less) of emacs's functionality. It's still the best editor I've ever found.


it's the curse of large programs, regularly you'll read "I've been using emacs for N decades and I had no ideas this existed ..."

I somehow RTFM'd three times, allegedly diligently and yet I still missed a lot of spots. And emacs development pace increased, so I'm due to a 4th RTFM :)


An alternative process is to call describe-function, use embark-collect to put all the auto suggestions into a buffer and memorise all functions.

Edit: I just did that and when I called count words to count lines that are in the buffer, Emacs just froze

Edit: 39180 functions. Not that hard to memorise ;P


even emacs can't handle itself


It’s getting better though. The addition of shortdoc, the `marginalia` package (which makes some already present doc text available during minibuffer usage), and the `helpful` package (which again just places already available information in the help buffer) make things so much better. I’ve been using VS Code lately, because the tooling for something at work is so much better, but the lack of introspection and hackability is really frustrating.


But discoverability can be done right in emacs. I think one of the better examples is magit (from which transient comes from).


The which-key package helps a lot with discoverability, in my experience.


which-key helps a lot with prefix commands. But doesn't help when you don't know the variants of I search that have silly default key bindings like the aforementioned C-M-@


Transient is, if I recall, a big part of magit’s special sauce. It’s a great library for interactive chording.


> a big part of magit’s special sauce

I’d say it’s what makes magit.. magit. The whole command composition interface (almost like chords) is what drives people to it. The looks and some fringe M-x commands are… just there


There's more to magit, especially its way of grabbing information from context in the log/graph view for instance, or the implicit chunkning, it's pure papercut removal.


It also enables super easy workflows. To give an example, consider working on a fork of a project from GitHub. You clone the project from its source and make some changes and commit them. Where do you push the changes? You make a fork on GitHub. Go to magit, press a couple of keys to add a remote, name it the same as your GitHub username, magit automatically sets the URL correctly.

Now you realise you've put those commits on your new master branch but etiquette says you should put them on a separate branch. A couple of keys creates a "spinoff branch". Magit automatically creates a new branch at that point, sets the upstream of that branch to the old upstream (e.g. origin/master) and resets the old branch (master) to its upstream.

Now because your remote is set as "push default" you can easily push to it. Magit will now show you if upstream (the other remote) has diverged which means you press a couple of keys to rebase on to upstream then force push to your fork.

And this doesn't even mention things like doing an interactive rebase. Magit helps immensely there. The diff "dwim" is useful too. The list goes on.


> Where do you push the changes? You make a fork on GitHub. Go to magit, press a couple of keys to add a remote, name it the same as your GitHub username, magit automatically sets the URL correctly.

Or, just use the magit-forge package by the same author and run `forge-fork`.


haha yeah magit rebase makes you learn without trying. Everyday I have colleagues screaming in terror having to rebase, while emacs users are whistling.

i'm also curious about having magit extensions, as many people say, git lacks some stuff as UI, and they may fit very well around magit


The "spinoff" feature I mentioned is a magit extension. As are other things like stashing (git's own stashing only recently got updated to be able to do little bit more of what magit can do). Magit actually claims to be a git porcelain, not just a git GUI. I think the long term goal is still to do what it does via libgit and not even use the git CLI at all.


I should monitor the github issues / discussions


The ease with which magit lets me do an interactive rebase that splits a commit into multiple commits changed my workflow.


The contextual rebase, diff, etc is the biggest advantage for me.


which-key (https://github.com/justbur/emacs-which-key) adds a similar functionality to most (all?) commands.


which-key is more like autocomplete for keybinds. I consider it orthogonal to transient. It's meant for modals that show you what keybinds actually exist given some "prefix" you have just inputted. If I had to make an analogy, I'd say which-key is closer to company+counsel+ivy than transient.

I have used which-key with the three packages I just mentioned for as long as I have been using Emacs, and this is how I've always seen its role.


Modality or contextual keymaps is indeed a very powerful concept and it seems like the only way to have usable complicated keybinding schemes, so nice that this stacked/transient override was added


Hi folks! Great to see all the interest in my post. Feel free to ask me questions/post observations related to it.


> The default keybindings for said commands are cursed. (Seriously, C-M-@ to call isearch-query-replace-regexp ?)

BTW, this isn't only a problem with `isearch`. I suspect that other multiple-simultaneous-keypresses tend to be hard on most people's hands. Which can be bad for your typing-oriented career, and for other humans uses of hands.

Some alternatives in Emacs:

* Try to press the modifier key(s) with one hand, and the non-modifier key with the other.

* If the modifier(s) require contorting in uncomfortable ways, consider whether moving from home row is easier.

* When an Emacs key sequence includes the "Meta" modifier (`M-`), consider whether pressing and releasing the Esc key first, and then doing the remaining key/combo, is easier.

* Make a better key binding. Examples:

    (global-set-key [f5] 'call-last-kbd-macro)
    (global-set-key [f12] 'undo)
    (global-set-key [XF86Back] '(lambda ()
                                  (interactive)
                                  (other-window -1)))
* Learn fancier Emacs features which might mean not having to type this or not as often (keyboard macros is just one).

* Use or write a function or package that automates the higher-level task. For writing your own, you can learn from one of these two manuals, and just start experimenting in your running Emacs: https://www.gnu.org/software/emacs/manual/html_node/eintr/ https://www.gnu.org/software/emacs/manual/html_node/elisp/


Another option to trigger functions are vim-inspired leader key sequences such as god mode [1] and the evil leader implementations in spacemacs and doomemacs, for example [2].

[1] https://github.com/emacsorphanage/god-mode [2] https://discourse.doomemacs.org/t/what-are-leader-and-locall...


I agree with what you said, but would suggest also using the god-mode package. With that, when you hit Esc, you enter "command mode" (hit Esc again to exit it) so most keys you press will be treated as "Ctrl-<key>". So instead of holding Ctrl pressed all the time, you just hit some keys (npbfae) to move around... and search is just "s". Most vim users would just use evil-mode but for the rest of us this is a good compromise and once you get used to it, it avoids the pinkies very well.

https://github.com/emacsorphanage/god-mode


Another workaround is using sticky keys a11y features, which changes modifiers to work in sequence rather than need to be pressed simultaneously.


Personally, I'm not a fan of key-bindings of the form <modifier sequence>-<some symbol that requires a shift key>. That said, what I find intriguing about including the Transient package in Emacs is the potential for supporting menu-driven Transient interfaces to existing commands in a way that doesn't break their default behavior. Such future Transient menus could be shipped as a default and obviate the need to learn complex key bindings.


I think which-key already solves exactly that: https://github.com/justbur/emacs-which-key


> Try to press the modifier key(s) with one hand, and the non-modifier key with the other.

This is the biggest problem I see with most people’s typing: they always want to press the whole key sequence with one hand, then they complain that it hurts! :)

Maybe not enough people took a typing class in school.


This is also why keyboard layouts which don’t have Alt keys on both sides are such a menace.


Very true.


> Some alternatives in Emacs:

I swear I had to read that twice to stop seeing "alternatives to Emacs". I'll see myself out now.

(Doom Emacs is really nice though, and modal editing does help with key bindings, just as a sibling comment points out.)


Related: to create submenu with sticky keys, there is Hydra: https://github.com/abo-abo/hydra


> The default keybindings for said commands are cursed. (Seriously, C-M-@ to call isearch-query-replace-regexp ?)

If only software allowed to be shipped with a different set of defaults or more convenient alternatives...


> The default keybindings for said commands are cursed.

Default keybindings are a curse.

Software in general would be so much better if keybindings were always explicitly part of the user's configuration. Despite that being technically the case in Emacs, the reality just isn't as practical as it should be.

Every default keybinding brings an assumption into UI/UX. That assumption can never be removed: it can only be moved.


The problem is designing coherent usable keybindings is a large undertaking.

Plus things like C-c C-f and similar working throughout many different elisp packages in a predictable useful way is super valuable.


its a huge problem. Firefox for example could not agree on what the binding for PiP should be on non US/UK keyboards, and had an impossible binding of Ctrl-Shift-] (where "]" requires an Alt on some keyboards).

https://bugzilla.mozilla.org/show_bug.cgi?id=1611154


Yeah, I'm confused on what the complaint is? Is the desire that it is always explicitly coded in a config file? You could probably dump the keymap to a file on initial load?

You could extend that so that if default is different from the last time it was loaded, you could let the user know, and then replace with any user defined one. (Letting user know is mainly so they can decide if new commands need mapping.)

That said, I'd hazard this is not that useful?


Yea, that doesn’t make much sense to me either. Maybe they should go to whatever Emacs buffer they have open and type `C-h B` to dump out the entire list of keybindings available in that buffer. That will probably disabuse them of the notion that the user has to personally invent all of them. Mine is 2.4k lines long! And that’s just for the modes that I happen to be using for that particular JSON file; many of the key bindings in a C++ or Rust file would be similar, but so many would be completely different.


> Mine is 2.4k lines long!

Are you telling me you actually use 2,400 key bindings?

If you do, then would it really be that hard to invent them yourself?

If you don't, then what good are all of these keymaps actually doing you?

I'm not advocating that you should have to reinvent your keymap. I'm advocating that you should be able to.

Emacs is the very best case available: it's technically possible! Nearly everything else demands we learn its own opinion, instead of implementing our own.


I don’t know them all, no. But it would be absolutely ridiculous to force a new user to try to design a set of key bindings for even the hundreds that I do use. Nobody can predict ahead of time which ones the user will learn over the years that they use an editor, or even which combinations of features they will enable.


So don't force them to.

And don't force them not to, either.


Like I said, yes, in emacs it is technically possible.

But you still have to redo the keymaps defined in every package you use; and you have to know what they are in the first place.

You can replace single bindings one at a time easily enough. You can't change them all without a two-step effort. We could eliminate step one for anyone, like me, who's is interested.

There's a reason that evil-mode took so much effort to put together, and it still has serious edge cases. I want to make my own original modal editing keymap. I have tried many times, and given up. It's too much work to both see what to change in the first place, and to remove the default; and that's what it takes to just get started!

Picture this: you are learning to use Emacs for the very first time. What are you learning? Today, the answer is C-n, C-x C-s, etc. My alternative is to learn the functions instead. If you don't have an opinion about what key should be bound, then use someone else's config. This way you can actually comprehend your entire configuration! It doesn't need to be mandatory, but I would love the opportunity.


What I'm saying is you can automate a fair bit of this. When a new keymap is loaded, dump it and let the user know of it.

Things are super complicated with this general idea, though, as don't forget that the standard letters are also basic keybindings. People can and do take advantage of that fact. Right? I'm assuming you would not want those to be special cased here?


You can in Emacs, though you must first learn how. Last time I tried, I gave up.

Emacs is, by far, the best case. Even if I did get Emacs to behave exactly how I wanted, I can't apply that to any of the other software I use.


Ah, my apologies. I took your initial post to mean that even emacs doesn't get what you wanted. You mean largely that it is not the advertised path, even in emacs where it is technically possible. Makes sense.

The level of introspection you can do in emacs is something I wish all programs had. Being able to ask the program, "what were the last commands you saw?" and "what would you do if I did {something}" are huge.


For plugins maybe, but coming up with a thoughtful set of key bindings takes work. If everything is reconfigurable, like with Emacs, I don’t see the harm in giving users something to start with.


Just coming up with evil bindings for modes before evil-collection was hard enough :)


Evil-mode is an example of what I am advocating here.

Imagine if evil-mode could start with a blank slate. Wouldn't that be easier?

The problem is that every package is designed to integrate with regular default-Emacs. If you are using evil-mode, that means every package presents its own edge case.


Emacs originally was a set of macros to standardize key bindings across multiple editors that existed at the time.


Not exactly. It was a set of macros, yes, but the goal was an improved editor, not a standardized interface. Later there were multiple ports which shared many things in common, such as key bindings, on–line help, etc.


No, it was a standardized interface. Guy Steele talked about going around the office collecting keybindings from multiple people and distilling them down into a standard set.


But not from users of multiple editors. They were all users of TECO who had written their own macros to add similar features.


I'm not sure where you're going with this. A bunch of people wrote macros for TECO. Moon and Steele collected them and standardized them. The set of standardized macros is Emacs.

Thus, Emacs originally was a set of macros to standardize key bindings across multiple editors that existed at the time, exactly as GP said.


libreadline


> Software in general would be so much better if keybindings were always explicitly part of the user's configuration.

So you'd open up Emacs, and the only thing you'd be able to do is insert and delete text? No "beginning-of-line", no "find-file"? That seems...even less newbie-friendly than Emacs currently is.


No, inserting text is a command (it's the self-insert-command). Presumably how it would have to be done is when some software (like Emacs) launches it'd prompt the user for every required keybinding.


That concept breaks down with the multiple thousands of default key bindings in a typical Emacs setup (source: go into an org buffer press C-h b, then go to a Python buffer and press it again, and so on)


I'm not advocating we ban the default keymap. I'm advocating that we move it.

You may like it fine, but I find it in my way more often than not.

What does it truly mean to be newbie-friendly? Are you trying to teach them the functionality of your software, or your opinions about how to use it? Why not teach newbies (find-file) first? Would that really be so bad? Why not give them both options?


The fact that ctrl+c copies on my computer and I can expect the same at my mom's computer or my friend's computer seems like a blessing not a curse.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: