Mastodon

Medusa. The Mother of all Hydras

My personal Hydras for Emacs , 2021-07-05T11:00:00+02:00

I like my Hydras. They are very useful for all the commands, that I don't use on a daily basis. I tend to forget the name of those commands, and also the keys I have bound them to. So for all these cases it's quite handy to have a small menu popping up, with hints for all those keys, and their commands. I can visually group them, and sort them in any order that makes sense to me.

What you read here is my actual configuration file, it is done via literal configuration a method similar to literate programming where my explanations are woven into snippets of actual configuration lines. Those snippets are tangled together and then executed by Emacs' Org-Babel package. You can also download it from my repository at Codeberg.org

In principle, I have two main entry points into my tree of hydras.

  • /medusa/major for all sort of things, that are tied to a special major mode.

    Each major mode has its own base hydra, so /medusa/major isn't a hydra itself, but a function, that calls the body of a hydra dependent on the active major mode This covers mostly things that are also reachable via the C-c key-prefix.

  • /medusa/emacs/body for all sort of things, that are not tied to a special major mode This covers most functions that are also reachable via the meno or C-x key-prefix

I tied this hydra to my menu key, or the app key on a windows system. Those XF86… keys are in use on my special POS keyboard, that I had in use for a while.

(global-set-key (kbd "<menu>") 'medusa/major)
(global-set-key (kbd "<apps>") 'medusa/major)
(global-set-key (kbd "<XF86Launch7>") 'medusa/major)

The right Windows key, to the left of the Menu key is now my super modifier key. Pressing it together with menu, shows me the global Emacs hydra:

(global-set-key (kbd "s-<menu>") 'medusa/emacs/body)
(global-set-key (kbd "<XF86AudioNext>") 'medusa/emacs/body)

Emacs-Hydra

This is the entry point to my global Emacs-Hydra. Its pretty raw by now. the keys that are visible in the Menu are functional. Those keys that call functions, or other hydras, but are not visible in the menu are considered tests.

(defhydra medusa/emacs (:color blue)
"
=^=^==============================================================================
=^ ^                                   Emacs                                     = 
=^=^==============================================================================
 _a_bbrevs _m_inor modes  _y_ankpad  _p_rojectile
=^=^==============================================================================
"
 ("y" medusa/yankpad/body)
 ("p" medusa/projectile/body)
 ("o" org-mode)
 ("f" medusa/file/body "File")
 ("a" medusa/abbrevs/body)
 ("m" medusa/minormodes/body)
 ("<menu>" medusa/launcher)

;; ("c" medusa/org-clock/body)
;; ("b" org-iswitchb )
;; ("r" medusa/org-refile-hydra/body)
)

Abbrevs

A defined “abbrev” is a word which “expands”, if you insert it, into some different text. Abbrevs are defined by the user to expand in specific ways. For example, you might define ‘foo’ as an abbrev expanding to ‘find outer otter’. Then you could insert ‘find outer otter ’ into the buffer by typing ‘f o o <SPC>’.

This hydra helps me in defining and editing those abbreviations, as I could never remember, which way of defining is the inverse direction.

It also shows two nice hydra heads, that I try to use wherever possible. The C and the ? head. The first takes me to the Customization group for everything about abbrevs, and the latter directly into the respective section in the Emacs manual that comes with the Emcas info system.

(defhydra medusa/abbrevs (:color blue :hint nil)
"
-^-^------------------^-^-----------------^-^---------------------------------^-^-----
-^ ^                  ^ ^           Abbrev^s^                                 ^ ^    - 
-^-^------------------^-^-----------------^-^---------------------------------^-^-----
 ^^GLOBAL ABBREV     ^^MODE SPECIFIC      ^^Other                          _C_ustomize
 ^*^***************  ^*^***************   ^*^*****
 from _s_cratch      from _S_cratch       _-_ Prefix abbrev
 from _a_bbrev       from _A_bbrev        e_x_pand abbrev
 from _d_efinition   from _D_efinition    ^ ^
 ^ ^                  ^ ^                 ^ ^                                 _?_ help
-^-^------------------^-^-----------------^-^---------------------------------^-^-----
"
 ("-" abbrev-prefix-mark)
 ("x" expand-abbrev)
 ("l" list-abbrevs)
 ("e" edit-abbrevs)
 ("s" define-global-abbrev)
 ("S" define-mode-abbrev)
 ("d" add-global-abbrev)
 ("D" add-mode-abbrev)
 ("a" inverse-add-global-abbrev)
 ("A" inverse-add-mode-abbrev)
 ("C" (customize-group-other-window "abbrev"))
 ("?" (info "(emacs) Abbrevs"))
 ("<menu>" medusa/launcher)
)

Minor Modes

A minor mode is an optional editing mode that alters the behavior of Emacs in some well-defined way. Unlike major modes, any number of minor modes can be in effect at any time. Some minor modes are “buffer-local”, and can be turned on (enabled) in certain buffers and off (disabled) in others. Other minor modes are “global”: while enabled, they affect everything you do in the Emacs session, in all buffers. Most minor modes are disabled by default, but a few are enabled by default.

(defhydra medusa/minormodes (global-map "H-m":color red :hint nil)
"
-^-^------------------^-^-----------------------------------------------------^-^-----
-^ ^                  ^ ^             Minor Modes                             ^ ^    - 
-^-^------------------^-^-----------------------------------------------------^-^-----
 ^ ^ GLOBAL MODES     ^ ^ LOCAL MODES   
 ^*^***************   ^*^***************
 _c_olumn number      _n_umbering lines 
 _l_ine number        fl_y_check mode

 _m_enu bar           auto _S_ave
 _t_ool bar           auto _F_ill
 _s_croll bar         _v_isual line

 _f_rame tabs         _w_indow tabs  

 _i_complete mode     _a_bbrev                                                _?_ help
-^-^------------------^-^-----------------------------------------------------^-^-----
"
 ("c" column-number-mode)
 ("l" line-number-mode)
 ("n" display-line-numbers-mode)
 ("i" icomplete-mode)
 ("m" menu-bar-mode)
 ("t" tool-bar-mode)
 ("s" scroll-bar-mode)
 ("a" abbrev-mode)
 ("v" visual-line-mode)
 ("f" tab-bar-mode)
 ("w" tab-line-mode)
 ("S" auto-save-mode)
 ("F" auto-fill-mode)
 ("y" flycheck-mode)
 ("?" (info "(emacs) Minor Modes"))
 ("<menu>" medusa/launcher)
)

Major Modes

(defun medusa/major ()
        "A launcher for hydras based on the current context."
        (interactive)
        (cl-case major-mode
          ('org-mode (medusa/org/body))
          ('ledger-mode (medusa/ledger/body))
          ('ledger-report-mode (medusa/ledger-report/body))
          (t (medusa/general/body) (message "No hydra for this major mode: %s" major-mode))))

Magic

(defun medusa/magic ()
      "A launcher for hydras based on the current context."
      (interactive)
      (cl-case major-mode
        ('org-mode (let* ((elem (org-element-context))
                                              (etype (car elem))
                                              (type (org-element-property :type elem)))
                                 (cl-case etype
                                       (src-block (medusa/babel/body))
                                       (link (medusa/org-link/body))
                                       ((table-row table-cell) (medusa/org-table/body) )
                                       (headline (medusa/org/body)) ; still to define
                                       (paragraph (medusa/org/body)) ; still to define
                                       (t (medusa/org/body) (message "No hydra for this type: %s " etype))
                                 )
                                )
                               )
        ('ledger-mode (medusa/ledger/body))
        ('ledger-report-mode (medusa/ledger-report/body))
        (t (medusa/general/body) (message "No hydra for this major mode: %s" major-mode))))


(defhydra medusa/magic (:color blue)
"
==================================================================================
=                                    Magic                                      = 
==================================================================================
 _y_ankpad  
==================================================================================
"
 ("y" medusa/yankpad/body)
 ("o" org-mode)
 ("f" medusa/file/body "File")
 ("<menu>" medusa/launcher)

;; ("c" medusa/org-clock/body)
;; ("b" org-iswitchb )
;; ("r" medusa/org-refile-hydra/body)
)

General

(defhydra medusa/general (:color blue)
"
==================================================================================
=                                    Medusa                                      = 
==================================================================================
 _y_ankpad  
==================================================================================
"
 ("y" medusa/yankpad/body)
 ("o" org-mode)
 ("f" medusa/file/body "File")
 ("<menu>" medusa/launcher)

;; ("c" medusa/org-clock/body)
;; ("b" org-iswitchb )
;; ("r" medusa/org-refile-hydra/body)
)

File-Hydra

 (defhydra medusa/file (:color blue :hint nil)
"
--------------------------------------------------------------------------------
-                                  File                                        -
--------------------------------------------------------------------------------
 _n_ew                                 _d_irectory
 _o_pen   (*)                          _p_rint
 _l_ast visited
 ^ ^ 
 _s_ave             
 _s_ave as          
 _c_lose            
 ^ ^ 
 _i_nsert           
 _r_evert           
 --------------------------------------------------------------------------------
"
       ("f" find-file-existing  :exit t)
       ("n" find-file           :color blue)
       ("o" find-file-existing  :color blue)
       ("l" recentf-open-files  :color blue)
       ("i" insert-file         :color blue)
       ("r" revert-buffer       :color blue)
       ("s" save-buffer         :color blue)
       ("a" write-file          :color blue)
       ("c" kill-this-buffer    :color blue)
       ("d" dired               :color blue)
       ("p" print-buffer        :color blue)
       )

Org

(defhydra medusa/org (:color blue)
  "Org:"
  ("c" medusa/org-clock/body "clock" :exit t)
  ("<menu>" org-ctrl-c-ctrl-c "Magic" :color blue)
  ("<apps>" org-ctrl-c-ctrl-c "Magic" :color blue)
  ("r" medusa/org-refile-hydra/body "refile")
  ("y" medusa/yankpad-hydra/body "yankpad")
  ("t" medusa/org-timer/body "Org-Timer")
  ("f" medusa/file/body "File")
  ("SPC" medusa/general/body "General")

  )

Org-Timer-Hydra

   (defhydra medusa/org-timer (:color blue :hint nil)
  "
   --------------------------------------------------------------------------------
   -                                  Timer                                       -
   --------------------------------------------------------------------------------
    _t_imer insert                           _g_o                                 
    _i_tem insert                            _s_top                               
    ^ ^                                      _p_ause                              
    ^ ^                                      ^ ^                                  
    ^ ^                                      _c_ountdown                          
    ^ ^                                      ^ ^                                  
    ^ ^                                      _?_ show remaining                   
   --------------------------------------------------------------------------------
  "
         ("t" org-timer "insert timer" :exit t)
         ("g" org-timer-start "Go" :color blue)
         ("s" org-timer-stop "Stop" :color blue)
         ("p" org-timer-pause-or-continue "Pause" :color blue)
         ("i" org-timer-item "insert timer item" :color blue)
         ("c" org-timer-set-timer "Countdown" :color blue)
         ("." org-timer "insert timer" :color blue)
         ("-" org-timer-item "insert timer item" :color blue)
         ("," org-timer-item "insert timer item" :color blue)
         ("?" org-timer-show-remaining "remaining?" :color blue)
         )

Table

(defhydra medusa/org-table (:color blue)
  "table:"
  ("c" hydra-org-clock/body "clock" :exit t)
  ("b" org-iswitchb "buffer" :color blue)
  ("<menu>" speedbar "speedbar" :color blue)
  ("r" medusa/org-refile-hydra/body "refile")
  ("y" medusa/yankpad-hydra/body "yankpad")
  )
(defhydra medusa/org-link (:color blue)
  "link:"
  ("c" hydra-org-clock/body "clock" :exit t)
  ("b" org-iswitchb "buffer" :color blue)
  ("<menu>" speedbar "speedbar" :color blue)
  ("r" medusa/org-refile-hydra/body "refile")
  ("y" medusa/yankpad-hydra/body "yankpad")
  )

Babel

(defhydra medusa/babel (:color blue)
  "Source:"
  ("c" hydra-org-clock/body "clock" :exit t)
  ("b" org-iswitchb "buffer" :color blue)
  ("<menu>" org-ctrl-c-ctrl-c "evaluate" :color blue)
  ("<apps>" org-ctrl-c-ctrl-c "evaluate" :color blue)
  ("r" medusa/org-refile-hydra/body "refile")
  ("y" medusa/yankpad-hydra/body "yankpad")
 ("SPC" medusa/general/body "General")
  )

Clocking-Hydra

  (global-set-key (kbd "C-<f11>") 'medusa/org-clock/body)
  (defhydra medusa/org-clock (:color blue)
         "
  ^Clock:^ ^In/out^     ^Edit^   ^Summary^    | ^Timers:^ ^Run^           ^Insert
  -^-^-----^-^----------^-^------^-^----------|--^-^------^-^-------------^------
  (_?_)    _i_n         _e_dit   _g_oto entry | (_z_)     _b_egin      ti_m_e
   ^ ^     _c_ontinue   _q_uit   _d_isplay    |  ^ ^      cou_n_tdown     i_t_em
   ^ ^     _o_ut        ^ ^      _r_eport     |  ^ ^      _p_ause toggle
   ^ ^     ^ ^          ^ ^      ^ ^          |  ^ ^      _s_top
  "
         ("i" org-clock-in)
         ("c" org-clock-in-last)
         ("o" org-clock-out)

         ("e" org-clock-modify-effort-estimate)
         ("q" org-clock-cancel)

         ("g" org-clock-goto)
         ("d" org-clock-display )
         ("r" org-clock-report)
         ("?" (org-info "Clocking commands"))

        ("b" org-timer-start)
        ("n" org-timer-set-timer)
        ("p" org-timer-pause-or-continue)
        ("s" org-timer-stop)

        ("m" org-timer)
        ("t" org-timer-item)
        ("z" (org-info "Timers"))
)

Ledger

  (defhydra medusa/ledger (:color blue :hint nil)

"
 --------------------------------------------------------------------------------
 -                                  Leder                                       -
 ********************************************************************************
 * _a_dd      transaction  ^ ^               * _r_eporting                            -
 * _c_opy     transaction  ^ ^               * ^ ^                                    -
 * _d_elete   transaction  ^ ^               * ^ ^                                    -
 * ^ ^                     ^ ^               * ^ ^                                    -
 * _t_oggle   transaction  ^ ^               * ^ ^                                    -
 * _u_pcoming transactions ^ ^               * ^ ^                                    -
 * ^ ^                     ^ ^               * ^ ^                                    -
 * _s_ort region           _S_ort  buffer    * ^ ^                                    -
 * _C_lean buffer          ^ ^               * ^ ^                                    -
 * ^ ^                     ^ ^               * ^ ^                                    -
 * _=_ calculate amount    ^ ^               * ^ ^                                    *
 --------------------------------------------------------------------------------
 * _q_uit                  ^ ^                 ^ ^                                    *
 --------------------------------------------------------------------------------
"

("d" ledger-delete-current-transaction)
("<menu>" ledger-add-transaction)
("<apps>" ledger-add-transaction)
("a" ledger-add-transaction)
("SPC" medusa/general/body)
("r" ledger-report)
("." ledger-complete-at-point)     
("<tab>" ledger-magic-tab)   
("<down>" ledger-navigate-end-of-xact :color red)    
("<up>" ledger-navigate-beginning-of-xact :color red)
("<C-down>" ledger-navigate-next-xact-or-directive :color red)       
("<C-up>" ledger-navigate-prev-xact-or-directive :color red)
("t" ledger-toggle-current-transaction)
("f" ledger-occur)         
("F" ledger-occur-refresh)
("R" ledger-reconcile)     
("c" ledger-copy-transaction-at-point)
("C" ledger-mode-clean-buffer)
("u" ledger-schedule-upcoming)     
("S" ledger-sort-buffer)   
("s" ledger-sort-region)   
("/" ledger-toggle-current-transaction)
("q" nil "cancel")
("=" nil "cancel")
)

Ledger-Report

 (defhydra medusa/ledger-report (:color blue)
 "
        ^Balance^     ^Register^      ^Budget^       ^Report^
   -^-------^-----^--------^------^------^-------^------^-----
        _1_ Overview  _2_ Overview    _3_ Overview
        g Giro        G Giro        i_t_em
        b Bargeld     B Bargeld      _p_ause toggle
        k Kreditkarte K Kreditkarte  _s_top
        h Hauskredite H Hauskredite  _s_top

 "

 ("<menu>" ledger-add-transaction)
 ("<apps>" ledger-add-transaction)
 ("1" medusa/general/body)
 ("2" medusa/general/body)
 ("3" medusa/general/body)
 ("t" medusa/general/body)
 ("p" medusa/general/body)
 ("s" medusa/general/body)
 ("SPC" medusa/general/body)

 )

Yankpad-Hydra

 (defhydra medusa/yankpad (:color blue :hint nil)
 "
  --------------------------------------------------------------------------------
  -                                  Yankpad                                     -
  --------------------------------------------------------------------------------
   _i_nsert snippet                         _r_eload                                
   e_x_pand snippet                         ^ ^                                     
   _e_dit   snippets                        ^ ^                                     
   _._ repeat                               ^ ^                                     
   ^ ^                                      ^ ^                                     
   _s_et category                           ^ ^                                     
   _a_dd category                           ^ ^                                     
   ^ ^                                      ^ ^                                     
   _c_apture snippet                        ^ ^                                     
  --------------------------------------------------------------------------------
 "
  ("e" yankpad-edit)
  ("i" yankpad-insert)
  ("y" yankpad-insert)
  ("c" yankpad-capture-snippet)
  ("a" yankpad-append-category)
  ("s" yankpad-set-category)
  ("r" yankpad-reload)
  ("x" yankpad-expand)
  ("." yankpad-repeat)
 )

Projectile

(defhydra medusa/projectile-other-window (:color teal)
      "projectile-other-window"
              ("f"  projectile-find-file-other-window        "file")
              ("g"  projectile-find-file-dwim-other-window   "file dwim")
              ("d"  projectile-find-dir-other-window         "dir")
              ("b"  projectile-switch-to-buffer-other-window "buffer")
              ("q"  nil                                      "cancel" :color blue)
)

(defhydra medusa/projectile (:color teal :hint nil)
      "

     PROJECTILE: %(projectile-project-root)

             ^^Find File          ^^Search Tags          ^^Buffers         ^^     Cache
       ------------------------------------------------------------------------------------------
        _s-f_: file            _a_: ag                _i_: Ibuffer           _c_: cache clear
         _ff_: file dwim       _g_: update gtags      _b_: switch to buffer  _x_: remove known project
         _fd_: file curr dir   _o_: multi-occur     _s-k_: Kill all buffers  _X_: cleanup non-existing
              _r_: recent file                                               ^^^^_z_: cache current
              _d_: dir

      "
              ("a"   helm-projectile-ag)
              ("b"   helm-projectile-switch-to-buffer)
              ("c"   projectile-invalidate-cache)
              ("d"   helm-projectile-find-dir)
              ("s-f" helm-projectile-find-file)
              ("ff"  helm-projectile-find-file-dwim)
              ("fd"  projectile-find-file-in-directory)
              ("g"   ggtags-update-tags)
              ("s-g" ggtags-update-tags)
              ("i"   projectile-ibuffer)
              ("K"   projectile-kill-buffers)
              ("s-k" projectile-kill-buffers)
              ("m"   projectile-multi-occur)
              ("o"   projectile-multi-occur)
              ("s-p" helm-projectile-switch-project "switch project")
              ("p"   helm-projectile-switch-project)
              ("s"   helm-projectile-switch-project)
              ("r"   helm-projectile-recentf)
              ("x"   projectile-remove-known-project)
              ("X"   projectile-cleanup-known-projects)
              ("z"   projectile-cache-current-file)
              ("`"   medusa/projectile-other-window/body "other window")
              ("q"   nil "cancel" :color blue)
)

jl

dahermit freundlichem Gruss Andreas Drop