(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.