| images | Upload files to "images" | |
| LICENSE | Update LICENSE | |
| README.md | Update README.md | |
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.elfile and load on startup. - Load the
my-hydras.elas 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)