diff options
Diffstat (limited to 'elpa/transient-0.8.6/transient.org')
-rw-r--r-- | elpa/transient-0.8.6/transient.org | 2745 |
1 files changed, 2745 insertions, 0 deletions
diff --git a/elpa/transient-0.8.6/transient.org b/elpa/transient-0.8.6/transient.org new file mode 100644 index 0000000..f14929a --- /dev/null +++ b/elpa/transient-0.8.6/transient.org @@ -0,0 +1,2745 @@ +#+title: Transient User and Developer Manual +:PREAMBLE: +#+author: Jonas Bernoulli +#+email: emacs.transient@jonas.bernoulli.dev +#+date: 2018-{{{year}}} + +#+texinfo_dir_category: Emacs misc features +#+texinfo_dir_title: Transient: (transient). +#+texinfo_dir_desc: Transient Commands +#+subtitle: for version 0.8.6 + +#+setupfile: .orgconfig + +Transient is the library used to implement the keyboard-driven “menus” +in Magit. It is distributed as a separate package, so that it can be +used to implement similar menus in other packages. + +This manual can be bit hard to digest when getting started. A useful +resource to get over that hurdle is Psionic K's interactive tutorial, +available at https://github.com/positron-solutions/transient-showcase. + +#+texinfo: @noindent +This manual is for Transient version 0.8.6. + +#+texinfo: @insertcopying +:END: +* Introduction + +Transient is the library used to implement the keyboard-driven {{{dfn(menus)}}} +in Magit. It is distributed as a separate package, so that it can be +used to implement similar menus in other packages. + +This manual can be bit hard to digest when getting started. A useful +resource to get over that hurdle is Psionic K's interactive tutorial, +available at https://github.com/positron-solutions/transient-showcase. + +** Some things that Transient can do +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- Display current state of arguments +- Display and manage lifecycle of modal bindings +- Contextual user interface +- Flow control for wizard-like composition of interactive forms +- History & persistence +- Rendering arguments for controlling CLI programs + +** Complexity in CLI programs +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +Complexity tends to grow with time. How do you manage the complexity +of commands? Consider the humble shell command =ls=. It now has over +/fifty/ command line options. Some of these are boolean flags (=ls -l=). +Some take arguments (=ls --sort=s=). Some have no effect unless paired +with other flags (=ls -lh=). Some are mutually exclusive. Some shell +commands even have so many options that they introduce /subcommands/ +(=git branch=, =git commit=), each with their own rich set of options +(=git branch -f=). + +** Using Transient for composing interactive commands +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +What about Emacs commands used interactively? How do these handle +options? One solution is to make many versions of the same command, +so you don't need to! Consider: =delete-other-windows= vs. +=delete-other-windows-vertically= (among many similar examples). + +Some Emacs commands will simply prompt you for the next "argument" +(=M-x switch-to-buffer=). Another common solution is to use prefix +arguments which usually start with =C-u=. Sometimes these are sensibly +numerical in nature (=C-u 4 M-x forward-paragraph= to move forward 4 +paragraphs). But sometimes they function instead as boolean +"switches" (=C-u C-SPACE= to jump to the last mark instead of just +setting it, =C-u C-u C-SPACE= to unconditionally set the mark). Since +there aren't many standards for the use of prefix options, you have to +read the command's documentation to find out what the possibilities +are. + +But when an Emacs command grows to have a truly large set of options +and arguments, with dependencies between them, lots of option values, +etc., these simple approaches just don't scale. Transient is designed +to solve this issue. Think of it as the humble prefix argument =C-u=, +/raised to the power of 10/. Like =C-u=, it is key driven. Like the +shell, it supports boolean "flag" options, options that take +arguments, and even "sub-commands", with their own options. But +instead of searching through a man page or command documentation, +well-designed transients /guide/ their users to the relevant set of +options (and even their possible values!) directly, taking into +account any important pre-existing Emacs settings. And while for +shell commands like =ls=, there is only one way to "execute" (hit +=Return=!), transients can "execute" using multiple different keys tied +to one of many self-documenting /actions/ (imagine having 5 different +colored return keys on your keyboard!). Transients make navigating +and setting large, complex groups of command options and arguments +easy. Fun even. Once you've tried it, it's hard to go back to the +=C-u what can I do here again?= way. + +* Usage +** Invoking Transients +#+cindex: invoking transients + +A transient prefix command is invoked like any other command by +pressing the key that is bound to that command. The main difference +to other commands is that a transient prefix command activates a +transient keymap, which temporarily binds the transient's infix and +suffix commands, and that those bindings are displayed in a transient +menu, displayed in a popup buffer. Bindings from other keymaps may, +or may not, be disabled while the transient state is in effect. + +There are two kinds of commands that are available after invoking a +transient prefix command; infix and suffix commands. Infix commands +set some value (which is then shown in the popup buffer), without +leaving the transient. Suffix commands, on the other hand, usually +quit the transient and they may use the values set by the infix +commands, i.e., the infix *arguments*. + +Instead of setting arguments to be used by a suffix command, infix +commands may also set some value by side-effect, e.g., by setting the +value of some variable. + +** Aborting and Resuming Transients +#+cindex: aborting transients +#+cindex: resuming transients + +#+cindex: quit transient +To quit the transient without invoking a suffix command press {{{kbd(C-g)}}}. + +Key bindings in transient keymaps may be longer than a single event. +After pressing a valid prefix key, all commands whose bindings do not +begin with that prefix key are temporarily unavailable and grayed out. +To abort the prefix key press {{{kbd(C-g)}}} (which in this case only quits the +prefix key, but not the complete transient). + +A transient prefix command can be bound as a suffix of another +transient. Invoking such a suffix replaces the current transient +state with a new transient state, i.e., the available bindings change +and the information displayed in the popup buffer is updated +accordingly. Pressing {{{kbd(C-g)}}} while a nested transient is active only +quits the innermost transient, causing a return to the previous +transient. + +{{{kbd(C-q)}}} or {{{kbd(C-z)}}} on the other hand always exits all transients. If you use +the latter, then you can later resume the stack of transients using +{{{kbd(M-x transient-resume)}}}. + +#+attr_texinfo: :compact t +- Key: C-g (transient-quit-seq) :: +- Key: C-g (transient-quit-one) :: + + This key quits the currently active incomplete key sequence, if any, + or else the current transient. When quitting the current transient, + it returns to the previous transient, if any. + +Transient's predecessor bound {{{kbd(q)}}} instead of {{{kbd(C-g)}}} to the quit command. +To learn how to get that binding back see ~transient-bind-q-to-quit~'s +documentation string. + +- Key: C-q (transient-quit-all) :: + + This command quits the currently active incomplete key sequence, if + any, and all transients, including the active transient and all + suspended transients, if any. + +- Key: C-z (transient-suspend) :: + + Like ~transient-quit-all~, this command quits an incomplete key + sequence, if any, and all transients. Additionally, it saves the + stack of transients so that it can easily be resumed (which is + particularly useful if you quickly need to do “something else” and + the stack is deeper than a single transient, and/or you have already + changed the values of some infix arguments). + + Note that only a single stack of transients can be saved at a time. + If another stack is already saved, then saving a new stack discards + the previous stack. + +- Key: M-x transient-resume :: + + This command resumes the previously suspended stack of transients, + if any. + +** Common Suffix Commands +#+cindex: common suffix commands + +A few shared suffix commands are available in all transients. These +suffix commands are not shown in the popup buffer by default. + +This includes the aborting commands mentioned in the previous section, +as well as some other commands that are all bound to {{{kbdvar(C-x <KEY>)}}}. After +{{{kbd(C-x)}}} is pressed, a section featuring all these common commands is +temporarily shown in the popup buffer. After invoking one of them, +the section disappears again. Note, however, that one of these +commands is described as “Show common permanently”; invoke that if you +want the common commands to always be shown for all transients. + +- Key: C-x t (transient-toggle-common) :: + + This command toggles whether the generic commands that are common to + all transients are always displayed or only after typing the + incomplete prefix key sequence {{{kbd(C-x)}}}. This only affects the current + Emacs session. + +- User Option: transient-show-common-commands :: + + This option controls whether shared suffix commands are shown + alongside the transient-specific infix and suffix commands. By + default, the shared commands are not shown to avoid overwhelming + the user with too many options. + + While a transient is active, pressing {{{kbd(C-x)}}} always shows the common + commands. The value of this option can be changed for the current + Emacs session by typing {{{kbd(C-x t)}}} while a transient is active. + +The other common commands are described in either the previous or in +one of the following sections. + +** Saving Values +#+cindex: saving values of arguments + +After setting the infix arguments in a transient, the user can save +those arguments for future invocations. + +Most transients will start out with the saved arguments when they are +invoked. There are a few exceptions, though. Some transients are +designed so that the value that they use is stored externally as the +buffer-local value of some variable. Invoking such a transient again +uses the buffer-local value. [fn:1] + +If the user does not save the value and just exits using a regular +suffix command, then the value is merely saved to the transient's +history. That value won't be used when the transient is next invoked, +but it is easily accessible (see [[*Using History]]). + +- Key: C-x s (transient-set) :: + + This command saves the value of the active transient for this Emacs + session. + +- Key: C-x C-s (transient-save) :: + + This command saves the value of the active transient persistently + across Emacs sessions. + +- Key: C-x C-k (transient-reset) :: + + This command clears the set and saved values of the active transient. + +- User Option: transient-values-file :: + + This option names the file that is used to persist the values of + transients between Emacs sessions. + +[fn:1] ~magit-diff~ and ~magit-log~ are two prominent examples, and their +handling of buffer-local values is actually a bit more complicated +than outlined above and even customizable. + +** Using History +#+cindex: value history + +Every time the user invokes a suffix command the transient's current +value is saved to its history. These values can be cycled through, +the same way one can cycle through the history of commands that read +user-input in the minibuffer. + +#+attr_texinfo: :compact t +- Key: C-M-p (transient-history-prev) :: +- Key: C-x p :: + + This command switches to the previous value used for the active + transient. + +- Key: C-M-n (transient-history-next) :: +- Key: C-x n :: + + This command switches to the next value used for the active + transient. + +In addition to the transient-wide history, infixes can have their own +history. When an infix reads user-input using the minibuffer, the +user can use the regular minibuffer history commands to cycle through +previously used values. Usually the same keys as those mentioned +above are bound to those commands. + +Authors of transients should arrange for different infix commands that +read the same kind of value to also use the same history key (see +[[*Suffix Slots]]). + +Both kinds of history are saved to a file when Emacs is exited. + +- User Option: transient-save-history :: + + This option controls whether the history of transient commands is + saved when exiting Emacs. + +- User Option: transient-history-file :: + + This option names the file that is used to persist the history of + transients and their infixes between Emacs sessions. + +- User Option: transient-history-limit :: + + This option controls how many history elements are kept at the time + the history is saved in ~transient-history-file~. + +** Getting Help for Suffix Commands +#+cindex: getting help + +Transients can have many suffixes and infixes that the user might not +be familiar with. To make it trivial to get help for these, Transient +provides access to the documentation directly from the active +transient. + +- Key: C-h (transient-help) :: + + This command enters help mode. When help mode is active, typing a + key shows information about the suffix command that the key normally + is bound to (instead of invoking it). Pressing {{{kbd(C-h)}}} a second time + shows information about the /prefix/ command. + + After typing a key, the stack of transient states is suspended and + information about the suffix command is shown instead. Typing {{{kbd(q)}}} in + the help buffer buries that buffer and resumes the transient state. + +What sort of documentation is shown depends on how the transient was +defined. For infix commands that represent command-line arguments +this ideally shows the appropriate manpage. ~transient-help~ then tries +to jump to the correct location within that. Info manuals are also +supported. The fallback is to show the command's documentation +string, for non-infix suffixes this is usually appropriate. + +** Enabling and Disabling Suffixes +#+cindex: enabling suffixes +#+cindex: disabling suffixes + +The user base of a package that uses transients can be very diverse. +This is certainly the case for Magit; some users have been using it and +Git for a decade, while others are just getting started now. + +#+cindex: levels +For that reason a mechanism is needed that authors can use to classify a +transient's infixes and suffixes along the essentials...everything +spectrum. We use the term {{{dfn(levels)}}} to describe that mechanism. + +#+cindex: transient-level +Each suffix command is placed on a level and each transient has a +level (called {{{dfn(transient-level)}}}), which controls which suffix commands +are available. Integers between 1 and 7 (inclusive) are valid levels. +For suffixes, 0 is also valid; it means that the suffix is not +displayed at any level. + +The levels of individual transients and/or their individual suffixes +can be changed interactively, by invoking the transient and then +pressing {{{kbd(C-x l)}}} to enter the “edit” mode, see below. + +The default level for both transients and their suffixes is 4. The +~transient-default-level~ option only controls the default for +transients. The default suffix level is always 4. The authors of +transients should place certain suffixes on a higher level, if they +expect that it won't be of use to most users, and they should place +very important suffixes on a lower level, so that they remain +available even if the user lowers the transient level. + +- User Option: transient-default-level :: + + This option controls which suffix levels are made available by + default. It sets the transient-level for transients for which the + user has not set that individually. + +- User Option: transient-levels-file :: + + This option names the file that is used to persist the levels of + transients and their suffixes between Emacs sessions. + +- Key: C-x l (transient-set-level) :: + + This command enters edit mode. When edit mode is active, then all + infixes and suffixes that are currently usable are displayed along + with their levels. The colors of the levels indicate whether they + are enabled or not. The level of the transient is also displayed + along with some usage information. + + In edit mode, pressing the key that would usually invoke a certain + suffix instead prompts the user for the level that suffix should be + placed on. + + Help mode is available in edit mode. + + To change the transient level press {{{kbd(C-x l)}}} again. + + To exit edit mode press {{{kbd(C-g)}}}. + + Note that edit mode does not display any suffixes that are not + currently usable. ~magit-rebase~, for example, shows different + suffixes depending on whether a rebase is already in progress or + not. The predicates also apply in edit mode. + + Therefore, to control which suffixes are available given a certain + state, you have to make sure that that state is currently active. + +- Key: C-x a (transient-toggle-level-limit) :: + + This command toggle whether suffixes that are on levels higher than + the level specified by ~transient-default-level~ are temporarily + available anyway. + +- Function: transient-set-default-level suffix level :: + + This function sets the default level of the suffix COMMAND to LEVEL. + + If a suffix command appears in multiple menus, it may make sense to + consistently change its level in all those menus at once. For + example, the ~--gpg-sign~ argument (which is implemented using the + command ~magit:--gpg-sign~), is bound in all of Magit's menu which + create commits. Users who sometimes sign their commits would want + that argument to be available in all of these menus, while for users + who never sign it is just unnecessary noise in any menus. + + To always make ~--gpg-sign~ available, use: + + #+begin_src emacs-lisp + (transient-set-default-level 'magit:--gpg-sign 1) + #+end_src + + To never make ~--gpg-sign~ available, use: + + #+begin_src emacs-lisp + (transient-set-default-level 'magit:--gpg-sign 0) + #+end_src + + This sets the level in the suffix prototype object for this command. + Commands only have a suffix prototype if they were defined using one + of ~transient-define-argument~, ~transient-define-infix~ and + ~transient-define-suffix~. For all other commands this would signal + an error. (This is one of the reasons why package authors should + use one of these functions to define shared suffix commands, and + especially shared arguments.) + + If the user changes the level of a suffix in a particular menu, + using {{{kbd(C-x l)}}} as shown above, then that obviously shadows the default. + + It is also possible to set the level of a suffix binding in a + particular menu, either when defining the menu using + ~transient-define-prefix,~ or later using ~transient-insert-suffix~. If + such bindings specify a level, then that also overrides the default. + (Per-suffix default levels is a new feature, so you might encounter + this quite often.) + +** Other Commands + +When invoking a transient in a small frame, the transient window may +not show the complete buffer, making it necessary to scroll, using the +following commands. These commands are never shown in the transient +window, and the key bindings are the same as for ~scroll-up-command~ and +~scroll-down-command~ in other buffers. + +- Command: transient-scroll-up arg :: + + This command scrolls text of transient popup window upward {{{var(ARG)}}} + lines. If {{{var(ARG)}}} is ~nil~, then it scrolls near full screen. This + is a wrapper around ~scroll-up-command~ (which see). + +- Command: transient-scroll-down arg :: + + This command scrolls text of transient popup window down {{{var(ARG)}}} + lines. If {{{var(ARG)}}} is ~nil~, then it scrolls near full screen. This + is a wrapper around ~scroll-down-command~ (which see). + +The following commands are not available by default. If you would +like to use them for all menus, bind them in ~transient-map~. + +- Command: transient-copy-menu-text :: + + This command copies the contents of the menu buffer to the kill + ring. + +- Command: transient-toggle-docstrings :: + + This command toggle between showing suffix descriptions in the menu + (as usual) or showing the first lines of the respective docstrings + in their place. For commands that do not have a docstring, always + display the suffix description. Because there likely isn't enough + room to display multiple docstrings side-by-side, a single column + is used when displaying docstrings. + +** Configuration + +More options are described in [[* Common Suffix Commands]], in [[* Saving +Values]], in [[* Using History]] and in [[* Enabling and Disabling Suffixes]]. + +*** Essential Options +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +Also see [[* Common Suffix Commands]]. + +- User Option: transient-show-popup :: + + This option controls whether the current transient's infix and + suffix commands are shown in the popup buffer. + + - If ~t~ (the default) then the popup buffer is shown as soon as a + transient prefix command is invoked. + + - If ~nil~, then the popup buffer is not shown unless the user + explicitly requests it, by pressing an incomplete prefix key + sequence. + + - If a number, then the a brief one-line summary is shown instead of + the popup buffer. If zero or negative, then not even that summary + is shown; only the pressed key itself is shown. + + The popup is shown when the user explicitly requests it by + pressing an incomplete prefix key sequence. Unless this is zero, + the popup is shown after that many seconds of inactivity (using + the absolute value). + +- User Option: transient-show-common-commands :: + + This option controls whether shared suffix commands are shown + alongside the transient-specific infix and suffix commands. By + default, the shared commands are not shown to avoid overwhelming + the user with too many options. + + While a transient is active, pressing {{{kbd(C-x)}}} always shows the common + commands. The value of this option can be changed for the current + Emacs session by typing {{{kbd(C-x t)}}} while a transient is active. + +- User Option: transient-show-during-minibuffer-read :: + + This option controls whether the transient menu continues to be + displayed while the minibuffer is used to read user input. + + This is only relevant to commands that do not close the menu, such as + commands that set infix arguments. If a command exits the menu, and + uses the minibuffer, then the menu is always closed before the + minibuffer is entered, irrespective of the value of this option. + + When ~nil~ (the default), hide the menu while the minibuffer is in use. + When ~t~, keep showing the menu, but allow for the menu window to be + resized, to ensure that completion candidates can be displayed. + + When ~fixed~, keep showing the menu and prevent it from being resized, + which may make it impossible to display the completion candidates. If + that ever happens for you, consider using ~t~ or an integer, as described + below. + + If the value is ~fixed~ and the menu window uses the full height of its + frame, then the former is ignored and resizing is allowed anyway. This + is necessary because individual menus may use unusual display actions + different from what ~transient-display-buffer-action~ specifies (likely + to display that menu in a side-window). + + When using a third-party mode, which automatically resizes windows + (e.g., by calling ~balance-windows~ on ~post-command-hook~), then + ~fixed~ (or ~nil~) is likely a better choice than ~t~. + + The value can also be an integer, in which case the behavior depends on + whether at least that many lines are left to display windows other than + the menu window. If that is the case, display the menu and preserve the + size of that window. Otherwise, allow resizing the menu window if the + number is positive, or hide the menu if it is negative. + +- User Option: transient-read-with-initial-input :: + + This option controls whether the last history element is used as the + initial minibuffer input when reading the value of an infix argument + from the user. If ~nil~, there is no initial input and the first + element has to be accessed the same way as the older elements. + +- User Option: transient-enable-popup-navigation :: + + This option controls whether navigation commands are enabled in the + transient popup buffer. If the value is ~verbose~ (the default), + brief documentation about the command under point is additionally + show in the echo area. + + While a transient is active the transient popup buffer is not the + current buffer, making it necessary to use dedicated commands to act + on that buffer itself. If this option is non-~nil~, then the + following features are available: + + - {{{kbd(UP)}}} moves the cursor to the previous suffix. + - {{{kbd(DOWN)}}} moves the cursor to the next suffix. + - {{{kbd(M-RET)}}} invokes the suffix the cursor is on. + - {{{kbd(mouse-1)}}} invokes the clicked on suffix. + - {{{kbd(C-s)}}} and {{{kbd(C-r)}}} start isearch in the popup buffer. + + By default {{{kbd(M-RET)}}} is bound to ~transient-push-button~, instead of + {{{kbd(RET)}}}, because if a transient allows the invocation of non-suffixes, + then it is likely, that you would want {{{kbd(RET)}}} to do what it would do + if no transient were active." + +- User Option: transient-display-buffer-action :: + + This option specifies the action used to display the transient popup + buffer. The transient popup buffer is displayed in a window using + {{{codevar((display-buffer BUFFER transient-display-buffer-action))}}}. + + The value of this option has the form {{{codevar((FUNCTION . ALIST))}}}, + where {{{var(FUNCTION)}}} is a function or a list of functions. Each such + function should accept two arguments: a buffer to display and an + alist of the same form as {{{var(ALIST)}}}. See [[info:elisp#Choosing Window]], + for details. + + The default is: + + #+BEGIN_SRC emacs-lisp + (display-buffer-in-side-window + (side . bottom) + (dedicated . t) + (inhibit-same-window . t)) + #+END_SRC + + This displays the window at the bottom of the selected frame. + For alternatives see [[info:elisp#Buffer Display Action Functions]], + and [[info:elisp#Buffer Display Action Alists]]. + + When you switch to a different ACTION, you should keep the ALIST + entries for ~dedicated~ and ~inhibit-same-window~ in most cases. + Do not drop them because you are unsure whether they are needed; + if you are unsure, then keep them. + + Note that the buffer that was current before the transient buffer + is shown should remain the current buffer. Many suffix commands + act on the thing at point, if appropriate, and if the transient + buffer became the current buffer, then that would change what is + at point. To that effect ~inhibit-same-window~ ensures that the + selected window is not used to show the transient buffer. + + It may be possible to display the window in another frame, but + whether that works in practice depends on the window-manager. + If the window manager selects the new window (Emacs frame), + then that unfortunately changes which buffer is current. + + If you change the value of this option, then you might also + want to change the value of ~transient-mode-line-format~. + + This user option may be overridden if ~:display-action~ is passed + when creating a new prefix with ~transient-define-prefix~. + +*** Accessibility Options +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- User Option: transient-force-single-column :: + + This option controls whether the use of a single column to display + suffixes is enforced. This might be useful for users with low + vision who use large text and might otherwise have to scroll in two + dimensions. + +*** Auxiliary Options +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- User Option: transient-mode-line-format :: + + This option controls whether the transient popup buffer has a + mode-line, separator line, or neither. + + If ~nil~, then the buffer has no mode-line. If the buffer is not + displayed right above the echo area, then this probably is not a + good value. + + If ~line~ (the default) or a natural number, then the buffer has no + mode-line, but a line is drawn in its place. If a number is used, + that specifies the thickness of the line. On termcap frames we + cannot draw lines, so there ~line~ and numbers are synonyms for ~nil~. + + The color of the line is used to indicate if non-suffixes are + allowed and whether they exit the transient. The foreground + color of ~transient-key-noop~ (if non-suffixes are disallowed), + ~transient-key-stay~ (if allowed and transient stays active), or + ~transient-key-exit~ (if allowed and they exit the transient) is + used to draw the line. + + This user option may be overridden if ~:mode-line-format~ is passed + when creating a new prefix with ~transient-define-prefix~. + + Otherwise this can be any mode-line format. See [[info:elisp#Mode + Line Format]], for details. + +- User Option: transient-semantic-coloring :: + + This option controls whether colors are used to indicate the + transient behavior of commands. + + If non-~nil~, then the key binding of each suffix is colorized to + indicate whether it exits the transient state or not. The color of + the prefix is indicated using the line that is drawn when the value + of ~transient-mode-line-format~ is ~line~. + +- User Option: transient-highlight-mismatched-keys :: + + This option controls whether key bindings of infix commands that do + not match the respective command-line argument should be highlighted. + For other infix commands this option has no effect. + + When this option is non-~nil~, the key binding for an infix argument + is highlighted when only a long argument (e.g., ~--verbose~) is + specified but no shorthand (e.g., ~-v~). In the rare case that a + shorthand is specified but the key binding does not match, then it + is highlighted differently. + + Highlighting mismatched key bindings is useful when learning the + arguments of the underlying command-line tool; you wouldn't want to + learn any short-hands that do not actually exist. + + The highlighting is done using one of the faces + ~transient-mismatched-key~ and ~transient-nonstandard-key~. + +- User Option: transient-substitute-key-function :: + + This function is used to modify key bindings. If the value of this + option is ~nil~ (the default), then no substitution is performed. + + This function is called with one argument, the prefix object, and + must return a key binding description, either the existing key + description it finds in the ~key~ slot, or the key description that + replaces the prefix key. It could be used to make other + substitutions, but that is discouraged. + + For example, {{{kbd(=)}}} is hard to reach using my custom keyboard layout, + so I substitute {{{kbd(()}}} for that, which is easy to reach using a layout + optimized for lisp. + + #+BEGIN_SRC emacs-lisp + (setq transient-substitute-key-function + (lambda (obj) + (let ((key (oref obj key))) + (if (string-match "\\`\\(=\\)[a-zA-Z]" key) + (replace-match "(" t t key 1) + key)))) + #+END_SRC + +- User Option: transient-align-variable-pitch :: + + This option controls whether columns are aligned pixel-wise in the + popup buffer. + + If this is non-~nil~, then columns are aligned pixel-wise to support + variable-pitch fonts. Keys are not aligned, so you should use a + fixed-pitch font for the ~transient-key~ face. Other key faces + inherit from that face unless a theme is used that breaks that + relationship. + + This option is intended for users who use a variable-pitch font for + the ~default~ face. + +- User Option: transient-force-fixed-pitch :: + + This option controls whether to force the use of a monospaced font + in popup buffer. Even if you use a proportional font for the + ~default~ face, you might still want to use a monospaced font in + transient's popup buffer. Setting this option to ~t~ causes ~default~ + to be remapped to ~fixed-pitch~ in that buffer. + +*** Developer Options +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +These options are mainly intended for developers. + +- User Option: transient-detect-key-conflicts :: + + This option controls whether key binding conflicts should be + detected at the time the transient is invoked. If so, this results + in an error, which prevents the transient from being used. Because + of that, conflicts are ignored by default. + + Conflicts cannot be determined earlier, i.e., when the transient is + being defined and when new suffixes are being added, because at that + time there can be false-positives. It is actually valid for + multiple suffixes to share a common key binding, provided the + predicates of those suffixes prevent that more than one of them is + enabled at a time. + +- User Option: transient-highlight-higher-levels :: + + This option controls whether suffixes that would not be available by + default are highlighted. + + When non-~nil~ then the descriptions of suffixes are highlighted if + their level is above 4, the default of ~transient-default-level~. + Assuming you have set that variable to 7, this highlights all + suffixes that won't be available to users without them making the + same customization. + +*** Hook Variables +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- Variable: transient-exit-hook :: + + This hook is run after a transient is exited. + +- Variable: transient-setup-buffer-hook :: + + This hook is run when the transient buffer is being setup. + That buffer is current and empty when this hook is runs. + +* Modifying Existing Transients +#+cindex: modifying existing transients + +To an extent, transients can be customized interactively, see +[[*Enabling and Disabling Suffixes]]. This section explains how existing +transients can be further modified non-interactively. Let's begin +with an example: + +#+begin_src emacs-lisp + (transient-append-suffix 'magit-patch-apply "-3" + '("-R" "Apply in reverse" "--reverse")) +#+end_src + +This inserts a new infix argument to toggle the ~--reverse~ argument +after the infix argument that toggles ~-3~ in ~magit-patch-apply~. + +The following functions share a few arguments: + +- {{{var(PREFIX)}}} is a transient prefix command, a symbol. + +- {{{var(SUFFIX)}}} is a transient infix or suffix specification in the same form + as expected by ~transient-define-prefix~. Note that an infix is a + special kind of suffix. Depending on context “suffixes” means + “suffixes (including infixes)” or “non-infix suffixes”. Here it + means the former. See [[*Suffix Specifications]]. + + {{{var(SUFFIX)}}} may also be a group in the same form as expected by + ~transient-define-prefix~. See [[*Group Specifications]]. + +- {{{var(LOC)}}} is a command, a key vector, a key description (a string as + returned by ~key-description~), or a list specifying coordinates (the + last element may also be a command or key). For example ~(1 0 -1)~ + identifies the last suffix (~-1~) of the first subgroup (~0~) of the + second group (~1~). + + If {{{var(LOC)}}} is a list of coordinates, then it can be used to identify a + group, not just an individual suffix command. + + The function ~transient-get-suffix~ can be useful to determine whether + a certain coordination list identifies the suffix or group that you + expect it to identify. In hairy cases it may be necessary to look + at the definition of the transient prefix command. + +These functions operate on the information stored in the +~transient--layout~ property of the {{{var(PREFIX)}}} symbol. Suffix entries in +that tree are not objects but have the form {{{codevar((LEVEL CLASS PLIST))}}}, where +{{{var(PLIST)}}} should set at least ~:key~, ~:description~ and ~:command~. + +- Function: transient-insert-suffix prefix loc suffix &optional keep-other :: +- Function: transient-append-suffix prefix loc suffix &optional keep-other :: + + These functions insert the suffix or group {{{var(SUFFIX)}}} into {{{var(PREFIX)}}} before + or after {{{var(LOC)}}}. + + Conceptually adding a binding to a transient prefix is similar to + adding a binding to a keymap, but this is complicated by the fact + that multiple suffix commands can be bound to the same key, provided + they are never active at the same time, see [[*Predicate Slots]]. + + Unfortunately both false-positives and false-negatives are possible. + To deal with the former use non-~nil~ {{{var(KEEP-OTHER.)}}} The symbol ~always~ + prevents the removal of a false-positive in some cases where other + non-~nil~ values would fail. To deal with false-negatives remove the + conflicting binding separately, using ~transient-remove-suffix~. + +- Function: transient-replace-suffix prefix loc suffix :: + + This function replaces the suffix or group at {{{var(LOC)}}} in {{{var(PREFIX)}}} with + suffix or group {{{var(SUFFIX)}}}. + +- Function: transient-remove-suffix prefix loc :: + + This function removes the suffix or group at {{{var(LOC)}}} in {{{var(PREFIX)}}}. + +- Function: transient-get-suffix prefix loc :: + + This function returns the suffix or group at {{{var(LOC)}}} in {{{var(PREFIX)}}}. The + returned value has the form mentioned above. + +- Function: transient-suffix-put prefix loc prop value :: + + This function edits the suffix or group at {{{var(LOC)}}} in {{{var(PREFIX)}}}, by setting + the {{{var(PROP)}}} of its plist to {{{var(VALUE)}}}. + +Most of these functions do not signal an error if they cannot perform +the requested modification. The functions that insert new suffixes +show a warning if {{{var(LOC)}}} cannot be found in {{{var(PREFIX,)}}} without signaling an +error. The reason for doing it like this is that establishing a key +binding (and that is what we essentially are trying to do here) should +not prevent the rest of the configuration from loading. Among these +functions only ~transient-get-suffix~ and ~transient-suffix-put~ may +signal an error. + +* Defining New Commands +** Technical Introduction + +Taking inspiration from prefix keys and prefix arguments, Transient +implements a similar abstraction involving a prefix command, infix +arguments and suffix commands. + +When the user calls a transient prefix command, a transient +(temporary) keymap is activated, which binds the transient's infix and +suffix commands, and functions that control the transient state are +added to ~pre-command-hook~ and ~post-command-hook~. The available suffix +and infix commands and their state are shown in a popup buffer until +the transient state is exited by invoking a suffix command. + +Calling an infix command causes its value to be changed. How that is +done depends on the type of the infix command. The simplest case is +an infix command that represents a command-line argument that does not +take a value. Invoking such an infix command causes the switch to be +toggled on or off. More complex infix commands may read a value from +the user, using the minibuffer. + +Calling a suffix command usually causes the transient to be exited; +the transient keymaps and hook functions are removed, the popup buffer +no longer shows information about the (no longer bound) suffix +commands, the values of some public global variables are set, while +some internal global variables are unset, and finally the command is +actually called. Suffix commands can also be configured to not exit +the transient. + +A suffix command can, but does not have to, use the infix arguments in +much the same way any command can choose to use or ignore the prefix +arguments. For a suffix command that was invoked from a transient, the +variable ~transient-current-suffixes~ and the function ~transient-args~ +serve about the same purpose as the variables ~prefix-arg~ and +~current-prefix-arg~ do for any command that was called after the prefix +arguments have been set using a command such as ~universal-argument~. + +#+cindex: command dispatchers +Transient can be used to implement simple “command dispatchers”. The +main benefit then is that the user can see all the available commands +in a popup buffer, which can be thought of as a “menu”. That is +useful by itself because it frees the user from having to remember all +the keys that are valid after a certain prefix key or command. +Magit's ~magit-dispatch~ (on {{{kbd(C-x M-g)}}}) command is an example of using +Transient to merely implement a command dispatcher. + +In addition to that, Transient also allows users to interactively pass +arguments to commands. These arguments can be much more complex than +what is reasonable when using prefix arguments. There is a limit to +how many aspects of a command can be controlled using prefix +arguments. Furthermore, what a certain prefix argument means for +different commands can be completely different, and users have to read +documentation to learn and then commit to memory what a certain prefix +argument means to a certain command. + +Transient suffix commands, on the other hand, can accept dozens of +different arguments without the user having to remember anything. +When using Transient, one can call a command with arguments that are +just as complex as when calling the same function non-interactively +from Lisp. + +Invoking a transient suffix command with arguments is similar to +invoking a command in a shell with command-line completion and history +enabled. One benefit of the Transient interface is that it remembers +history not only on a global level (“this command was invoked using +these arguments, and previously it was invoked using those other +arguments”), but also remembers the values of individual arguments +independently. See [[*Using History]]. + +After a transient prefix command is invoked, {{{kbdvar(C-h <KEY>)}}} can be used to +show the documentation for the infix or suffix command that {{{kbdvar(<KEY>)}}} is +bound to (see [[*Getting Help for Suffix Commands]]), and infixes and +suffixes can be removed from the transient using {{{kbdvar(C-x l <KEY>)}}}. Infixes +and suffixes that are disabled by default can be enabled the same way. +See [[*Enabling and Disabling Suffixes]]. + +Transient ships with support for a few different types of specialized +infix commands. A command that sets a command line option, for example, +has different needs than a command that merely toggles a boolean flag. +Additionally, Transient provides abstractions for defining new types, +which the author of Transient did not anticipate (or didn't get around +to implementing yet). + +Note that suffix commands also support regular prefix arguments. A +suffix command may even be called with both infix and prefix arguments +at the same time. If you invoke a command as a suffix of a transient +prefix command, but also want to pass prefix arguments to it, then +first invoke the prefix command, and only after doing that invoke the +prefix arguments, before finally invoking the suffix command. If you +instead began by providing the prefix arguments, then those would +apply to the prefix command, not the suffix command. Likewise, if you +want to change infix arguments before invoking a suffix command with +prefix arguments, then change the infix arguments before invoking the +prefix arguments. In other words, regular prefix arguments always +apply to the next command, and since transient prefix, infix and +suffix commands are just regular commands, the same applies to them. +(Regular prefix keys behave differently because they are not commands +at all, instead they are just incomplete key sequences, and those +cannot be interrupted with prefix commands.) + +** Defining Transients + +A transient consists of a prefix command and at least one suffix +command, though usually a transient has several infix and suffix +commands. The below macro defines the transient prefix command *and* +binds the transient's infix and suffix commands. In other words, it +defines the complete transient, not just the transient prefix command +that is used to invoke that transient. + +- Macro: transient-define-prefix name arglist [docstring] [keyword value]... group... [body...] :: + + This macro defines {{{var(NAME)}}} as a transient prefix command and binds the + transient's infix and suffix commands. + + {{{var(ARGLIST)}}} are the arguments that the prefix command takes. + {{{var(DOCSTRING)}}} is the documentation string and is optional. + + These arguments can optionally be followed by keyword-value pairs. + Each key has to be a keyword symbol, either ~:class~ or a keyword + argument supported by the constructor of that class. The + ~transient-prefix~ class is used if the class is not specified + explicitly. + + {{{var(GROUP)}}}s add key bindings for infix and suffix commands and specify + how these bindings are presented in the popup buffer. At least one + {{{var(GROUP)}}} has to be specified. See [[*Binding Suffix and Infix Commands]]. + + The {{{var(BODY)}}} is optional. If it is omitted, then {{{var(ARGLIST)}}} is ignored and + the function definition becomes: + + #+BEGIN_SRC emacs-lisp + (lambda () + (interactive) + (transient-setup 'NAME)) + #+END_SRC + + If {{{var(BODY)}}} is specified, then it must begin with an ~interactive~ form + that matches {{{var(ARGLIST)}}}, and it must call ~transient-setup~. It may, + however, call that function only when some condition is satisfied. + + #+cindex: scope of a transient + All transients have a (possibly ~nil~) value, which is exported when + suffix commands are called, so that they can consume that value. + For some transients it might be necessary to have a sort of + secondary value, called a “scope”. Such a scope would usually be + set in the command's ~interactive~ form and has to be passed to the + setup function: + + #+BEGIN_SRC emacs-lisp + (transient-setup 'NAME nil nil :scope SCOPE) + #+END_SRC + + For example, the scope of the ~magit-branch-configure~ transient is + the branch whose variables are being configured. + +** Binding Suffix and Infix Commands + +The macro ~transient-define-prefix~ is used to define a transient. +This defines the actual transient prefix command (see [[*Defining +Transients]]) and adds the transient's infix and suffix bindings, as +described below. + +Users and third-party packages can add additional bindings using +functions such as ~transient-insert-suffix~ (see [[*Modifying Existing +Transients]]). These functions take a “suffix specification” as one of +their arguments, which has the same form as the specifications used in +~transient-define-prefix~. + +*** Group Specifications +#+cindex: group specifications + +The suffix and infix commands of a transient are organized in groups. +The grouping controls how the descriptions of the suffixes are +outlined visually but also makes it possible to set certain properties +for a set of suffixes. + +Several group classes exist, some of which organize suffixes in +subgroups. In most cases the class does not have to be specified +explicitly, but see [[*Group Classes]]. + +Groups are specified in the call to ~transient-define-prefix~, using +vectors. Because groups are represented using vectors, we cannot use +square brackets to indicate an optional element and instead use curly +brackets to do the latter. + +Group specifications then have this form: + +#+begin_src emacs-lisp + [{LEVEL} {DESCRIPTION} {KEYWORD VALUE}... ELEMENT...] +#+end_src + +The {{{var(LEVEL)}}} is optional and defaults to 4. See [[*Enabling and Disabling +Suffixes]]. + +The {{{var(DESCRIPTION)}}} is optional. If present, it is used as the heading of +the group. + +The {{{var(KEYWORD)}}}-{{{var(VALUE)}}} pairs are optional. Each keyword has to be a +keyword symbol, either ~:class~ or a keyword argument supported by the +constructor of that class. + +- One of these keywords, ~:description~, is equivalent to specifying + {{{var(DESCRIPTION)}}} at the very beginning of the vector. The recommendation + is to use ~:description~ if some other keyword is also used, for + consistency, or {{{var(DESCRIPTION)}}} otherwise, because it looks better. + +- Likewise ~:level~ is equivalent to {{{var(LEVEL)}}}. + +- Other important keywords include the ~:if...~ and ~:inapt-if...~ + keywords. These keywords control whether the group is available + in a certain situation. + + For example, one group of the ~magit-rebase~ transient uses ~:if + magit-rebase-in-progress-p~, which contains the suffixes that are + useful while rebase is already in progress; and another that uses + ~:if-not magit-rebase-in-progress-p~, which contains the suffixes that + initiate a rebase. + + These predicates can also be used on individual suffixes and are + only documented once, see [[*Predicate Slots]]. + +- The value of ~:hide~, if non-~nil~, is a predicate that controls + whether the group is hidden by default. The key bindings for + suffixes of a hidden group should all use the same prefix key. + Pressing that prefix key should temporarily show the group and its + suffixes, which assumes that a predicate like this is used: + + #+BEGIN_SRC emacs-lisp + (lambda () + (eq (car transient--redisplay-key) + ?\C-c)) ; the prefix key shared by all bindings + #+END_SRC + +- The value of ~:setup-children~, if non-~nil~, is a function that takes + one argument, a potentially list of children, and must return a list + of children or an empty list. This can either be used to somehow + transform the group's children that were defined the normal way, or + to dynamically create the children from scratch. + + The returned children must have the same form as stored in the + prefix's ~transient--layout~ property, but it is often more convenient + to use the same form as understood by ~transient-define-prefix~, + described below. If you use the latter approach, you can use the + ~transient-parse-suffixes~ and ~transient-parse-suffix~ functions to + transform them from the convenient to the expected form. Depending + on the used group class, ~transient-parse-suffixes~'s SUFFIXES must be + a list of group vectors (for ~transient-columns~) or a list of suffix + lists (for all other group classes). + + If you explicitly specify children and then transform them using + ~:setup-children~, then the class of the group is determined as usual, + based on explicitly specified children. + + If you do not explicitly specify children and thus rely solely on + ~:setup-children~, then you must specify the class using ~:class~. + For backward compatibility, if you fail to do so, ~transient-column~ + is used and a warning is displayed. This warning will eventually + be replaced with an error. + + #+BEGIN_SRC emacs-lisp + (transient-define-prefix my-finder-by-keyword () + "Select a keyword and list matching packages." + ;; The real `finder-by-keyword' is more convenient + ;; of course, but that is not the point here. + [:class transient-columns + :setup-children + (lambda (_) + (transient-parse-suffixes + 'my-finder-by-keyword + (let ((char (1- ?A))) + (mapcar ; a list ... + (lambda (partition) + (vconcat ; of group vectors ... + (mapcar (lambda (elt) + (let ((keyword (symbol-name (car elt)))) + ; ... where each suffix is a list + (list (format "%c" (cl-incf char)) + keyword + (lambda () + (interactive) + (finder-list-matches keyword))))) + partition))) + (seq-partition finder-known-keywords 7)))))]) + #+END_SRC + +- The boolean ~:pad-keys~ argument controls whether keys of all suffixes + contained in a group are right padded, effectively aligning the + descriptions. + +- If a keyword argument accepts a function as value, you an use a + ~lambda~ expression. As a special case, the ~##~ macro (which returns a + ~lambda~ expression and is implemented in the ~llama~ package) is also + supported. Inside group specifications, the use of ~##~ is not + supported anywhere but directly following a keyword symbol. + +The {{{var(ELEMENT)}}}s are either all subgroups, or all suffixes and strings. +(At least currently no group type exists that would allow mixing +subgroups with commands at the same level, though in principle there +is nothing that prevents that.) + +If the {{{var(ELEMENT)}}}s are not subgroups, then they can be a mixture of +lists, which specify commands, and strings. Strings are inserted +verbatim into the buffer. The empty string can be used to insert gaps +between suffixes, which is particularly useful if the suffixes are +outlined as a table. + +Inside group specifications, including inside contained suffix +specifications, nothing has to be quoted and quoting anyway is +invalid. The value following a keyword, can be explicitly unquoted +using ~,~. This feature is experimental and should be avoided. + +The form of suffix specifications is documented in the next node. + +*** Suffix Specifications +#+cindex: suffix specifications + +A transient's suffix and infix commands are bound when the transient +prefix command is defined using ~transient-define-prefix~, see +[[*Defining Transients]]. The commands are organized into groups, see +[[*Group Specifications]]. Here we describe the form used to bind an +individual suffix command. + +The same form is also used when later binding additional commands +using functions such as ~transient-insert-suffix~, see [[*Modifying +Existing Transients]]. + +Note that an infix is a special kind of suffix. Depending on context +“suffixes” means “suffixes (including infixes)” or “non-infix +suffixes”. Here it means the former. + +Suffix specifications have this form: + +#+begin_src emacs-lisp + ([LEVEL] [KEY [DESCRIPTION]] COMMAND|ARGUMENT [KEYWORD VALUE]...) +#+end_src + +{{{var(LEVEL)}}}, {{{var(KEY)}}} and {{{var(DESCRIPTION)}}} can also be specified using the {{{var(KEYWORD)}}}s +~:level~, ~:key~ and ~:description~. If the object that is associated with +{{{var(COMMAND)}}} sets these properties, then they do not have to be specified +here. You can however specify them here anyway, possibly overriding +the object's values just for the binding inside this transient. + +- {{{var(LEVEL)}}} is the suffix level, an integer between 1 and 7. See + [[*Enabling and Disabling Suffixes]]. + +- {{{var(KEY)}}} is the key binding, either a vector or key description string. + +- {{{var(DESCRIPTION)}}} is the description, either a string or a function that + takes zero or one arguments (the suffix object) and returns a string. + The function should be a lambda expression to avoid ambiguity. In + some cases a symbol that is bound as a function would also work but + to be safe you should use ~:description~ in that case. + +The next element is either a command or an argument. This is the only +argument that is mandatory in all cases. + +- {{{var(COMMAND)}}} should be a symbol that is bound as a function, which has + to be defined or at least autoloaded as a command by the time the + containing prefix command is invoked. + + Any command will do; it does not need to have an object associated + with it (as would be the case if ~transient-define-suffix~ or + ~transient-define-infix~ were used to define it). + + COMMAND can also be a ~lambda~ expression. + + As mentioned above, the object that is associated with a command can + be used to set the default for certain values that otherwise have to + be set in the suffix specification. Therefore if there is no object, + then you have to make sure to specify the {{{var(KEY)}}} and the {{{var(DESCRIPTION)}}}. + + As a special case, if you want to add a command that might be neither + defined nor autoloaded, you can use a workaround like: + + #+BEGIN_SRC emacs-lisp + (transient-insert-suffix 'some-prefix "k" + '("!" "Ceci n'est pas une commande" no-command + :if (lambda () (featurep 'no-library)))) + #+END_SRC + + Instead of ~featurep~ you could also use ~require~ with a non-~nil~ value + for {{{var(NOERROR)}}}. + +- The mandatory argument can also be a command-line argument, a + string. In that case an anonymous command is defined and bound. + + Instead of a string, this can also be a list of two strings, in + which case the first string is used as the short argument (which can + also be specified using ~:shortarg~) and the second as the long argument + (which can also be specified using ~:argument~). + + Only the long argument is displayed in the popup buffer. See + ~transient-detect-key-conflicts~ for how the short argument may be + used. + + Unless the class is specified explicitly, the appropriate class is + guessed based on the long argument. If the argument ends with === + (e.g., =--format==) then ~transient-option~ is used, otherwise + ~transient-switch~. + +Finally, details can be specified using optional {{{var(KEYWORD)}}}-{{{var(VALUE)}}} pairs. +Each keyword has to be a keyword symbol, either ~:class~ or a keyword +argument supported by the constructor of that class. See [[*Suffix +Slots]]. + +If a keyword argument accepts a function as value, you an use a ~lambda~ +expression. As a special case, the ~##~ macro (which returns a ~lambda~ +expression and is implemented in the ~llama~ package) is also supported. +Inside suffix bindings, the use of ~##~ is not supported anywhere but +directly following a keyword symbol. + +** Defining Suffix and Infix Commands +#+cindex: defining suffix commands +#+cindex: defining infix commands + +Note that an infix is a special kind of suffix. Depending on context +“suffixes” means “suffixes (including infixes)” or “non-infix +suffixes”. + +- Macro: transient-define-suffix name arglist [docstring] [keyword value]... body... :: + + This macro defines {{{var(NAME)}}} as a transient suffix command. + + {{{var(ARGLIST)}}} are the arguments that the command takes. + {{{var(DOCSTRING)}}} is the documentation string and is optional. + + These arguments can optionally be followed by keyword-value pairs. + Each keyword has to be a keyword symbol, either ~:class~ or a keyword + argument supported by the constructor of that class. The + ~transient-suffix~ class is used if the class is not specified + explicitly. + + The {{{var(BODY)}}} must begin with an ~interactive~ form that matches {{{var(ARGLIST)}}}. + The infix arguments are usually accessed by using ~transient-args~ + inside ~interactive~. + +- Macro: transient-define-infix name arglist [docstring] [keyword value]... :: + + This macro defines {{{var(NAME)}}} as a transient infix command. + + {{{var(ARGLIST)}}} is always ignored (but mandatory never-the-less) and + reserved for future use. {{{var(DOCSTRING)}}} is the documentation string and + is optional. + + At least one key-value pair is required. All transient infix + commands are ~equal~ to each other (but not ~eq~). It is meaningless + to define an infix command, without providing at least one keyword + argument (usually ~:argument~ or ~:variable~, depending on the class). + The suffix class defaults to ~transient-switch~ and can be set using + the ~:class~ keyword. + + The function definition is always: + + #+BEGIN_SRC emacs-lisp + (lambda () + (interactive) + (let ((obj (transient-suffix-object))) + (transient-infix-set obj (transient-infix-read obj))) + (transient--show)) + #+END_SRC + + ~transient-infix-read~ and ~transient-infix-set~ are generic functions. + Different infix commands behave differently because the concrete + methods are different for different infix command classes. In rare + cases the above command function might not be suitable, even if you + define your own infix command class. In that case you have to use + ~transient-define-suffix~ to define the infix command and use ~t~ as the + value of the ~:transient~ keyword. + +- Macro: transient-define-argument name arglist [docstring] [keyword value]... :: + + This macro defines {{{var(NAME)}}} as a transient infix command. + + This is an alias for ~transient-define-infix~. Only use this alias + to define an infix command that actually sets an infix argument. + To define an infix command that, for example, sets a variable, use + ~transient-define-infix~ instead. + +** Using Infix Arguments + +The functions and the variables described below allow suffix commands +to access the value of the transient from which they were invoked; +which is the value of its infix arguments. These variables are set +when the user invokes a suffix command that exits the transient, but +before actually calling the command. + +When returning to the command-loop after calling the suffix command, +the arguments are reset to ~nil~ (which causes the function to return +~nil~ too). + +Like for Emacs's prefix arguments, it is advisable, but not mandatory, +to access the infix arguments inside the command's ~interactive~ form. +The preferred way of doing that is to call the ~transient-args~ +function, which for infix arguments serves about the same purpose as +~prefix-arg~ serves for prefix arguments. + +- Function: transient-args prefix :: + + This function returns the value of the transient prefix command + {{{var(PREFIX)}}}. + + If the current command was invoked from the transient prefix command + {{{var(PREFIX)}}}, then it returns the active infix arguments. If the current + command was not invoked from {{{var(PREFIX)}}}, then it returns the set, saved + or default value for {{{var(PREFIX)}}}. + +- Function: transient-get-value :: + + This function returns the value of the current prefix. + + This is mostly intended for internal use, but may also be of use + in ~transient-set-value~ and ~transient-save-value~ methods. Unlike + ~transient-args~, this does not include the values of suffixes whose + ~unsavable~ slot is non-~nil~. + +- Function: transient-arg-value arg args :: + + This function returns the value of {{{var(ARG)}}} as it appears in {{{var(ARGS)}}}. + + For a switch a boolean is returned. For an option the value is + returned as a string, using the empty string for the empty value, + or ~nil~ if the option does not appear in {{{var(ARGS)}}}. + +- Function: transient-suffixes prefix :: + + This function returns the suffixes of the transient prefix command + {{{var(PREFIX)}}}. This is a list of objects. This function should only be + used if you need the objects (as opposed to just their values) and + if the current command is not being invoked from {{{var(PREFIX)}}}. + +** Using Prefix Scope + +Some transients have a sort of secondary value, called a scope. A +prefix's scope can be accessed using ~transient-scope~; similar to how +its value can be accessed using ~transient-args~. + +- Function: transient-scope prefixes classes :: + + This function returns the scope of the active or current transient + prefix command. + + If optional PREFIXES and CLASSES are both nil, return the scope of + the prefix currently being setup, making this variation useful, e.g., + in ~:if*~ predicates. If no prefix is being setup, but the current + command was invoked from some prefix, then return the scope of that. + + If PREFIXES is non-nil, it must be a prefix command or a list of such + commands. If CLASSES is non-nil, it must be a prefix class or a list + of such classes. When this function is called from the body or the + ~interactive~ form of a suffix command, PREFIXES and/or CLASSES should + be non-nil. If either is non-nil, try the following in order: + + - If the current suffix command was invoked from a prefix, which + appears in PREFIXES, return the scope of that prefix. + + - If the current suffix command was invoked from a prefix, and its + class derives from one of the CLASSES, return the scope of that + prefix. + + - If a prefix is being setup and it appears in PREFIXES, return its + scope. + + - If a prefix is being setup and its class derives from one of the + CLASSES, return its scope. + + - Finally try to return the default scope of the first command in + PREFIXES. This only works if that slot is set in the respective + class definition or using its `transient-init-scope' method. + + If no prefix matches, return nil. + +** Current Suffix Command + +- Function: transient-suffix-object command :: + + This function returns the object associated with the current suffix + command. + + Each suffix commands is associated with an object, which holds + additional information about the suffix, such as its value (in + the case of an infix command, which is a kind of suffix command). + + This function is intended to be called by infix commands, which + are usually aliases of ~transient--default-infix-command~, which + is defined like this: + + #+begin_src emacs-lisp + (defun transient--default-infix-command () + (interactive) + (let ((obj (transient-suffix-object))) + (transient-infix-set obj (transient-infix-read obj))) + (transient--show)) + #+end_src + + (User input is read outside of ~interactive~ to prevent the + command from being added to ~command-history~.) + + Such commands need to be able to access their associated object + to guide how ~transient-infix-read~ reads the new value and to + store the read value. Other suffix commands (including non-infix + commands) may also need the object to guide their behavior. + + This function attempts to return the object associated with the + current suffix command even if the suffix command was not invoked + from a transient. (For some suffix command that is a valid thing + to do, for others it is not.) In that case ~nil~ may be returned, + if the command was not defined using one of the macros intended + to define such commands. + + The optional argument COMMAND is intended for internal use. If + you are contemplating using it in your own code, then you should + probably use this instead: + + #+begin_src emacs-lisp + (get COMMAND 'transient--suffix) + #+end_src + +- Variable: transient-current-suffixes :: + + The suffixes of the transient from which this suffix command was + invoked. This is a list of objects. Usually it is sufficient to + instead use the function ~transient-args~, which returns a list of + values. In complex cases it might be necessary to use this variable + instead, i.e., if you need access to information beside the value. + +** Current Prefix Command + +- Function: transient-prefix-object :: + + This function returns the current prefix as an object. + + While a transient is being setup or refreshed (which involves + preparing its suffixes) the variable ~transient--prefix~ can be + used to access the prefix object. Thus this is what has to be + used in suffix methods such as ~transient-format-description~, + and in object-specific functions that are stored in suffix slots + such as ~description~. + + When a suffix command is invoked (i.e., in its ~interactive~ form + and function body) then the variable ~transient-current-prefix~ + has to be used instead. + + Two distinct variables are needed, because any prefix may itself + be used as a suffix of another prefix, and such sub-prefixes have + to be able to tell themselves apart from the prefix they were + invoked from. + + Regular suffix commands, which are not prefixes, do not have to + concern themselves with this distinction, so they can use this + function instead. In the context of a plain suffix, it always + returns the value of the appropriate variable. + +- Variable: transient-current-prefix :: + + The transient from which this suffix command was invoked. The value + is a ~transient-prefix~ object, which holds information associated + with the transient prefix command. + +- Variable: transient-current-command :: + + The transient from which this suffix command was invoked. The value + is a symbol, the transient prefix command. + +- Function: transient-active-prefix &optional prefixes :: + + This function returns the active transient object. It returns ~nil~ + if there is no active transient, if the transient buffer isn't + shown, and while the active transient is suspended (e.g., while the + minibuffer is in use). + + Unlike ~transient-current-prefix~, which is only ever non-~nil~ in code + that is run directly by a command that is invoked while a transient + is current, this function is also suitable for use in asynchronous + code, such as timers and callbacks (this function's main use-case). + + If optional PREFIXES is non-~nil~, it must be a prefix command symbol + or a list of symbols, in which case the active transient object is + only returned if it matches one of the PREFIXES. + +** Transient State +#+cindex: transient state + +Invoking a transient prefix command “activates” the respective +transient, i.e., it puts a transient keymap into effect, which binds +the transient's infix and suffix commands. + +The default behavior while a transient is active is as follows: + +- Invoking an infix command does not affect the transient state; the + transient remains active. + +- Invoking a (non-infix) suffix command “deactivates” the transient + state by removing the transient keymap and performing some + additional cleanup. + +- Invoking a command that is bound in a keymap other than the + transient keymap is disallowed and trying to do so results in a + warning. This does not “deactivate” the transient. + +The behavior can be changed for all suffixes of a particular prefix +and/or for individual suffixes. The values should nearly always be +booleans, but certain functions, called “pre-commands”, can also be +used. These functions are named ~transient--do-VERB~, and the symbol +~VERB~ can be used as a shorthand. + +A boolean is interpreted as answering the question "does the +transient stay active, when this command is invoked?" ~t~ means that +the transient stays active, while ~nil~ means that invoking the command +exits the transient. + +Note that when the suffix is a “sub-prefix”, invoking that command +always activates that sub-prefix, causing the outer prefix to no +longer be active and displayed. Here ~t~ means that when you exit the +inner prefix, then the outer prefix becomes active again, while ~nil~ +means that all outer prefixes are exited at once. + +- The behavior for non-suffixes can be set for a particular prefix, + by the prefix's ~transient-non-suffix~ slot to a boolean, a suitable + pre-command function, or a shorthand for such a function. See + [[*Pre-commands for Non-Suffixes]]. + +- The common behavior for the suffixes of a particular prefix can be + set using the prefix's ~transient-suffixes~ slot. + + The value specified in this slot does *not* affect infixes. Because + it affects both regular suffixes as well as sub-prefixes, which + have different needs, it is best to avoid explicitly specifying a + function. + +- The behavior of an individual suffix can be changed using its + ~transient~ slot. While it is usually best to use a boolean, for this + slot it can occasionally make sense to specify a function explicitly. + + Note that this slot can be set when defining a suffix command using + ~transient-define-suffix~ and/or in the definition of the prefix. If + set in both places, then the latter takes precedence, as usual. + +The available pre-command functions are documented in the following +sub-sections. They are called by ~transient--pre-command~, a function +on ~pre-command-hook~, and the value that they return determines whether +the transient is exited. To do so the value of one of the constants +~transient--exit~ or ~transient--stay~ is used (that way we don't have to +remember if ~t~ means “exit” or “stay”). + +Additionally, these functions may change the value of ~this-command~ +(which explains why they have to be called using ~pre-command-hook~), +call ~transient-export~, ~transient--stack-zap~ or ~transient--stack-push~; +and set the values of ~transient--exitp~, ~transient--helpp~ or +~transient--editp~. + +For completeness sake, some notes about complications: + +- The transient-ness of certain built-in suffix commands is specified + using ~transient-predicate-map~. This is a special keymap, which + binds commands to pre-commands (as opposed to keys to commands) and + takes precedence over the prefix's ~transient-suffix~ slot, but not + the suffix's ~transient~ slot. + +- While a sub-prefix is active we nearly always want {{{kbd(C-g)}}} to take the + user back to the “super-prefix”, even when the other suffixes don't + do that. However, in rare cases this may not be desirable, in which + case ~replace~ can be used as the value of the sub-prefix's ~transient~ + slot. + +*** Pre-commands for Infixes +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +The default for infixes is ~transient--do-stay~. This is also the only +function that makes sense for infixes, which is why this predicate is +used even if the value of the prefix's ~transient-suffix~ slot is ~t~. In +extremely rare cases, one might want to use something else, which can +be done by setting the infix's ~transient~ slot directly. + +- Function: transient--do-stay :: + + Call the command without exporting variables and stay transient. + +*** Pre-commands for Suffixes +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +By default, invoking a suffix causes the transient to be exited. + +The behavior for an individual suffix command can be changed by +setting its ~transient~ slot to a boolean (which is highly recommended), +or to one of the following pre-commands. + +- Function: transient--do-exit :: + + Call the command after exporting variables and exit the transient. + +- Function: transient--do-return :: + + Call the command after exporting variables and return to the parent + prefix. If there is no parent prefix, then call ~transient--do-exit~. + +- Function: transient--do-call :: + + Call the command after exporting variables and stay transient. + +The following pre-commands are only suitable for sub-prefixes. It is +not necessary to explicitly use these predicates because the correct +predicate is automatically picked based on the value of the ~transient~ +slot for the sub-prefix itself. + +- Function: transient--do-recurse :: + + Call the transient prefix command, preparing for return to outer + transient. + + Whether we actually return to the parent transient is ultimately + under the control of each invoked suffix. The difference between + this pre-command and ~transient--do-stack~ is that it changes the + value of the ~transient-suffix~ slot to ~t~. + + If there is no parent transient, then only call this command and + skip the second step. + +- Function: transient--do-stack :: + + Call the transient prefix command, stacking the active transient. + Push the active transient to the transient stack. + + Unless ~transient--do-recurse~ is explicitly used, this pre-command + is automatically used for suffixes that are prefixes themselves, + i.e., for sub-prefixes. + +- Function: transient--do-replace :: + + Call the transient prefix command, replacing the active transient. + Do not push the active transient to the transient stack. + + Unless ~transient--do-recurse~ is explicitly used, this pre-command + is automatically used for suffixes that are prefixes themselves, + i.e., for sub-prefixes. + +- Function: transient--do-suspend :: + + Suspend the active transient, saving the transient stack. + + This is used by the command ~transient-suspend~ and optionally also by + “external events” such as ~handle-switch-frame~. Such bindings should + be added to ~transient-predicate-map~. + +*** Pre-commands for Non-Suffixes +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +By default, non-suffixes (commands that are bound in other keymaps +beside the transient keymap) cannot be invoked. Trying to invoke +such a command results in a warning and the transient stays active. + +If you want a different behavior, then set the ~transient-non-suffix~ +slot of the transient prefix command. The value should be a boolean, +answering the question, "is it allowed to invoke non-suffix commands?, +a pre-command function, or a shorthand for such a function. + +If the value is ~t~, then non-suffixes can be invoked, when it is ~nil~ +(the default) then they cannot be invoked. + +The only other recommended value is ~leave~. If that is used, then +non-suffixes can be invoked, but if one is invoked, then that exits +the transient. + +- Function: transient--do-warn :: + + Call ~transient-undefined~ and stay transient. + +- Function: transient--do-stay :: + + Call the command without exporting variables and stay transient. + +- Function: transient--do-leave :: + + Call the command without exporting variables and exit the transient. + +# transient--do-noop intentionally left undocumented. + +*** Special Pre-Commands +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- Function: transient--do-quit-one :: + + If active, quit help or edit mode, else exit the active transient. + + This is used when the user pressed {{{kbd(C-g)}}}. + +- Function: transient--do-quit-all :: + + Exit all transients without saving the transient stack. + + This is used when the user pressed {{{kbd(C-q)}}}. + +- Function: transient--do-suspend :: + + Suspend the active transient, saving the transient stack. + + This is used when the user pressed {{{kbd(C-z)}}}. + +* Classes and Methods +#+cindex: classes and methods + +Transient uses classes and generic functions to make it possible to +define new types of suffix and prefix commands, which are similar to +existing types, but behave differently in some respects. + +Every prefix, infix and suffix command is associated with an object, +which holds information, which controls certain aspects of its +behavior. This happens in two ways. + +- Associating a command with a certain class gives the command a type. + This makes it possible to use generic functions to do certain things + that have to be done differently depending on what type of command + it acts on. + + That in turn makes it possible for third-parties to add new types + without having to convince the maintainer of Transient, that that + new type is important enough to justify adding a special case to a + dozen or so functions. + +- Associating a command with an object makes it possible to easily + store information that is specific to that particular command. + + Two commands may have the same type, but obviously their key + bindings and descriptions still have to be different, for example. + + The values of some slots are functions. The ~reader~ slot for example + holds a function that is used to read a new value for an infix + command. The values of such slots are regular functions. + + Generic functions are used when a function should do something + different based on the type of the command, i.e., when all commands + of a certain type should behave the same way but different from the + behavior for other types. Object slots that hold a regular function + as value are used when the task that they perform is likely to + differ even between different commands of the same type. + +** Group Classes + +The type of a group can be specified using the ~:class~ property at the +beginning of the class specification, e.g., ~[:class transient-columns +...]~ in a call to ~transient-define-prefix~. + +- The abstract ~transient-child~ class is the base class of both + ~transient-group~ (and therefore all groups) as well as of + ~transient-suffix~ (and therefore all suffix and infix commands). + + This class exists because the elements (or “children”) of certain + groups can be other groups instead of suffix and infix commands. + +- The abstract ~transient-group~ class is the superclass of all other + group classes. + +- The ~transient-column~ class is the simplest group. + + This is the default “flat” group. If the class is not specified + explicitly and the first element is not a vector (i.e., not a group), + then this class is used. + + This class displays each element on a separate line. + +- The ~transient-row~ class displays all elements on a single line. + +- The ~transient-columns~ class displays commands organized in columns. + + Direct elements have to be groups whose elements have to be commands + or strings. Each subgroup represents a column. This class takes + care of inserting the subgroups' elements. + + This is the default “nested” group. If the class is not specified + explicitly and the first element is a vector (i.e., a group), then + this class is used. + +- The ~transient-subgroups~ class wraps other groups. + + Direct elements have to be groups whose elements have to be commands + or strings. This group inserts an empty line between subgroups. + The subgroups themselves are responsible for displaying their + elements. + +** Group Methods + +- Function: transient-setup-children group children :: + + This generic function can be used to setup the children or a group. + + The default implementation usually just returns the children + unchanged, but if the ~setup-children~ slot of {{{var(GROUP)}}} is non-~nil~, then + it calls that function with {{{var(CHILDREN)}}} as the only argument and + returns the value. + + The children are given as a (potentially empty) list consisting of + either group or suffix specifications. These functions can make + arbitrary changes to the children including constructing new + children from scratch. + +- Function: transient--insert-group group :: + + This generic function formats the group and its elements and inserts + the result into the current buffer, which is a temporary buffer. + The contents of that buffer are later inserted into the popup buffer. + + Functions that are called by this function may need to operate in + the buffer from which the transient was called. To do so they can + temporarily make the ~transient--shadowed-buffer~ the current buffer. + +** Prefix Classes + +Transient itself provides a single class for prefix commands, +~transient-prefix~, but package authors may wish to define specialized +classes. Doing so makes it possible to change the behavior of the set +of prefix commands that use that class, by implementing specialized +methods for certain generic functions (see [[* Prefix Methods]]). + +A transient prefix command's object is stored in the ~transient--prefix~ +property of the command symbol. While a transient is active, a clone +of that object is stored in the variable ~transient--prefix~. A clone +is used because some changes that are made to the active transient's +object should not affect later invocations. + +** Suffix Classes + +- All suffix and infix classes derive from ~transient-suffix~, which in + turn derives from ~transient-child~, from which ~transient-group~ also + derives (see [[*Group Classes]]). + +- All infix classes derive from the abstract ~transient-infix~ class, + which in turn derives from the ~transient-suffix~ class. + + Infixes are a special type of suffixes. The primary difference is + that infixes always use the ~transient--do-stay~ pre-command, while + non-infix suffixes use a variety of pre-commands (see [[*Transient + State]]). Doing that is most easily achieved by using this class, + though theoretically it would be possible to define an infix class + that does not do so. If you do that then you get to implement many + methods. + + Also, infixes and non-infix suffixes are usually defined using + different macros (see [[*Defining Suffix and Infix Commands]]). + +- Classes used for infix commands that represent arguments should + be derived from the abstract ~transient-argument~ class. + +- The ~transient-switch~ class (or a derived class) is used for infix + arguments that represent command-line switches (arguments that do + not take a value). + +- The ~transient-option~ class (or a derived class) is used for infix + arguments that represent command-line options (arguments that do + take a value). + +- The ~transient-switches~ class can be used for a set of mutually + exclusive command-line switches. + +- The ~transient-files~ class can be used for a =--= argument that + indicates that all remaining arguments are files. + +- Classes used for infix commands that represent variables should + derived from the abstract ~transient-variable~ class. + +- The ~transient-information~ and ~transient-information*~ classes are + special in that suffixes that use these class are not associated + with a command and thus also not with any key binding. Such + suffixes are only used to display arbitrary information, and that + anywhere a suffix can appear. Display-only suffix specifications + take these form: + + #+begin_src emacs-lisp + ([LEVEL] :info DESCRIPTION [KEYWORD VALUE]...) + ([LEVEL] :info* DESCRIPTION [KEYWORD VALUE]...) + #+end_src + + The ~:info~ and ~:info*~ keyword arguments replaces the ~:description~ + keyword used for other suffix classes. Other keyword arguments that + you might want to set, include ~:face~, predicate keywords (such as + ~:if~ and ~:inapt-if~), and ~:format~. By default the value of ~:format~ + includes ~%k~, which for this class is replaced with the empty string + or spaces, if keys are being padded in the containing group. + + The only difference between these two classes is that ~:info*~ aligns + its description with the descriptions of suffix commands, while for + ~:info~ the description bleeds into the area where suffixes display + their key bindings. + +- The ~transient-lisp-variable~ class can be used to show and change the + value of lisp variables. This class is not fully featured yet and + it is somewhat likely that future improvements won't be fully + backward compatible. + +- The ~transient-describe-target~ class is used by the command + ~transient-describe~. + +- The ~transient-value-preset~ class is used to implement the command + ~transient-preset~, which activates a value preset. + +Magit defines additional classes, which can serve as examples for the +fancy things you can do without modifying Transient. Some of these +classes will likely get generalized and added to Transient. For now +they are very much subject to change and not documented. + +** Prefix Methods + +To get information about the methods implementing these generic +functions use ~describe-function~. + +- Function: transient-init-value obj :: + + This generic function sets the initial value of the object {{{var(OBJ)}}}. + Methods exist for both prefix and suffix objects. + + The default method for prefix objects sets the value of OBJ's ~value~ + slot to the set, saved or default value. The value that is set for + the current session is preferred over the saved value, which is + preferred over the default value. + + The default value is determined using the generic function + ~transient-default-value~. If you need to change how the value for a + prefix class is determined, its usually sufficient to implement a + method for that function. + +- Function: transient-default-value obj :: + + This generic function returns the default value of the object {{{var(OBJ)}}}. + Methods exist for both prefix and suffix objects. + + The default method for prefix objects returns the value of the + ~default-value~ slot if that is bound and not a function. If it is a + function, that is called to get the value. If the slot is unbound, + ~nil~ is returned. + +- Function: transient-prefix-value obj :: + + This generic function returns the value of the prefix object {{{var(OBJ)}}}. + The respective generic function for infix and suffix objects is + named ~transient-infix-value~. + +- Function: transient-init-scope obj :: + + This generic function sets the scope of the object {{{var(OBJ)}}}. Methods + exist for both prefix and suffix objects. + + This function is called for all prefix and suffix commands, but + unless a concrete method is implemented this falls through to + the default implementation, which is a noop. + +~transient-set-value~, ~transient-save-value~, ~transient-reset-value~, +~transient--history-key~, ~transient--history-push~ and +~transient--history-init~ are other generic functions dealing with the +value of prefix objects. See their doc-strings for more information. + +~transient-show-help~ is another generic function implemented for prefix +commands. The default method effectively describes the command using +~describe-function~. + +** Suffix Methods + +To get information about the methods implementing these generic +functions use ~describe-function~. + +*** Suffix Value Methods + +- Function: transient-init-value obj :: + + This generic function sets the initial value of the object {{{var(OBJ)}}}. + Methods exist for both prefix and suffix objects. + + For ~transient-argument~ objects this function handles setting the + value by itself. + + For other ~transient-suffix~ objects (including ~transient-infix~ + objects), this calls ~transient-default-value~ and uses the value + returned by that, unless it is the special value ~eieio--unbound~, + which indicates that there is no default value. Since that is what + the default method for ~transient-suffix~ objects does, both of these + functions effectively are noops for these classes. + + If you implement a class that derives from ~transient-infix~ directly, + then you must implement a dedicated method for this function and/or + ~transient-default-value~. + +- Function: transient-default-value obj :: + + This generic function returns the default value of the object {{{var(OBJ)}}}. + Methods exist for both prefix and suffix objects. + +- Function: transient-infix-read obj :: + + This generic function determines the new value of the infix object + {{{var(OBJ)}}}. + + This function merely determines the value; ~transient-infix-set~ is + used to actually store the new value in the object. + + For most infix classes this is done by reading a value from the + user using the reader specified by the ~reader~ slot (using the + ~transient-infix-value~ method described below). + + For some infix classes the value is changed without reading + anything in the minibuffer, i.e., the mere act of invoking the + infix command determines what the new value should be, based + on the previous value. + +- Function: transient-prompt obj :: + + This generic function returns the prompt to be used to read infix + object {{{var(OBJ)}}}'s value. + +- Function: transient-infix-set obj value :: + + This generic function sets the value of infix object {{{var(OBJ)}}} to {{{var(VALUE)}}}. + +- Function: transient-infix-value obj :: + + This generic function returns the value of the suffix object {{{var(OBJ)}}}. + + This function is called by ~transient-args~ (which see), meaning this + function is how the value of a transient is determined so that the + invoked suffix command can use it. + + Currently most values are strings, but that is not set in stone. + ~nil~ is not a value, it means “no value”. + + Usually only infixes have a value, but see the method for + ~transient-suffix~. + +- Function: transient-init-scope obj :: + + This generic function sets the scope of the object {{{var(OBJ)}}}. Methods + exist for both prefix and suffix objects. + + The scope is actually a property of the transient prefix, not of + individual suffixes. However it is possible to invoke a suffix + command directly instead of from a transient. In that case, if + the suffix expects a scope, then it has to determine that itself + and store it in its ~scope~ slot. + + This function is called for all prefix and suffix commands, but + unless a concrete method is implemented, this falls through to + the default implementation, which is a noop. + +*** Suffix Format Methods + +# Low-level transient--init-suffix-key intentionally left out. + +- Function: transient-format obj :: + + This generic function formats and returns {{{var(OBJ)}}} for display. + + When this function is called, then the current buffer is some + temporary buffer. If you need the buffer from which the prefix + command was invoked to be current, then do so by temporarily + making ~transient--source-buffer~ current. + +- Function: transient-format-key obj :: + + This generic function formats {{{var(OBJ)}}}'s ~key~ for display and returns the + result. + +- Function: transient-format-description obj :: + + This generic function formats {{{var(OBJ)}}}'s ~description~ for display and + returns the result. + +- Function: transient-format-value obj :: + + This generic function formats {{{var(OBJ)}}}'s value for display and returns + the result. + +- Function: transient-show-help obj :: + + Show help for the prefix, infix or suffix command represented by + {{{var(OBJ)}}}. + + Regardless of OBJ's type, if its ~show-help~ slot is non-~nil~, that + must be a function, which takes OBJ is its only argument. It must + prepare, display and return a buffer, and select the window used to + display it. The ~transient-show-help-window~ macro is intended for + use in such functions. + + For prefixes, show the info manual, if that is specified using the + ~info-manual~ slot. Otherwise, show the manpage if that is specified + using the ~man-page~ slot. Otherwise, show the command's + documentation string. + + For suffixes, show the command's documentation string. + + For infixes, show the manpage if that is specified. Otherwise show + the command's documentation string. + +- Macro: transient-with-help-window &rest body :: + + Evaluate BODY, send output to ~*Help*~ buffer, and display it in a + window. Select the help window, and make the help buffer current + and return it. + +- Function: transient-show-summary obj &optional return :: + + This generic function shows or, if optional RETURN is non-~nil~, + returns a brief summary about the command at point or hovered with + the mouse. + + This function is called when the mouse is moved over a command and + (if the value of ~transient-enable-popup-navigation~ is ~verbose~) when + the user navigates to a command using the keyboard. + + If OBJ's ~summary~ slot is a string, that is used. If ~summary~ is a + function, that is called with OBJ as the only argument and the + returned string is used. If ~summary~ is or returns something other + than a string or ~nil~, no summary is shown. If ~summary~ is or returns + ~nil~, the first line of the documentation string is used, if any. + + If RETURN is non-~nil~, this function returns the summary instead of + showing it. This is used when a tooltip is needed. + +** Prefix Slots +*** Value and Scope +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- ~default-value~ The default value of the prefix. Use the keyword + argument ~:value~ (sic) to set this slot in the definition of a + prefix. + +- ~init-value~ A function that is responsible for setting the object's + value. If bound, then this is called with the object as the only + argument. Usually this is not bound, in which case the object's + primary ~transient-init-value~ method is called instead. + +- ~history-key~ If multiple prefix commands should share a single value, + then this slot has to be set to the same value for all of them. You + probably don't want that. + +- ~incompatible~ A list of lists. Each sub-list specifies a set of + mutually exclusive arguments. Enabling one of these arguments + causes the others to be disabled. An argument may appear in + multiple sub-lists. Arguments must me given in the same form as + used in the ~argument~ or ~argument-format~ slot of the respective + suffix objects, usually something like ~--switch~ or ~--option=%s~. For + options and ~transient-switches~ suffixes it is also possible to match + against a specific value, as returned by ~transient-infix-value~, + for example, ~--option=one~. + +- ~scope~ For some transients it might be necessary to have a sort of + secondary value, called a “scope”. See ~transient-define-prefix~. + +*** Behavior +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- ~transient-suffix~, ~transient-non-suffix~ and ~transient-switch-frame~ + play a part when determining whether the currently active transient + prefix command remains active/transient when a suffix or arbitrary + non-suffix command is invoked. See [[*Transient State]]. + +- ~refresh-suffixes~ Normally suffix objects and keymaps are only setup + once, when the prefix is invoked. Setting this to ~t~, causes them to + be recreated after every command. This is useful when using ~:if...~ + predicates, and those need to be rerun for some reason. Doing this + is somewhat costly, and there is a risk of losing state, so this is + disabled by default and still considered experimental. + +- ~environment~ A function used to establish an environment while + initializing, refreshing or redisplaying a transient prefix menu. + This is useful to establish a cache, in case multiple suffixes + require the same expensive work. The provided function is called + with at least one argument, the function for which it establishes + the environment. It must ~funcall~ that function with no arguments. + During initialization the second argument is the prefix object + being initialized. This slot is still experimental. + +*** Appearance +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- ~display-action~ determines how this prefix is displayed, overriding + ~transient-display-buffer-action~. It should have the same type. + +- ~mode-line-format~ is this prefix's mode line format, overriding + ~transient-mode-line-format~. It should have the same type. + +- ~column-widths~ is only respected inside ~transient-columns~ groups and + allows aligning columns across separate instances of that. A list + of integers. + +- ~variable-pitch~ controls whether alignment is done pixel-wise to + account for use of variable-pitch characters, which is useful, e.g., + when using emoji. + +*** Documentation +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- ~show-help~, ~man-page~ or ~info-manual~ can be used to specify the + documentation for the prefix and its suffixes. The command + ~transient-help~ uses the function ~transient-show-help~ (which see) to + lookup and use these values. + +- ~suffix-description~ can be used to specify a function which provides + fallback descriptions for suffixes that lack a description. This + is intended to be temporarily used when implementing of a new prefix + command, at which time ~transient-command-summary-or-name~ is a useful + value. + +*** Internal +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +These slots are mostly intended for internal use. They should not be +set in calls to ~transient-define-prefix~. + +- ~prototype~ When a transient prefix command is invoked, then a clone + of that object is stored in the global variable ~transient--prefix~ + and the prototype is stored in the clone's ~prototype~ slot. + +- ~command~ The command, a symbol. Each transient prefix command + consists of a command, which is stored in a symbol's function slot + and an object, which is stored in the ~transient--prefix~ property + of the same symbol. + +- ~level~ The level of the prefix commands. The suffix commands whose + layer is equal or lower are displayed. See [[*Enabling and Disabling + Suffixes]]. + +- ~value~ The likely outdated value of the prefix. Instead of accessing + this slot directly you should use the function ~transient-get-value~, + which is guaranteed to return the up-to-date value. + +- ~history~ and ~history-pos~ are used to keep track of historic values. + Unless you implement your own ~transient-infix-read~ method you should + not have to deal with these slots. + +- ~unwind-suffix~ is used internally to ensure transient state is + properly exited, even in case of an error. + +** Suffix Slots + +Here we document most of the slots that are only available for suffix +objects. Some slots are shared by suffix and group objects, they are +documented in [[*Predicate Slots]]. + +Also see [[*Suffix Classes]]. + +*** Slots of ~transient-child~ +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +This is the abstract superclass of ~transient-suffix~ and ~transient-group~. +This is where the shared ~if*~ and ~inapt-if*~ slots (see [[*Predicate Slots]]), +the ~level~ slot (see [[*Enabling and Disabling Suffixes]]), and the ~advice~ +and ~advice*~ slots (see [[*Slots of ~transient-suffix~]]) are defined. + +- ~parent~ The object for the parent group. + +*** Slots of ~transient-suffix~ +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- ~key~ The key, a key vector or a key description string. + +- ~command~ The command, a symbol. + +- ~transient~ Whether to stay transient. See [[*Transient State]]. + +- ~format~ The format used to display the suffix in the popup buffer. + It must contain the following %-placeholders: + + - ~%k~ For the key. + - ~%d~ For the description. + - ~%v~ For the infix value. Non-infix suffixes don't have a value. + +- ~description~ The description, either a string or a function, which is + called with zero or one argument (the suffix object), and returns a + string. + +- ~face~ Face used for the description. In simple cases it is easier + to use this instead of using a function as ~description~ and adding + the styling there. ~face~ is appended using ~add-face-text-property~. + +- ~show-help~ A function used to display help for the suffix. If + unspecified, the prefix controls how help is displayed for its + suffixes. See also function ~transient-show-help~. + +- ~summary~ The summary displayed in the echo area, or as a tooltip. + If this is ~nil~, which it usually should be, the first line of the + documentation string is used instead. See ~transient-show-summary~ + for details. + +- ~definition~ A command, which is used if the body is omitted when + defining a command using ~transient-define-suffix~. + +The following two slots are experimental. They can also be set for a +group, in which case they apply to all suffixes in that group, except +for suffixes that set the same slot to a non-nil value. + +- ~advice~ A function used to advise the command. The advise is called + using ~(apply advice command args)~, i.e., it behaves like an "around" + advice. + +- ~advice*~ A function used to advise the command. Unlike ~advice~, this + advises not only the command body but also its ~interactive~ spec. If + both slots are non-nil, ~advice~ is used for the body and ~advice*~ is + used for the ~interactive~ form. When advising the ~interactive~ spec, + called using ~(funcall advice #'advice-eval-interactive-spec spec)~. + +*** Slots of ~transient-infix~ +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +Some of these slots are only meaningful for some of the subclasses. +They are defined here anyway to allow sharing certain methods. + +- ~argument~ The long argument, e.g., ~--verbose~. + +- ~shortarg~ The short argument, e.g., ~-v~. + +- ~value~ The value. Should not be accessed directly. + +- ~init-value~ Function that is responsible for setting the object's + value. If bound, then this is called with the object as the only + argument. Usually this is not bound, in which case the object's + primary ~transient-init-value~ method is called instead. + +- ~unsavable~ Whether the value of the suffix is not saved as part of + the prefixes. + +- ~multi-value~ For options, whether the option can have multiple + values. If this is non-~nil~, then the values are read using + ~completing-read-multiple~ by default and if you specify your own + reader, then it should read the values using that function or + similar. + + Supported non-~nil~ values are: + + - Use ~rest~ for an option that can have multiple values. This is + useful e.g., for an ~--~ argument that indicates that all remaining + arguments are files (such as ~git log -- file1 file2~). + + In the list returned by ~transient-args~ such an option and its + values are represented by a single list of the form ~(ARGUMENT + . VALUES)~. + + - Use ~repeat~ for an option that can be specified multiple times. + + In the list returned by ~transient-args~ each instance of the option + and its value appears separately in the usual from, for example: + ~("--another-argument" "--option=first" "--option=second")~. + + In both cases the option's values have to be specified in the + default value of a prefix using the same format as returned by + ~transient-args~, e.g., ~("--other" "--o=1" "--o=2" ("--" "f1" "f2"))~. + +- ~always-read~ For options, whether to read a value on every invocation. + If this is ~nil~, then options that have a value are simply unset and + have to be invoked a second time to set a new value. + +- ~allow-empty~ For options, whether the empty string is a valid value. + +- ~history-key~ The key used to store the history. This defaults to the + command name. This is useful when multiple infixes should share the + same history because their values are of the same kind. + +- ~reader~ The function used to read the value of an infix. Not used + for switches. The function takes three arguments, {{{var(PROMPT)}}}, + {{{var(INITIAL-INPUT)}}} and {{{var(HISTORY)}}}, and must return a string. + +- ~prompt~ The prompt used when reading the value, either a string or a + function that takes the object as the only argument and which + returns a prompt string. + +- ~choices~ A list of valid values, or a function that returns such a + list. The latter is not implemented for ~transient-switches~, because + I couldn't think of a use-case. How exactly the choices are used + varies depending on the class of the suffix. + +*** Slots of ~transient-variable~ +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- ~variable~ The variable. + +*** Slots of ~transient-switches~ +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +- ~argument-format~ The display format. Must contain ~%s~, one of the + ~choices~ is substituted for that. E.g., ~--%s-order~. + +- ~argument-regexp~ The regexp used to match any one of the switches. + E.g., ~\\(--\\(topo\\|author-date\\|date\\)-order\\)~. + +** Predicate Slots + +Suffix and group objects share two sets of predicate slots that +control whether a group or suffix should be available depending on +some state. Only one slot from each set can be used at the same +time. It is undefined which slot is honored if you use more than +one. + +Predicates from the first group control whether the suffix is present +in the menu at all. + +- ~if~ Enable if predicate returns non-~nil~. +- ~if-not~ Enable if predicate returns ~nil~. +- ~if-non-nil~ Enable if variable's value is non-~nil~. +- ~if-nil~ Enable if variable's value is ~nil~. +- ~if-mode~ Enable if major-mode matches value. +- ~if-not-mode~ Enable if major-mode does not match value. +- ~if-derived~ Enable if major-mode derives from value. +- ~if-not-derived~ Enable if major-mode does not derive from value. + +Predicates from the second group control whether the suffix can be +invoked. The suffix is shown in the menu regardless, but when it +is considered "inapt", then it is grayed out to indicated that it +currently cannot be invoked. + +- ~inapt-if~ Inapt if predicate returns non-~nil~. +- ~inapt-if-not~ Inapt if predicate returns ~nil~. +- ~inapt-if-non-nil~ Inapt if variable's value is non-~nil~. +- ~inapt-if-nil~ Inapt if variable's value is ~nil~. +- ~inapt-if-mode~ Inapt if major-mode matches value. +- ~inapt-if-not-mode~ Inapt if major-mode does not match value. +- ~inapt-if-derived~ Inapt if major-mode derives from value. +- ~inapt-if-not-derived~ Inapt if major-mode does not derive from value. + +By default these predicates run when the prefix command is invoked, +but this can be changes, using the ~refresh-suffixes~ prefix slot. +See [[*Prefix Slots]]. + +One more slot is shared between group and suffix classes, ~level~. Like +the slots documented above, it is a predicate, but it is used for a +different purpose. The value has to be an integer between 1 +and 7. ~level~ controls whether a suffix or a group should be +available depending on user preference. +See [[*Enabling and Disabling Suffixes]]. + +* FAQ +:PROPERTIES: +:APPENDIX: t +:END: + +** Can I control how the popup buffer is displayed? +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +Yes, see ~transient-display-buffer-action~ in [[*Configuration]]. You can +also control how the popup buffer is displayed on a case-by-case basis +by passing ~:display-action~ to ~transient-define-prefix~. + +** How can I copy text from the popup buffer? +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +To be able to mark text in Transient's popup buffer using the mouse, +you have to add the below binding. Note that for technical reasons, +the region won't be visualized, while doing so. After you have quit +the transient popup, you will be able to yank it in another buffer. + +#+begin_src emacs-lisp + (keymap-set transient-predicate-map + "<mouse-set-region>" + #'transient--do-stay) +#+end_src + +** How can I autoload prefix and suffix commands? +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +If your package only supports Emacs 30, just prefix the definition +with ~;;;###autoload~. If your package supports released versions of +Emacs, you unfortunately have to use a long form autoload comment +as described in [[info:elisp#Autoload]]. + +#+begin_src emacs-lisp + ;;;###autoload (autoload 'magit-dispatch "magit" nil t) + (transient-define-prefix magit-dispatch () + ...) +#+end_src + +** How does Transient compare to prefix keys and universal arguments? +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +See https://github.com/magit/transient/wiki/Comparison-with-prefix-keys-and-universal-arguments. + +** How does Transient compare to Magit-Popup and Hydra? +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +See https://github.com/magit/transient/wiki/Comparison-with-other-packages. + +** Why did some of the key bindings change? +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +You may have noticed that the bindings for some of the common commands +do *not* have the prefix {{{kbd(C-x)}}} and that furthermore some of these commands +are grayed out while others are not. That unfortunately is a bit +confusing if the section of common commands is not shown permanently, +making the following explanation necessary. + +The purpose of usually hiding that section but showing it after the +user pressed the respective prefix key is to conserve space and not +overwhelm users with too much noise, while allowing the user to +quickly list common bindings on demand. + +That however should not keep us from using the best possible key +bindings. The bindings that do use a prefix do so to avoid wasting +too many non-prefix bindings, keeping them available for use in +individual transients. The bindings that do not use a prefix and that +are *not* grayed out are very important bindings that are *always* +available, even when invoking the “common command key prefix” or *any +other* transient-specific prefix. The non-prefix keys that *are* grayed +out however, are not available when any incomplete prefix key sequence +is active. They do not use the “common command key prefix” because it +is likely that users want to invoke them several times in a row and +e.g., {{{kbd(M-p M-p M-p)}}} is much more convenient than {{{kbd(C-x M-p C-x M-p C-x M-p)}}}. + +You may also have noticed that the “Set” command is bound to {{{kbd(C-x s)}}}, +while Magit-Popup used to bind {{{kbd(C-c C-c)}}} instead. I have seen several +users praise the latter binding (sic), so I did not change it +willy-nilly. The reason that I changed it is that using different +prefix keys for different common commands, would have made the +temporary display of the common commands even more confusing, i.e., +after pressing {{{kbd(C-c)}}} all the bindings that begin with the {{{kbd(C-x)}}} prefix +would be grayed out. + +Using a single prefix for common commands key means that all other +potential prefix keys can be used for transient-specific commands +*without* the section of common commands also popping up. {{{kbd(C-c)}}} in +particular is a prefix that I want to (and already do) use for Magit, and +also using that for a common command would prevent me from doing so. + +(See also the next question.) + +** Why does {{{kbd(q)}}} not quit popups anymore? +:PROPERTIES: +:UNNUMBERED: notoc +:END: + +I agree that {{{kbd(q)}}} is a good binding for commands that quit something. +This includes quitting whatever transient is currently active, but it +also includes quitting whatever it is that some specific transient is +controlling. The transient ~magit-blame~ for example binds {{{kbd(q)}}} to the +command that turns ~magit-blame-mode~ off. + +So I had to decide if {{{kbd(q)}}} should quit the active transient (like +Magit-Popup used to) or whether {{{kbd(C-g)}}} should do that instead, so that {{{kbd(q)}}} +could be bound in individual transient to whatever commands make sense +for them. Because all other letters are already reserved for use by +individual transients, I have decided to no longer make an exception +for {{{kbd(q)}}}. + +If you want to get {{{kbd(q)}}}'s old binding back then you can do so. Doing +that is a bit more complicated than changing a single key binding, so +I have implemented a function, ~transient-bind-q-to-quit~ that makes the +necessary changes. See its documentation string for more information. + +* Keystroke Index +:PROPERTIES: +:APPENDIX: t +:INDEX: ky +:COOKIE_DATA: recursive +:END: +* Command and Function Index +:PROPERTIES: +:APPENDIX: t +:INDEX: fn +:END: +* Variable Index +:PROPERTIES: +:APPENDIX: t +:INDEX: vr +:END: +* Concept Index +:PROPERTIES: +:APPENDIX: t +:INDEX: cp +:END: + +* GNU General Public License +:PROPERTIES: +:APPENDIX: t +:END: +#+texinfo: @include gpl.texi + +* Copying +:PROPERTIES: +:COPYING: t +:END: + +#+begin_quote +Copyright (C) 2018--{{{year}}} Free Software Foundation, Inc. + +You can redistribute this document and/or modify it under the terms +of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any +later version. + +This document is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. +#+end_quote + +# LocalWords: ARGLIST ARGS CLI DOCSTRING ELEMENTs EVAL GROUPs Infixes +# LocalWords: Infixes KEYWORDs LOC LocalWords MERCHANTABILITY Magit +# LocalWords: Magit's Makefile OBJ OBJ's Pre alist arglist +# LocalWords: args autoloaded boolean booleans customizable docstring +# LocalWords: eval featurep infixes init isearch keymap keymaps loc +# LocalWords: magit manpage minibuffer monospaced ness nilly noop noops +# LocalWords: plist pre prev rebase redisplay src subclass subclasses +# LocalWords: subcommands subprocess superclass tooltip termcap utils + +# IMPORTANT: Also update ORG_ARGS and ORG_EVAL in the Makefile. +# Local Variables: +# indent-tabs-mode: nil +# org-hide-macro-markers: t +# org-src-preserve-indentation: nil +# End: |