1
1
Fork
You've already forked emacs-hydra-examples
0
Examples of hydras that work.
2025年12月09日 15:33:28 +01:00
images Upload files to "images" 2024年01月01日 18:49:32 +00:00
LICENSE Update LICENSE 2024年05月18日 12:51:04 +00:00
README.md Update README.md 2025年12月09日 15:33:28 +01:00

Version License: MIT

Examples of hydras for Emacs

Hydras and transient menus both can provide a temporary menu of commands at the bottom of the screen. Hydras can also provide a pop-up menu as alternate mode of operation. Transient menus are currently more popular. Both are useful for getting work done with an unfamiliar package by providing for the execution of commands by clicking on hyperlinks.

Emacs wizardy via hydra mastery

Hydras in Emacs provide a transitory popup menu that is invoked with a prefix key binding. The prefix is for a set of key bindings that are related to a mode or a category of tasks. Single letters mapped to Emacs commands complete the keybinding. These single letters are the heads of the hydra.

The single letters and their actions are listed in a transitory menu. The selection of a blue colored letter executes the command and closes the menu. The selection of a red-colored letter executes the associated command but leaves the menu open.

You can even make a hydra of your hydras so that you only have to remember the keybinding of one hydra, which in this case is C-c 0, where C represents the control key which is held down while pressing the c key and then 0 is pressed after releasing C-c. By nesting the hydras, this is the only key binding that you will need to remember to access all of the hydra heads of all of your hydras. You can define prefix keys for specific hydras to access them directly without going through the hydra-of-hdyras. However, I am finding myself using the former approach because of its simpilicity. Hydras can provide even beginning Emacs users with customizable superpowers.

I had heard of hydras in Emacs long before I understood them. There is now a five-minute overview on the Emacs Elements YouTube channel that provides a good introduction with three use cases. The videos on this channel are short and to the point. I find that they best meet my needs at this point on my Emacs journey. (I am a third year user; I consider myself between advanced beginner and competent user in the five levels of the Dreyfus-Dreyfus model of Adult Expertise Aquisition).

