How can I define transient color per command, like hydra?

Table of Contents

Problem: I need one transient command to end to the transient-session after it is done

From a Reddit thread at https://www.reddit.com/r/emacs/comments/15u0c7w/how_can_i_define_transient_color_per_command/

This is basically like using Hydra semantic colors1.

I have a transient that starts with :transient-suffix 'transient--do-stay near its definition, which allows me to execute several of its commands in a sequence without quiting the transient. There are certain commands within that transient, however, that should quit the transient if they are used. How can I specify a different transient-suffix on a certain few exception commands?

Example

My big transient has a mapping that includes the ability to winmove between different panes using my arrow keys; I should be able to do this rapidly and repeatedly for multiple movements. Same story with adjusting the pane (“splitter”) size; I need to be able to do it repeatedly to get the split size I want. However, other commands should terminate the transient session immediately, such as finding a file or spawning a sub-process.

Solution

img

("f" "find-file" find-file :transient transient--do-quit-one)

Individual commands can take a :transient argument, as per the above; this means that I can still do my repeatable commands on a 'transient--do-stay basis, but when I do the find-file command, it will end the transient session when finished.

Full code example

The tsa/ commands are custom, but the point still comes across without me providing their definitions.

(transient-define-prefix tsa/transient-window ()
  "Window navigation transient"
  :transient-suffix 'transient--do-stay
  [["Movement"
    ("h" "focus ←" windmove-left)
    ("t" "focus ↓" windmove-down)
    ("c" "focus ↑" windmove-up)
    ("n" "focus →" windmove-right)]
   ["Resize"    
    ("<left>" "X←" tsa/move-splitter-left)
    ("<down>" "X↓" tsa/move-splitter-down)    
    ("<up>" "X↑" tsa/move-splitter-up)    
    ("<right>" "X→" tsa/move-splitter-right)]
   ["Switch"
    ("b" "buffer" switch-to-buffer)
    ("f" "find-file" find-file :transient transient--do-quit-one)
    ("g" "git-grep" consult-git-grep :transient transient--do-quit-one)
    ("G" "Projectile RG" consult-ripgrep :transient transient--do-quit-one)
    ("p" "projectileF" projectile-find-file)
    ("F" "follow" follow-mode)
    ("a" "ace 1" transient-ace-cmd)
    ("&" "sub emacs" tsa/sub-emacs :transient transient--do-quit-one)]
   ["Split"
    ("v" "vertical" tsa/split-vertical)
    ("x" "horizontal" tsa/split-horizontal)
    ("`" "exwm swap" tsa/exwm-workspace-swap)
    ("s" "swap" tsa/screen-swap)
    ("S" "split" tsa/toggle-window-split)]   
   ["Scroll"
    ("." "left" scroll-left)
    ("," "right" scroll-right)
    ("4" "quad view" tsa/split-window-4)
    ("=" "Scratch" tsa/open-scratch)
    ("w" "Switch to Test" projectile-toggle-between-implementation-and-test "test<>imp")
    ]
   ["Window Lifecycle"
    ("d" "delete select 🗔" delete-window)
    ("D" "delete this 🗔" tsa/del-window)
    ("o" "delete adjacent 🗔" delete-other-windows)
    ("z" "winner back" tsa/winner-back)
    ("Z" "winner redo" winner-redo)
    ("SPC" "quit" transient-quit-all)
    ]])

Footnotes

1 Hydra semantic colors are such a useful idea that transient happily made the same a default. https://oremacs.com/2015/02/02/colorful-hydrae/ for the hydra implementation details, and code comments on inclusion in transient here: https://github.com/magit/transient/blob/226db67b3680acbeb74cb0403e1a302917054174/lisp/transient.el#L289. It was addressed in this major change, with good discussion: https://github.com/magit/transient/commit/248862c58e3bc0c13c6e3315adc2f3bb43c3c476

Tory Anderson avatar
Tory Anderson
Full-time Web App Engineer, Digital Humanist, Researcher, Computer Psychologist