Why I Use Helm and Why You Should Too
Emacs is a whirlwind of shortcuts and commands for a beginner. Because Emacs isn't a true modal editor like VIM you must learn a plethora of keyboard shortcuts to edit text efficiently. Richard Stallman, the creator of GNU Emacs, was well aware of this so he created the "GNU Emacs Human Interface Machine", which was a specially designed keyboard for Emacs power users.
The picture below is an example of one of these machines.
All joking aside, Emacs's default interface isn't very user friendly when you don't know the shortcut or command name you want to execute. When you run a command that requires user input, you're given an empty prompt. That's it. If you read the tutorial then you may remember that you can press TAB to see some options. That's a little better I suppose, but it would be better if you could see your possibilities without asking for it. Enter helm.
Helm is an extension package for Emacs that, among other things, hooks into many of the commands requiring user input and supplants them with a new command that presents the user with a prompt AND an interactive list of options that is fuzzy matched to what is typed in that prompt. It's sort of similar to the goto anything commands that are available in Sublime Text, except it's available on more than just a handful of commands.
Say I want to find a window command that splits the window into two vertical halves and all I know is that the command has 'window' and 'split' in its name and I'm not sure which term is first. Helm makes it extremely easy to browse the available symbols(names) in the current Emacs environment using the 'helm-apropos' command.
In the demo above, I run 'helm-apropos' and try searching for a command that has 'window' followed by 'split' in its name. I find nothing appropriate so I try the reverse and search for a command with 'split' followed by 'window' in its name. I eventually find the correct answer which is 'split-window-right'.
There's an important feature to note about this kind of UI that isn't immediately obvious. Because you're presented with all the possibilities, you end up learning the capabilities of the program by simply using the program. Because of this side effect, Emacs became a much more understandable system after I installed helm. It's such a boon to the Emacs experience that I would consider changing editors if helm wasn't available.
Below I outline some useful helm commands followed by my favorite helm extension packages.
Use helm-M-x as an alternative to typing M-x.
live lisp environment.
The helm-dash package lets you search programming language documentation through "docsets" you've installed on your machine. Install docsets for a language using the 'helm-dash-install-docset' command and search them using the 'helm-dash' command. Press RETURN on a result to open the documentation in your default browser.
Evalator is a new kind of REPL that I wrote for Emacs that lets you interactively transform data. It evaluates expressions in Emacs Lisp by default but it can support any language provided you've installed the evaluation context package.
I use evalator mainly as a calculator and a quick experimentation tool when I'm writing Emacs Lisp and Clojure code. It feels much quicker than using a normal REPL because expressions are evaluated automatically.
Evalator starts with a prompt where you supply an expression to generate the initial data. Following expressions transform that data on a per-element basis so its very easy to transform lists and other collections. You can also use evalator in explicit mode, which allows you to transform data as usual, but it lets you generate the equivalent code of the entire transformation.helm-descbinds githubtuhdo covered this better than I ever could.
I hope by now that I've convinced you to check out helm. It really is an innovative way of interacting with Emacs.
After sharing this article on the Emacs subreddit, I received an excellent comment from an Emacs package author I admire very much, Oleh Krehel, AKA abo-abo. He makes some very innovative tools for Emacs including a completion framework called ivy, which many Emacs users prefer to helm.
In his reply, Oleh argues that if the built-in Emacs function
completing-read were updated, then packages that extend helm could be used in all the different completion frameworks. This includes ivy, icicles, ido, and others. Here's the conversation and I've included his comment below(formatting has been added):
Nice article, very good-looking presentation.
However, you repeat the opinion that the completion (which is a great thing to have) is welded to the method of presenting said completion (in this case, Helm). Many other people do this as well, with 112 packages in MELPA having "helm-" in their name. Hard-wiring completion to helm prevents access to ~100 packages for users that like other methods of presenting completion.
In the short run, it's convenient to live in Helm's bubble: assume that Helm is all you'll ever need and hard-wire everything to Helm. But most helm-foo packages out there simply consist of three things:
- Functions that generate the list of strings.
- Functions that take a single string - the selected candidate, and do something with it.
- The helm glue that wires the first group to the second.
The non-helm people could make use of the functions in group-1 and group-2. The two problems they face: There's no glue. This could be solved by completing packages relying on the built-in
completing-readmore. There's a helm dependency. This isn't severe, but if you don't use helm you don't want to pay the overhead of
(require 'helm)and having to update helm from the package manager.
These two problems can be solved eventually by having a better completing-read API in the core. So that a package that only wants to provide completion can call completing-read and not be tied to any completion presentation framework. Two new parameters would be especially good to have: action - a lambda that decides what to do with the selected candidate, and caller - a symbol that identifies the completion session for purposes of customization (since this-command isn't reliable).
Here we have helm-rhythmbox, an excellent package that provides a function from group-1 -
helm-rhythmbox-candidatesthat produces a list of songs on your system; and two functions from group-2 -
helm-rhythmbox-enqueue-songthat act on the selected song.
(defvar helm-source-rhythmbox-track-search '((name . "Rhythmbox") (candidates . helm-rhythmbox-candidates) (action . (("Play song" . helm-rhythmbox-play-song) ("Enqueue song" . helm-rhythmbox-enqueue-song))) (init . (lambda () (unless rhythmbox-library (rhythmbox-load-library)))))) ;;;###autoload (defun helm-rhythmbox () "Choose a song from the Rhythmbox library to play or enqueue." (interactive) (helm :sources '(helm-source-rhythmbox-track-search) :buffer "*helm-rhythmbox*"))
;;;###autoload (defun rhythmbox () "Choose a song from the Rhythmbox library to play or enqueue." (interactive) (unless rhythmbox-library (rhythmbox-load-library)) (completing-read "Rhythmbox: " (helm-rhythmbox-candidates) nil nil nil nil nil nil 'helm-rhythmbox-play-song 'rhythmbox)) ;; ideally, the following sections are not needed at all (eval-after-load 'helm ;; non-essential helm-specific customization via the 'rhythmbox key ) (eval-after-load 'ivy ;; non-essential ivy-specific customization via the 'rhythmbox key )
Now we have a rhythmbox command that could act in exactly the same way as helm-rhythmbox when helm-mode (available with Helm) is on. But this command would also work excellently with Ivy or Ido or Icicles or Icomplete or built-in completion. This command could live in a rhythmbox package that does not depend on helm, since it doesn't use anything Helm-specific.
I'm glad Oleh joined in on the discussion and I think he makes a great case for why the
completing-read function should be updated. Thanks Oleh!