The developer of hydra-mode provides examples in an hydra-examples.el file, but I overlooked this file and these examples a year ago when I was not motivated to learn more. He also hosts a community-maintained wiki with some examples. I think the one for markdown-mode is easy for a beginner to understand, and it looks very useful for editing markdown files. Some hydras are more advanced and difficult for beginning elisp users to understand. There are several other sets of examples in on-line blogposts (e.g., Sacha Chua's Emacs config to inspire the beginner.

I think beginning Emacs users would appreciate more examples. I decided to share some of my-hydras.elmy hydras for the benefit of beginning Emacs users.

Proceed with caution

After making a few hydras, I started to see new opporutnities to make more. The my-hydras.el file grew to 1700 lines in the first month. I expect that the growth of my hydras will plateau as my need for new hydras is fulfilled. I was correct. After six months, my-hydras.el has grown to over 2000 lines rather than >9000 lines if the growth had been linear.

Installing Hydras

There are several approaches to loading the hydras.

  • Store in the init.el file and load on startup of Emacs.
  • Store in an external my-hydras.el file and load on startup.
  • Load the my-hydras.el as needed after startup of Emacs.

Copy-and-paste into init.el

You can simply copy and paste a selected hydra to your init.el file and then customize them to meet your needs.

Store hydras in external file

Alternately, you can store hydras in a separate file. This approach eases the use of existing hydras as templates to make new hydras.

For example, I made the file my-hydras.el and stored it on a subfolder of my emacs directory called my-hydras. I added the line (provide 'my-hydras) to the bottom of this file to convert it into a package file.

In the init.el file, I add this file to be list of packages near the top of of my init.el file (add-to-list 'package-selected-packages 'my-hydras) at the top of my init.el file. Then I add the following code elsewhere in the init.el file:

;; load hydras
(use-package my-hydras
 :load-path "~/emacs30/my-hydras/")

You can add a hydra head to open the my-hydra.el file to add new hydra heads.

To reload the updated hydras file, add the following to your init.el and then run M-x reload-hydras. This approach is faster than reloading the entire init.el file.

(defun reload-hydras ()
 "Reload my-hydras.el. Edit the path to suite your needs."
 (interactive)
 (load-file "~/emacs30/my-hydras/my-hydras.el"))

Hydra for yasnippets commands

This example defines the keybinding that will be active in the major modes where the package yasnippets is active. I found it on Reddit. The appearance of the pop-up menu is encoded explicitly. The format is explained here.

(use-package hydra
 :defer 2
 :bind ("C-c y" . hydra-yasnippet/body))
(defhydra hydra-yasnippet (:color blue)
 "
 ^
 ^YASnippet^ ^Do^
 ^─────────^──────────^──^────────
 _q_ quit _i_ insert
 ^^ _m_ mode
 ^^ _n_ new
 ^^ ^^
 "
 ("q" nil)
 ("i" yas-insert-snippet)
 ("m" yas-minor-mode)
 ("n" yas-new-snippet))

Hydra to open writing project on Overleaf in Firefox

Overleaf supports editing LaTeX files on-line in a text area. The documents are compiled to PDF faster than on my local machine. For example, I can compile a 1000 page book with 400 files in less than a minute when using the Overleaf website.

Overleaf also supports collaborative writing and the use of git for version control. I assemble my manuscripts and grant applications on Overleaf. I also assemble my platform talks and lectures with the beamer package on Overleaf. I can even assemble posters for scientific meetings from a gaint beamer slide. An example is below of a hydra for accessing a poster on Overleaf is given below.

;; overleaf
(custom-set-variables
 '(browse-url-browser-function (quote browse-url-firefox))
 '(browse-url-firefox-new-window-is-tab t))
(defhydra hydra-jump-to-overleaf-poster (:hint nil)
 "
 ^
 ^ Poster on Overleaf Abstract Due Date Submission Date Presentation Date
 ^─────────-----------------------------------------------------------------------------
 _a_ 4067 SciPy poster 28 February 14 June 12 July 6 PM
 _q_ quit
 ^────────--------------------------------------------------------------------------------
 "
 ("a" (browse-url--browser "https://www.overleaf.com/project/-------------------"))
 ("q" nil :color blue)) ; Add :color blue
(global-set-key (kbd "C-c 7") 'hydra-jump-to-overleaf-poster/body)

I have made hydras to access from Emacs writing logs, posters, papers, lectures, book, and grant application files. I had previously stored the urls of these documents in a local index.hmtl.

In summary, hydras support navigation to external projects while remaining in Emacs. I do not have to shift my focus to the web browser to navigate to a project on Overleaf.

Hydra for opening project files in org-mode

Projects are defined as consisting of multiple tasks in the Getting Things Done system by David Allen. I define projects as consisting of multiple events through time. Regardless, I divide projects into ten categories and store the projects with a unique identifier in a org-mode file for each category as shown below.

(defhydra hydra-jump-to-project-vertical (:hint nil)
 "
 ^
 ^Projects
 ^─────────-----
 _m_ manuscripts
 _g_ grants
 _b_ books
 _t_ talks
 _p_ posters
 _r_ reviews
 _f_ family
 _s_ service
 _l_ teaching
 _w_ workshops
 _n_ notes
 _q_ quit
 ^────────-----
 "
 ("m" (find-file "/Users/blaine/gtd/tasks/JournalArticles.org"))
 ("g" (find-file "/Users/blaine/gtd/tasks/Proposals.org"))
 ("b" (find-file "/Users/blaine/gtd/tasks/Books.org"))
 ("t" (find-file "/Users/blaine/gtd/tasks/Talks.org"))
 ("p" (find-file "/Users/blaine/gtd/tasks/Posters.org"))
 ("r" (find-file "/Users/blaine/gtd/tasks/ManuscriptReviews.org"))
 ("f" (find-file "/Users/blaine/gtd/tasks/Private.org"))
 ("s" (find-file "/Users/blaine/gtd/tasks/Service.org"))
 ("l" (find-file "/Users/blaine/gtd/tasks/Teaching.org"))
 ("w" (find-file "/Users/blaine/gtd/tasks/Workshops.org"))
 ("n" (find-file "/Users/blaine/org/notes.org"))
 ("q" nil :color blue)) ; Add :color blue
(global-set-key (kbd "C-c 1") 'hydra-jump-to-project-vertical/body)

Below is the generated popup menu:

I have made similar hdyras for writing projects that I am writing in org-mode locally and independently of Overleaf.

Hydra for opening a sqlite database using the DB Browser For SQlite

It can take time to navigate to a database file and open it. It would be nice to be able to open a database file with a hdyra head to reduce the motivational barrier to making a new entry in a database.

We define a function that opens a sqlite database using the DB\ Browser\ For\ SQlite.app from the shell. This function is then called by a hydra head. In this example, the head has three letters, xgq.

This example also includes a head, he, for editing the my-hydras.el file and one for editing the Emacs init.el file, i. There is a third head, z, for returning to the parent hydra.

Note that hydra head names longer than one letter have restrictions: Not all of them are permitted. For example, you cannot use both single letter and multiple letter hydra heads starting with the same letter.

;; Functions that open specific databases
(defun open-gqxtal-database ()
 "Open sqlite database in a `shell' buffer."
 (interactive)
 (comint-send-string
 (get-buffer-process (shell))
 "open /Users/blaine/0525gqx/gqx.db\n"))
;;*** hydra-databases
(defhydra hydra-of-databases (:hint nil)
 "
 ^
 ^Hydras Prefix
 ^─────────-------------------------------------------
 _xgq_ Open gqx.db in the DBBrowserForSQlite
 _he_ edit ~/emacs30/my-hydras/my-hydras.el
 _i_ edit init.el
 _z_ return to the parent hydra-of-hydras
 _q_ quit
 ^────────--------------------------------------------
 "
 ("xgq" (open-gqxtal-database) :color blue)
 ("he" (find-file "/Users/blaine/emacs30/my-hydras/my-hydras.el") :color blue)
 ("i" (find-file "/Users/blaine/emacs30/init.el") :color blue)
 ("z" hydra-of-hydras/body :color blue)
 ("q" nil :color blue))

Fancier hydras can be generated with the package pretty-hydra. The major-mode-hydra package runs on top of pretty-hdyra and is described at the same website. It eases the generation of tables of shortcut keys. Below is a from an example from the major-mode-hydra repo.

Menus configured by default

In the following examples, the default pop-up menu is used This is a simple box with the keys listed horizontally along with hints. The hints can contained sentences. The key is in doublequotes on the left, the command is next, the optional hint follows, and an optional plist of key-value pairs follows like the setting the color of the key.

Hydra for opening org agenda project files

This is the homolog of the example above that had the vertical menu. I prefer the vertical menu above.

(defhydra hydra-jump-to-project-file
 (:color blue)
 "Jump to org file."
 ("m" (find-file "/Users/blaine/gtd/tasks/JournalArticles.org") "JournalArticles.org")
 ("g" (find-file "/Users/blaine/gtd/tasks/Proposals.org") "Proposals.org")
 ("b" (find-file "/Users/blaine/gtd/tasks/Books.org") "Books.org")
 ("t" (find-file "/Users/blaine/gtd/tasks/Talks.org") "Talks.org")
 ("p" (find-file "/Users/blaine/gtd/tasks/Posters.org") "Posters.org")
 ("r" (find-file "/Users/blaine/gtd/tasks/ManuscriptReviews.org") "ManuscriptReviews.org")
 ("f" (find-file "/Users/blaine/gtd/tasks/Private.org") "Private.org")
 ("s" (find-file "/Users/blaine/gtd/tasks/Service.org") "Service.org")
 ("l" (find-file "/Users/blaine/gtd/tasks/Teaching.org") "Teaching.org")
 ("w" (find-file "/Users/blaine/gtd/tasks/Workshops.org") "Workshops.org")
 ("n" (find-file "/Users/blaine/org/notes.org") "notes.org")
 ("q" nil "Quit" :color blue)) ; Add :color blue
(global-set-key (kbd "C-c 1") 'hydra-jump-to-project-file/body)

Hydra for treemacs

This is a an example of a hydra for a specific package, treemacs. The hydra spares you the trouble of looking up the commands.

(defhydra hydra-of-treemacs (:hint nil)
 "
^
^Open system related files
 ^─────────-----------------------------------------------------------------------------
 _s_ M-0 treemacs-select-window
 _w_ C-x t 1 treemacs-delete-other-windows
 _d_ C-x t d treemacs-select-directory
 _m_ C-x t t treemacs
 _b_ C-x t B treemacs-bookmark
 _ff_ C-x t C-t treemacs-find-file
 _ft_ C-x t M-t treemacs-find-tag
 ^─────────-----------------------------------------------------------------------------
 _he_ edit my-hydras.el
 _i_ edit the init.el file
 _ri_ reload init.el
 _rh_ reload hydras
 _zz_ Return to hydra-of-hydras
 _q_ quit
 ^─────────-----------------------------------------------------------------------------
"
("s" (treemacs-select-window) :color blue)
("w" (treemacs-delete-other-windows) :color blue)
("d" (treemacs-select-directory) :color blue)
("m" (treemacs) :color blue)
("b" (treemacs-bookmark) :color blue)
("ff" (treemacs-find-file) :color blue)
("ft" (treemacs-find-tag) :color blue)
("he" (find-file "/Users/blaine/emacs30/my-hydras/my-hydras.el") :color blue)
("i" (find-file "/Users/blaine/emacs30/init.el") :color blue)
("ri" (reload-init) :color blue)
("rh" (reload-hydras) :color blue)
("zz" hydra-of-hydras/body :color blue)
("q" nil :color blue))

Hydra for engine-mode

Engine-mode is an Emacs package that supports sending a search term from Emacs to the search boxes of specific websites. The code snippet below supports the use of direct keybindings and of a hydra. The defengine takes only single-letter key bindings.

(use-package engine-mode)
(engine-mode t)
;; Default prefix is C-x /
;; Define the engine
(defengine github
 "https://github.com/search?ref=simplesearch&q=%s"
 :keybinding "h")
(defengine google 
 "https://www.google.com/search?q=%s"
 :keybinding "g")
(defengine pubmed
 "https://pubmed.ncbi.nlm.nih.gov/?term=%s"
 :keybinding "m")
;; Protein Databank 
(defengine pdb
 "https://www.rcsb.org/search?q=%s"
 :keybinding "p")
(defengine stack-overflow
 "https://stackoverflow.com/search?q=%s"
 :keybinding "o")
(defengine reddit 
 "https://www.reddit.com/search/?q=%s" 
 :keybinding "r")
(defengine sciencedirect 
 "https://www.sciencedirect.com/search?qs=%s"
 :keybinding "s")
(defengine wikipedia
 "https://www.wikipedia.org/search-redirect.php?language=en&go=Go&search=%s"
 :keybinding "k"
 :docstring "Searchin' the wikis.")
(defengine wolfram 
 "https://www.wolframalpha.com/input/?i=%s" 
 :keybinding "w")
(defengine youtube 
 "https://www.youtube.com/results?search_query=%s"
 :keybinding "y")
(defhydra hydra-engine
 (:color amaranth)
 "Send selected text to website."
 ("h" engine/search-github "Github")
 ("g" engine/search-google "Google")
 ("m" engine/search-pubmed "PubMed")
 ("p" engine/search-pdb "PDB")
 ("o" engine/search-stackoverflow "StackOverflow")
 ("r" engine/search-reddit "Reddit")
 ("s" engine/search-sciencedirect "Science Direct")
 ("k" engine/search-wikipedia "Wikipedia")
 ("w" engine/search-wolframalpha "Wolfram Alpha")
 ("y" engine/search-youtube "YouTube")
 ("q" nil "Quit" :color blue))
(global-set-key (kbd "C-c 3") 'hydra-engine/body)

Hydra of hydras

Yes, hydras can be nested! This hydra enables you to use only one keybinding to open several of your hydras. I have not tested the depth of the nesting that is possible, but I try to keep all tree-like structures as shallow as possible to speed up navigation.

(defhydra hydra-of-hydras ()
 ("p" hydra-jump-to-project-file/body "projects hydra for projects in org-mode, C-c 1" :color blue)
 ("y" hydra-yasnippet/body "yasnippets hydra, C-c y" :color blue)
 ("q" nil "Quit" :color blue))
(global-set-key (kbd "C-c 0") 'hydra-of-hydras/body)

This is the vertical variant for an updated version.

(defhydra hydra-of-hydras (:hint nil)
 "
 ^
 ^Hydras Prefix
 ^─────────--------------------------------------------------------
 _b_ bookmark buffer
 _c_ checklists
 _d0_ open databases
 _d1_ daily sites
 _d2_ drug design sites
 _d3_ dired of selected directories
 _d4_ defaliases
 _e_ engines for web searches C-c 3
 _f_ forms for lab work
 _la_ local journal articles C-c 2
 _lb_ local annotated bibliographies
 _lp_ local posters
 _mc_ cider (clojure) PLANNED
 _ml_ latex mode PLANNED
 _mm_ markdown-mode PLANNED
 _md_ org-mode PLANNED
 _mp_ python-mode PLANNED
 _od_ org-agenda-mode
 _om_ org-roam-mode C-c 4
 _oo_ org-mode
 _mr_ rst-mode
 _nj_ nextManuscripts0XXX.org
 _nn_ news
 _ob_ overleaf books C-c 7
 _og_ overleaf grant proposals
 _oj_ overleaf journal articles C-c 8
 _ol_ overleaf lectures
 _op_ overleaf poster
 _ot_ overleaf talks
 _ou_ overleaf helping users
 _pd_ ten10Kprojects database
 _pm_ pymol related
 _po_ projects in org-mode C-c 1
 _rs_ sicpy23 paper in reStructuredText
 _sf_ system files
 _sw_ software links
 _tm_ treemacs
 _wca_ My projects' collaborators, writing log
 _wcb_ BSC-OKC collaborators, writing log
 _wj_ journal articles, writing logs C-c 6
 _wg_ grant proposals
 _wb_ books, writing logs
 _wi_ window management
 _wl_ lectures, writing logs
 _wp_ posters, writing logs
 _ws_ service, writing logs
 _wt_ talks and seminars, writing logs
 _ww_ writing logs for workshop hosting
 _y_ yasnippets hydra C-c y
 _td_ Open mytime.db
 _tp_ Plot time by project
 _wd_ Open writingprogress.db
 _wp_ Plot writingprogress
 _he_ edit ~/emacs30/my-hydras/my-hydras.el
 _i_ edit init.el
 _ri_ reload init.el
 _rh_ reload hydras
 _q_ quit
 ^─────────--------------------------------------------------------
 "
("b" headlong-bookmark-jump :color blue)
("c" hydra-of-checklists/body :color blue)
("d0" hydra-of-databases/body :color blue)
("d1" hydra-of-daily-sites/body :color blue)
("d2" hydra-of-drug-design-sites/body :color blue)
("d3" hydra-of-dired/body :color blue)
("d4" hydra-of-defaliases/body :color blue)
("e" hydra-engine/body :color blue)
("f" hydra-of-forms/body :color blue)
("la" hydra-of-local-journal-articles/body :color blue)
("lb" hydra-of-annotated-bibliographies/body :color blue)
("lp" hydra-of-local-posters/body :color blue)
("mc" nil :color blue)
("ml" nil :color blue)
("mm" dh-hydra-markdown-mode/body :color blue)
("md" nil :color blue)
("mp" nil :color blue)
("od" hydra-of-org-agenda/body :color blue)
("om" hydra-of-org-roam/body :color blue)
("oo" hydra-of-org-mode/body :color blue)
("ot" hydra-of-org-table/body :color blue)
("mr" hydra-rst-mode/body :color blue)
("nj" hydra-next-manuscripts-org/body :color blue)
("nn" hydra-of-news/body :color blue)
("ob" hydra-overleaf-books/body :color blue)
("og" hydra-overleaf-grant-proposals/body :color blue)
("oj" hydra-overleaf-journal-articles/body :color blue)
("ol" hydra-overleaf-lectures/body :color blue)
("op" hydra-overleaf-posters/body :color blue)
("ot" hydra-overleaf-talks/body :color blue)
("ou" hydra-overleaf-users/body :color blue)
("pm" hydra-pymol-related/body :color blue)
("po" hydra-projects-org/body :color blue)
("rs" (find-file "/Users/blaine/0465scipy2023/scipy23paper/mooersblaine2023.rst") :color blue)
("sf" hydra-of-system-files/body :color blue)
("sw" hydra-of-software-links/body :color blue)
("tm" hydra-of-treemacs/body :color blue)
("wca" hydra-writing-log-my-projects-collaborations/body :color blue)
("wcb" hydra-writinglog-bsc-collaborations/body :color blue)
("wg" hydra-writing-log-grant-proposals/body :color blue)
("wi" jb-hydra-window/body :color blue)
("wj" hydra-writing-log-journal-articles/body :color blue)
("wl" hydra-writing-log-journal-lectures/body :color blue)
("wg" hydra-writing-log-grant-proposals/body :color blue)
("wb" hydra-writing-log-books/body :color blue)
("wp" hydra-writing-log-posters/body :color blue)
("ws" hydra-writing-log-service/body :color blue)
("wt" hydra-writing-log-talks/body :color blue)
("ww" hydra-writing-log-workshop/body :color blue)
("y" hydra-yasnippet/body :color blue)
("pd" (open-tenKprojects-database) :color blue)
("td" (open-timetracking-database) :color blue)
("tp" (plot-effort-by-project) :color blue)
("wd" (open-writing-database) :color blue)
("wp" (plot-writing-effort) :color blue)
("he" (find-file "/Users/blaine/emacs30/my-hydras/my-hydras.el") :color blue)
("i" (find-file "/Users/blaine/emacs30/init.el") :color blue)
("ri" (reload-init) :color blue)
("rh" (reload-hydras) :color blue)
("q" nil :color blue))
(global-set-key (kbd "C-c 0") 'hydra-of-hydras/body)

The snapshot below shows the popup window for the hydra-of-hydras.

Update history

Version Changes Date
Version 0.2 Added badges, funding, and update table. 2024 May 18

Sources of funding

  • NIH: R01 CA242845
  • NIH: R01 AI088011
  • NIH: P30 CA225520 (PI: R. Mannel)
  • NIH: P20 GM103640 and P30 GM145423 (PI: A. West)