(or emacs irrelevant)

Easily arrange hydra into a matrix

The new :columns option

Today I'll introduce a pretty cool new option that you can use to quickly create hydra docstrings arranged in a matrix. This, of course, was already possible before, but you had to format the matrix by-hand like this (I cite just bit instead of the full code, it was cut to fit into the Jekyll code column restriction):

(defhydra hydra-projectile (:color teal
                            :hint nil)
  "
     PROJECTILE:

     Find File            Search/Tags
-----------------------------------------
_s-f_: file            _a_: ag
 _ff_: file dwim       _g_: update gtags
 _fd_: file curr dir   _o_: multi-occur
 "
  ("s-f" projectile-find-file)
  ("a" projectile-ag)
  ("ff" projectile-find-file-dwim)
  ("fd" projectile-find-file-in-directory)
  ("g" ggtags-update-tags)
  ("o" projectile-multi-occur)
  ("q" nil "cancel"))

The syntax above is still very useful if you want to arrange every detail perfectly or need Ruby-style quoting. But here's the new syntax that allows to get almost the same docstring much easier:

(defhydra hydra-projectile (:color blue
                            :columns 4)
  "Projectile"
  ("a" projectile-ag "ag")
  ("b" projectile-switch-to-buffer "switch to buffer")
  ("c" projectile-invalidate-cache "cache clear")
  ("d" projectile-find-dir "dir")
  ("s-f" projectile-find-file "file")
  ("ff" projectile-find-file-dwim "file dwim")
  ("fd" projectile-find-file-in-directory "file curr dir")
  ("g" ggtags-update-tags "update gtags")
  ("i" projectile-ibuffer "Ibuffer")
  ("K" projectile-kill-buffers "Kill all buffers")
  ("o" projectile-multi-occur "multi-occur")
  ("p" projectile-switch-project "switch")
  ("r" projectile-recentf "recent file")
  ("x" projectile-remove-known-project "remove known")
  ("X" projectile-cleanup-known-projects "cleanup non-existing")
  ("z" projectile-cache-current-file "cache current")
  ("q" nil "cancel"))

It still looks pretty good, in my opinion:

hydra-columns-projectile.png

Note how all redundant information has been removed. Another advantage is the you can easily:

  • Add/remove heads.
  • Update head hints.
  • Change the number of columns.

A bit of customization

After each change, just re-eval the defhydra and you're done - no need to manually re-arrange the docstring. Since there already is an interface that allows you to customize the docstring very precisely, I tried to make the new interface as automatic as possible: just specify the number of columns and you're done. But if you want just a little bit more customization, look at this code:

(defvar hydra-key-doc-function 'hydra-key-doc-function-default
  "The function for formatting key-doc pairs.")

(defun hydra-key-doc-function-default (key key-width doc doc-width)
  (format (format "%%%ds: %%%ds" key-width (- -1 doc-width))
          key doc))

So if you want to add a little space here and there, or e.g. wrap key bindings in brackets, just clone hydra-key-doc-function-default, customize it a bit and set hydra-key-doc-function to the new function.

Outro

If you've been using just the plain style before and felt that you can't fit your docstring on one line, try the new style: it's just one line of change with respect to your old code. And if you've been building the docstring by-hand, see if it's possible to transform it to the new style: adding and removing new heads will become easier. Thanks to @Fuco1 for the suggestion in #140.

Quitting to command loop in Elisp

Today I'd like to share an interesting bit of Elisp that comes up every now and then for me. Imagine that you have this:

(defun useful-command ()
  (interactive)
  (do-thing-1)
  (do-thing-2 (funcall callback-function))
  (do-thing-3))

Sometimes, when you are in callback-function, you might want to abandon the function that called you, useful-command in this case, and call a different function, with the current context.

Here's what I've come up with to do just that:

