(or emacs irrelevant)

Hydra 0.11.0 is out

As usual, I'll just re-state the release notes and add some more notes in the end.

Fixes

  • Emacs 24.3 (and maybe earlier versions) compatibility added
  • (hydra-cleanup): Should not delete buffer first when window is dedicated.
  • (lv-message): Should not deactivate mark.
  • quit signals are intercepted, so that proper clean-up is done.
  • no defuns with the same name will be generated in case some heads' cmd parts coincide

New Features

Pink body color

When body color is pink, and hydra intercepts a binding which isn't a head, instead of quitting the hydra and executing the binding (default red behavior), it will execute the binding and not quit the hydra. This type of hydra is very similar to define-minor-mode.

So now, pink and amaranth are body colors that are a flavor of the default red that, instead of quitting when a non-head binding is intercepted, respectively run the binding or issue a warning.

Teal body color

Teal color behaves similarly to amaranth (issues a warning when intercepting foreign bindings), but the default behavior for each head is to quit.

The following evaluates to true:

(equal
 (macroexpand
  '(defhydra hydra-test (:color amaranth)
    ("a" fun-a)
    ("b" fun-b :color blue)
    ("c" fun-c :color blue)
    ("d" fun-d :color blue)
    ("e" fun-e :color blue)
    ("f" fun-f :color blue)))
 (macroexpand
  '(defhydra hydra-test (:color teal)
    ("a" fun-a :color red)
    ("b" fun-b)
    ("c" fun-c)
    ("d" fun-d)
    ("e" fun-e)
    ("f" fun-f))))

So if you want to write less, use teal color in this case.

Alternative color-less syntax

The color syntax is working quite well, since I was able to keep an almost full backward-compatibility: once you pinpoint a color it will have that behavior, all the new behaviors will be released under a new color.

Some might prefer an alternative set of switches rather than colors. New compat switches are:

- ":exit nil" for ":color red"; You don't have to specify either
  option in the body, since they are the default behavior that was
  available on Hydra release
- ":exit t" for ":color blue"
- ":foreign-keys warn" for ":color amaranth"
- ":foreign-keys warn :exit t" for ":color teal"
- ":foreign-keys run" for ":color pink"

The property :exit can be inherited and overridden in the same way as :color red or blue.

The following evaluates to true:

(equal
 (macroexpand
  '(defhydra hydra-test ()
    ("a" fun-a)
    ("b" fun-b :color blue)
    ("c" fun-c :color blue)
    ("d" fun-d :color blue)
    ("e" fun-e :color blue)
    ("f" fun-f :color blue)))
 (macroexpand
  '(defhydra hydra-test (:color blue)
    ("a" fun-a :color red)
    ("b" fun-b)
    ("c" fun-c)
    ("d" fun-d)
    ("e" fun-e)
    ("f" fun-f))))

The following two are exactly the same as the two above:

(equal
 (macroexpand
  '(defhydra hydra-test ()
    ("a" fun-a)
    ("b" fun-b :exit t)
    ("c" fun-c :exit t)
    ("d" fun-d :exit t)
    ("e" fun-e :exit t)
    ("f" fun-f :exit t)))
 (macroexpand
  '(defhydra hydra-test (:exit t)
    ("a" fun-a :exit nil)
    ("b" fun-b)
    ("c" fun-c)
    ("d" fun-d)
    ("e" fun-e)
    ("f" fun-f))))

Ruby-style string interpolation in docstrings

Here's an example:

(defhydra hydra-marked-items (dired-mode-map "")
  "
Number of marked items: %(length (dired-get-marked-files))
Auto-revert mode is:    %`auto-revert-mode
"
      ("m" dired-mark "mark"))

To enable this behavior, the docstring has to start with a newline (which will be stripped). This makes sense, since you usually want to align extensive docstrings, like I did this one. The escape syntax for variables is such that you can auto-complete them with company-mode. Both variables and sexps can use format style width specifiers. See the documentation of format for more details.

Examples 7-9 added to hydra-examples.el

These examples explain Ruby-style interpolation.

Updated faces

I've updated each face to match their color by default. Remember, that you can customize each face interactively with M-x customize-group hydra.

Alternative grey-scale or custom faces

If you don't want colors for some reason, you can customize hydra-fontify-head-function to your taste.

As an example:

(setq hydra-fontify-head-function
      #'hydra-fontify-head-greyscale)

This function is already defined in hydra.el, but you could define a similar one on your own:

(defun hydra-fontify-head-greyscale (head body)
  "Produce a pretty string from HEAD and BODY.
HEAD's binding is returned as a string wrapped with [] or {}."
  (let ((color (hydra--head-color head body)))
    (format
     (if (eq color 'blue)
         "[%s]"
       "(%s)") (car head))))

New switch :body-pre

This sexp or function will be prepended to the prefix/body function. Here's an example of use:

(defvar hydra-vi/init-pos nil)
(defhydra hydra-vi (:body-pre (setq hydra-vi/init-pos (point))
                    :color pink)
  "vi"
  ;; arrows
  ("h" backward-char)
  ("j" next-line)
  ("k" previous-line)
  ("l" forward-char)
  ;; exit points
  ("q" (goto-char hydra-vi/init-pos) "ins" :exit t)
  ("C-n" (forward-line 1) nil :exit t)
  ("C-p" (forward-line -1) nil :exit t))

Here, upon entering the hydra, the point position will be saved. And upon quitting, it will be restored.

Outro

I hope that you're enjoying the new updates as much as I do. Since the last release, there are two new blog posts about using hydra that I'm aware of: by Howard Abrams and John Kitchin.

Additionally, @hura, @kaushalmodi, and @glucas have made some additions to the Hydra wiki. Anyone is welcome to share their useful hydras there. Thanks a lot and happy hacking!