Skip to content
/ hydra-1 Public
forked from abo-abo/hydra

make Emacs bindings that stick around

Notifications You must be signed in to change notification settings

srid/hydra-1

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status

This is a package for GNU Emacs that can be used to tie related commands into a family of short bindings with a common prefix - a Hydra.

hydra

Once you summon the Hydra through the prefixed binding (the body + any one head), all heads can be called in succession with only a short extension.

The Hydra is vanquished once Hercules, any binding that isn't the Hydra's head, arrives. Note that Hercules, besides vanquishing the Hydra, will still serve his orignal purpose, calling his proper command. This makes the Hydra very seamless, it's like a minor mode that disables itself auto-magically.

Simplified usage

Here's how to quickly bind the examples bundled with Hydra:

(require 'hydra-examples)
(hydra-create "C-M-y" hydra-example-move-window-splitter)
(hydra-create "M-g" hydra-example-goto-error)
(hydra-create "<f2>" hydra-example-text-scale)

Using Hydra for global bindings

But it's much better to just take the examples as a template and write down everything explicitly:

(defhydra hydra-zoom (global-map "<f2>")
  "zoom"
  ("g" text-scale-increase "in")
  ("l" text-scale-decrease "out"))

With the example above, you can e.g.:

(key-chord-define-global "tt" 'hydra-zoom/body)

In fact, since defhydra returns the body symbol, you can even write it like this:

(key-chord-define-global
 "tt"
 (defhydra hydra-zoom (global-map "<f2>")
  "zoom"
  ("g" text-scale-increase "in")
  ("l" text-scale-decrease "out")))

If you like key chords so much that you don't want to touch the global map at all, you can e.g.:

(key-chord-define-global
 "hh"
 (defhydra hydra-error ()
   "goto-error"
   ("h" first-error "first")
   ("j" next-error "next")
   ("k" previous-error "prev")))

You can also substitute global-map with any other keymap, like c++-mode-map or yas-minor-mode-map.

See the introductory blog post for more information.

Using Hydra for major-mode or minor-mode bindings

Here's an example:

(defhydra lispy-vi (lispy-mode-map "C-z")
  "vi"
  ("l" forward-char)
  ("h" backward-char)
  ("j" next-line)
  ("k" previous-line))

Can Hydras can be helpful?

They can, if

(setq hydra-is-helpful t)

This is the default setting. In this case, you'll get a hint in the echo area consisting of current Hydra's base comment and heads. You can even add comments to the heads like this:

(defhydra hydra-zoom (global-map "<f2>")
  "zoom"
  ("g" text-scale-increase "in")
  ("l" text-scale-decrease "out"))

With this, you'll see zoom: [g]: in, [l]: out. in your echo area, once the zoom Hydra becomes active.

Colorful Hydras

Since version 0.5.0, Hydra's heads all have a color associated with them:

  • red (default) means the calling this head will not vanquish the Hydra
  • blue means that the Hydra will be vanquished after calling this head

In all the older examples, all heads are red by default. You can specify blue heads like this:

(global-set-key
 (kbd "C-c C-v")
 (defhydra toggle ()
   "toggle"
   ("a" abbrev-mode "abbrev" :color blue)
   ("d" toggle-debug-on-error "debug" :color blue)
   ("f" auto-fill-mode "fill" :color blue)
   ("t" toggle-truncate-lines "truncate" :color blue)
   ("w" whitespace-mode "whitespace" :color blue)
   ("q" nil "cancel")))

Or, since the heads can inherit the color from the body, the following is equivalent:

(global-set-key
 (kbd "C-c C-v")
 (defhydra toggle (:color blue)
   "toggle"
   ("a" abbrev-mode "abbrev")
   ("d" toggle-debug-on-error "debug")
   ("f" auto-fill-mode "fill")
   ("t" toggle-truncate-lines "truncate")
   ("w" whitespace-mode "whitespace")
   ("q" nil "cancel")))

The above Hydra is very similar to this code:

(global-set-key (kbd "C-c C-v t") 'toggle-truncate-lines)
(global-set-key (kbd "C-c C-v f") 'auto-fill-mode)
(global-set-key (kbd "C-c C-v a") 'abbrev-mode)

However, there are two important differences:

  • you get a hint like this right after C-c C-v:

      toggle: [t]: truncate, [f]: fill, [a]: abbrev, [q]: cancel.
    
  • you can cancel C-c C-v with a command while executing that command, instead of e.g. getting an error C-c C-v C-n is undefined for C-c C-v C-n.

Hydras and numeric arguments

Since version 0.6.0, for any Hydra:

  • digit-argment can be called with 0-9.
  • negative-argument can be called with -
  • universal-argument can be called with C-u

Hydras can have :pre and :post statements

Since version 0.7.0, you can specify code that will be called before each head, and after the body. For example:

(global-set-key
 (kbd "C-z")
 (defhydra hydra-vi
     (:pre
      (set-cursor-color "#40e0d0")
      :post
      (progn
        (set-cursor-color "#ffffff")
        (message
         "Thank you, come again.")))
   "vi"
   ("l" forward-char)
   ("h" backward-char)
   ("j" next-line)
   ("k" previous-line)
   ("q" nil "quit")))

New Hydra color: amaranth

Since version 0.8.0, a new color - amaranth, in addition to the previous red and blue, is available for the Hydra body.

According to Wikipedia:

The word amaranth comes from the Greek word amaranton, meaning "unwilting" (from the verb marainesthai, meaning "wilt"). The word was applied to amaranth because it did not soon fade and so symbolized immortality.

Hydras with amaranth body are impossible to quit with any binding except a blue head. A check for at least one blue head exists in defhydra, so that you don't get stuck by accident.

Here's an example of an amaranth Hydra:

(global-set-key
 (kbd "C-z")
 (defhydra hydra-vi
     (:pre
      (set-cursor-color "#40e0d0")
      :post
      (set-cursor-color "#ffffff")
      :color amaranth)
   "vi"
   ("l" forward-char)
   ("h" backward-char)
   ("j" next-line)
   ("k" previous-line)
   ("q" nil "quit")))

The only way to exit it, is to press q. No other methods will work. You can use an amaranth Hydra instead of a red one, if for you the cost of being able to exit only though certain bindings is less than the cost of accidentally exiting a red Hydra by pressing the wrong prefix.

Note that it does not make sense to define a single amaranth head, so this color can only be assigned to the body. An amaranth body will always have some amaranth heads and some blue heads (otherwise, it's impossible to exit), no reds.

About

make Emacs bindings that stick around

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Emacs Lisp 99.3%
  • Makefile 0.7%