(defmacro ivy-quit-and-run (&rest body)
  "Quit the minibuffer and run BODY afterwards."
  `(progn
     (put 'quit 'error-message "")
     (run-at-time nil nil
                  (lambda ()
                    (put 'quit 'error-message "Quit")
                    ,@body))
     (minibuffer-keyboard-quit)))

To break it up into parts:

  • minibuffer-keyboard-quit will unwind the call stack all the way to the command loop, preventing e.g. do-thing-3 from being called. Note that the call stack can be as deep as you like, e.g. useful-command might be called by utility-command etc.

  • run-at-time with the argument nil will run the code as soon as possible, which is almost exactly after we're back into the command loop.

  • The final trick is to prevent Quit from being displayed in the minibuffer.

Sample application

Suppose that I've called find-file when ivy-mode is active. Typically, I'd select a file and press C-m to open it. However, sometimes I just want to see the selected file in dired instead of opening it. This code is from before ivy multi-action interface, it plainly binds a command in ivy-minibuffer-map:

(define-key ivy-minibuffer-map (kbd "C-:") 'ivy-dired)

(defun ivy-dired ()
  (interactive)
  (if ivy--directory
      (ivy-quit-and-run
       (dired ivy--directory)
       (when (re-search-forward
              (regexp-quote
               (substring ivy--current 0 -1)) nil t)
         (goto-char (match-beginning 0))))
    (user-error
     "Not completing files currently")))

So at the moment when C-: is pressed, the call stack is:

  • C-x C-f called find-file.
  • find-file called completion-read-function which is set to ivy-completing-read.
  • ivy-completing-read called ivy-read.
  • ivy-read called read-from-minibuffer.

Thanks to the new macro, I can unwind all of that stuff, making sure nothing extra will be executed that was supposed to be executed after read-from-minibuffer had returned. In other words, the file will not be opened. Instead, a dired buffer will be opened, centered on the selected candidate.

What I described above can actually be a pretty common scenario, you could adapt it to helm or avy or projectile. Basically to anything that includes some form of completion (i.e. commands that wait for input) and offers you a customizable keymap. Small disclaimer: the above code falls into the quick-and-dirty category, I don't recommend it if you can do something smarter instead. But if you can't do anything smarter due to being constrained by an interface you don't control, this macro could help you out.

Command Rhythmbox from Emacs

I might have mentioned before that I'm using GNU/Linux on all of my computers. The particular flavor is Ubuntu, although it shouldn't matter much, since I can count the graphical applications that I use at all, besides Emacs, on one hand. They are: Firefox, Evince, Rhythmbox and VLC. Of course, as most true Emacs-ers, I strive to reduce this number to zero. So I got quite excited when I saw helm-rhythmbox show up in my package list. It works great: you can play and enqueue tracks with completion without leaving Emacs. Big thanks to @mrBliss, and, of course, the authors for dbus.el which makes interaction with D-Bus possible through Elisp.

I'm not as big a fan of Helm as I used to be, so I quickly implemented an Ivy equivalent:

(defun counsel-rhythmbox-enqueue-song (song)
  "Let Rhythmbox enqueue SONG."
  (let ((service "org.gnome.Rhythmbox3")
        (path "/org/gnome/Rhythmbox3/PlayQueue")
        (interface "org.gnome.Rhythmbox3.PlayQueue"))
    (dbus-call-method :session service path interface
                      "AddToQueue" (rhythmbox-song-uri song))))

;;;###autoload
(defun counsel-rhythmbox ()
  "Choose a song from the Rhythmbox library to play or enqueue."
  (interactive)
  (unless (require 'helm-rhythmbox nil t)
    (error "Please install `helm-rhythmbox'"))
  (unless rhythmbox-library
    (rhythmbox-load-library)
    (while (null rhythmbox-library)
      (sit-for 0.1)))
  (ivy-read "Rhythmbox: "
            (helm-rhythmbox-candidates)
            :action
            '(1
              ("Play song" helm-rhythmbox-play-song)
              ("Enqueue song" counsel-rhythmbox-enqueue-song))))

I listed the whole code just to show how easy it is to interact with D-Bus, and also to show-off the shiny new multi-action interface of ivy-read. Besides being discoverable via C-o, the multi-action interface is extensible as well. Here's how to add a "Dequeue" action without touching the original code:

(defun counsel-rhythmbox-dequeue-song (song)
  "Let Rhythmbox dequeue SONG."
  (let ((service "org.gnome.Rhythmbox3")
        (path "/org/gnome/Rhythmbox3/PlayQueue")
        (interface "org.gnome.Rhythmbox3.PlayQueue"))
    (dbus-call-method :session service path interface
                      "RemoveFromQueue" (rhythmbox-song-uri song))))
(ivy-set-actions
 'counsel-rhythmbox
 '(("Dequeue song" counsel-rhythmbox-dequeue-song)))

Very simple, counsel-rhythmbox-dequeue-song is a clone of counsel-rhythmbox-enqueue-song with only the method change from AddToQueue to RemoveFromQueue (I blind-guessed the name, but there should be a reference somewhere). If you got tired of having a whole three actions to choose from, you can revert to the initial two with:

(ivy-set-actions 'counsel-rhythmbox nil)

And here's how the updated C-o option panel now looks like:

counsel-rhythmbox.png

A bit of descriptions:

  • j moves to the next one of the 18 current candidates.
  • k moves to the previous candidate.
  • h moves to the first candidate.
  • l moves to the last candidate.
  • g calls the current action without exiting.
  • d calls the current action and exits.
  • s moves to the next action.
  • w moves to the previous action.
  • i and C-o close the options panel without exiting.
  • o closes the panel and exits.

Similarly to hydra, each action has a short docstring, like "Play song" that should describe what it does. Here are a few usage scenarios:

  • If I wanted to play the first song and enqueue the third and the sixth and exit the minibuffer, I would press gsjjgjjjd.
  • If I wanted to play the third and enqueue all the following, I would press jjgsjcjjjjjjjjjjjo. The many j is just me holding j until the selection reaches the end, then I simply exit without doing anything else by pressing o. The way c works is that it toggles the "calling" state - a state where the current action is called whenever a different candidate is selected.

Almost forgot, if this little intro got you excited, the packages that you should install from MELPA are: helm-rhythmbox and counsel.

Pause or resume the current Hydra

Today I'd like to highlight a generic command recently added to hydra. It's kind of cute, and maybe something that you didn't even know you wanted. Basically, the hydra-pause-resume command allows to pause and resume the current hydra with one key. And it works for all hydras at once, without any extra configuration. All you have to do is to bind it globally to whatever you like, for example:

(global-set-key (kbd "C-M-k") 'hydra-pause-resume)

What it does:

  • If a hydra is active, deactivate and push it on the stack.
  • If no hydra is active, pop one from the stack and call it.
  • If the stack is empty, call the last hydra.

Personally, I haven't found too much use from the stack - resuming the last one is enough for me. But the stack comes at no extra cost, and might be useful to someone.

If, for example, you have 2 hydras on the stack, how to resume the older one?

The way stacks work, you simply have to go through all elements one by one. So that's:

  1. C-M-k to resume the newer one.
  2. Quit the current one with the appropriate shortcut, only not with C-M-k, since that would just put it back on the stack.
  3. C-M-k to resume the only one remaining on the stack - the older one.

Thanks to @QiangF for the suggestion in #135.

Power up your locate command

locate

I'm sure many people know that Emacs comes with a locate command. This command, if you're on a Linux system, will find all files on your system that match a particular pattern. The advantage of locate over find when searching the whole system, is that it is much faster, since it uses a pre-computed database. This database is updated periodically, you can force an update with:

sudo updatedb

Of course find is faster if you need to search only a specific directory instead of the whole system, but sometimes you just don't know that directory.

counsel-locate

Dynamic

The way locate works it that it asks you for a query, which is glob-based instead of regex-based, and then prints the results to a static buffer.

On the other hand, counsel-locate is dynamic: each time you input a new character a new locate query is ran, and the old one is terminated. On my system, it takes around 2 seconds for a query to complete, so it requires a bit of patience.

Regex-based

I like regex way more than globs for some reason. Here's the command called for the input mp3$:

locate -i --regex mp3$

Of course, the standard ivy-mode method is used to build the regex from a list of space separated words. So the input fleet mp3$ will result in:

locate -i --regex \\(fleet\\).*?\\(mp3$\\)

You could go your own way and update the regex matcher to be ivy--regex-fuzzy, which results in:

locate -i --regex f.*l.*e.*e.*t.* .*m.*p.*3$

But I think less matches is usually better than more matches.

Multi-exit

This is just the coolest feature. Basically, for each file you locate, you can easily:

  • Open it in Emacs (default).
  • Open it with xdg-open, so that PDF files are forwarded to evince and MP3 files are forwarded to rhythmbox etc.
  • Open it in dired.

Here's an example of how to do it. First I call counsel-locate, which I like to bind to C-x l. Then I enter emacs pdf$ and wait around 2 seconds for the 248 results to come up. Then I scroll to the 18th result and press C-o to open up the hydra-based option panel:

counsel-locate-1.png

The last column (Action) is newer than others. As you can see, it has 3 exit points, which I can scroll with w and s. And currently I'm on the default exit point, which would open the file in Emacs.

For the next screenshot:

  • I pressed s twice to change the action to dired.
  • I pressed c to make the current action execute each time a new candidate is selected.

counsel-locate-2.png

So now, I could just scroll through all my directories on my system that contain PDF files related to Emacs by just holding j.

A similar thing can be done for music tracks:

  • C-x l dire mp3$ to get the list of all Dire Straits tracks on my system.
  • C-o s to switch the action from "open in Emacs" to "xdg-open".
  • From here, I could open one track after another by pressing C-M-n repeatedly. Or I can press c and then j repeatedly.

I've been experimenting with opening EPS and PDF files in quick succession. It's still a work in progress, since I need to use a special wmctrl script to prevent the Emacs window from losing focus each time a new Evince instance is opened.

Outro

You can check out the new feature by installing counsel from MELPA. It will automatically fetch ivy-mode as well. When you enable ivy-mode, besides doing all your completion, it will also remap switch-to-buffer to ivy-switch-buffer. That command also has a multi-exit: pressing C-o sd instead of C-m will kill the selected buffer instead of switching to it. It's a very minor optimization: instead of C-m C-x k you press C-o sd, however you could e.g. use C-o scjjjj to kill five buffers at once.

While the idea of multi-exits is powerful, it's hard to find places to use it efficiently. I think counsel-locate is a nice place for it, although it could work without it:

  • Find file in Emacs with C-m in the completion interface.
  • Call dired-jump with C-x C-j.
  • Type ! and xdg-open RET.
  • Select and kill the unneeded file with C-x k.

I hope you see now why I prefer C-o sd.