aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Bernoulli2025-02-01 18:14:47 +0100
committerJonas Bernoulli2025-02-01 18:14:47 +0100
commit3a86774ce55e9dc4dc6de01f6aca19fcaa41a5d3 (patch)
tree57dc39d0e5eed587f125e4fffd31da2163ad2ae9
parent5a5706f943ae2677c6d73fed8de11affd3ef04aa (diff)
downloademacs-3a86774ce55e9dc4dc6de01f6aca19fcaa41a5d3.tar.gz
emacs-3a86774ce55e9dc4dc6de01f6aca19fcaa41a5d3.zip
Update to Transient v0.8.4-7-gabee7353
-rw-r--r--doc/misc/transient.texi138
-rw-r--r--lisp/transient.el227
2 files changed, 292 insertions, 73 deletions
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi
index fb8b6da145c..4740663e987 100644
--- a/doc/misc/transient.texi
+++ b/doc/misc/transient.texi
@@ -31,7 +31,7 @@ General Public License for more details.
31@finalout 31@finalout
32@titlepage 32@titlepage
33@title Transient User and Developer Manual 33@title Transient User and Developer Manual
34@subtitle for version 0.8.3 34@subtitle for version 0.8.4
35@author Jonas Bernoulli 35@author Jonas Bernoulli
36@page 36@page
37@vskip 0pt plus 1filll 37@vskip 0pt plus 1filll
@@ -53,7 +53,7 @@ resource to get over that hurdle is Psionic K's interactive tutorial,
53available at @uref{https://github.com/positron-solutions/transient-showcase}. 53available at @uref{https://github.com/positron-solutions/transient-showcase}.
54 54
55@noindent 55@noindent
56This manual is for Transient version 0.8.3. 56This manual is for Transient version 0.8.4.
57 57
58@insertcopying 58@insertcopying
59@end ifnottex 59@end ifnottex
@@ -93,6 +93,7 @@ Defining New Commands
93* Binding Suffix and Infix Commands:: 93* Binding Suffix and Infix Commands::
94* Defining Suffix and Infix Commands:: 94* Defining Suffix and Infix Commands::
95* Using Infix Arguments:: 95* Using Infix Arguments::
96* Using Prefix Scope::
96* Current Suffix Command:: 97* Current Suffix Command::
97* Current Prefix Command:: 98* Current Prefix Command::
98* Transient State:: 99* Transient State::
@@ -553,6 +554,48 @@ the level specified by @code{transient-default-level} are temporarily
553available anyway. 554available anyway.
554@end table 555@end table
555 556
557@defun transient-set-default-level suffix level
558This function sets the default level of the suffix COMMAND to LEVEL@.
559
560If a suffix command appears in multiple menus, it may make sense to
561consistently change its level in all those menus at once. For
562example, the @code{--gpg-sign} argument (which is implemented using the
563command @code{magit:--gpg-sign}), is bound in all of Magit's menu which
564create commits. Users who sometimes sign their commits would want
565that argument to be available in all of these menus, while for users
566who never sign it is just unnecessary noise in any menus.
567
568To always make @code{--gpg-sign} available, use:
569
570@lisp
571(transient-set-default-level 'magit:--gpg-sign 1)
572@end lisp
573
574To never make @code{--gpg-sign} available, use:
575
576@lisp
577(transient-set-default-level 'magit:--gpg-sign 0)
578@end lisp
579
580This sets the level in the suffix prototype object for this command.
581Commands only have a suffix prototype if they were defined using one
582of @code{transient-define-argument}, @code{transient-define-infix} and
583@code{transient-define-suffix}. For all other commands this would signal
584an error. (This is one of the reasons why package authors should
585use one of these functions to define shared suffix commands, and
586especially shared arguments.)
587
588If the user changes the level of a suffix in a particular menu,
589using @kbd{C-x l} as shown above, then that obviously shadows the default.
590
591It is also possible to set the level of a suffix binding in a
592particular menu, either when defining the menu using
593@code{transient-define-prefix,} or later using @code{transient-insert-suffix}. If
594such bindings specify a level, then that also overrides the default.
595(Per-suffix default levels is a new feature, so you might encounter
596this quite often.)
597@end defun
598
556@node Other Commands 599@node Other Commands
557@section Other Commands 600@section Other Commands
558 601
@@ -1017,6 +1060,7 @@ signal an error.
1017* Binding Suffix and Infix Commands:: 1060* Binding Suffix and Infix Commands::
1018* Defining Suffix and Infix Commands:: 1061* Defining Suffix and Infix Commands::
1019* Using Infix Arguments:: 1062* Using Infix Arguments::
1063* Using Prefix Scope::
1020* Current Suffix Command:: 1064* Current Suffix Command::
1021* Current Prefix Command:: 1065* Current Prefix Command::
1022* Transient State:: 1066* Transient State::
@@ -1323,6 +1367,13 @@ be replaced with an error.
1323The boolean @code{:pad-keys} argument controls whether keys of all suffixes 1367The boolean @code{:pad-keys} argument controls whether keys of all suffixes
1324contained in a group are right padded, effectively aligning the 1368contained in a group are right padded, effectively aligning the
1325descriptions. 1369descriptions.
1370
1371@item
1372If a keyword argument accepts a function as value, you an use a
1373@code{lambda} expression. As a special case, the @code{##} macro (which returns a
1374@code{lambda} expression and is implemented in the @code{llama} package) is also
1375supported. Inside group specifications, the use of @code{##} is not
1376supported anywhere but directly following a keyword symbol.
1326@end itemize 1377@end itemize
1327 1378
1328The @var{ELEMENT}s are either all subgroups, or all suffixes and strings. 1379The @var{ELEMENT}s are either all subgroups, or all suffixes and strings.
@@ -1446,6 +1497,12 @@ Finally, details can be specified using optional @var{KEYWORD}-@var{VALUE} pairs
1446Each keyword has to be a keyword symbol, either @code{:class} or a keyword 1497Each keyword has to be a keyword symbol, either @code{:class} or a keyword
1447argument supported by the constructor of that class. @xref{Suffix Slots}. 1498argument supported by the constructor of that class. @xref{Suffix Slots}.
1448 1499
1500If a keyword argument accepts a function as value, you an use a @code{lambda}
1501expression. As a special case, the @code{##} macro (which returns a @code{lambda}
1502expression and is implemented in the @code{llama} package) is also supported.
1503Inside suffix bindings, the use of @code{##} is not supported anywhere but
1504directly following a keyword symbol.
1505
1449@node Defining Suffix and Infix Commands 1506@node Defining Suffix and Infix Commands
1450@section Defining Suffix and Infix Commands 1507@section Defining Suffix and Infix Commands
1451 1508
@@ -1568,6 +1625,55 @@ used if you need the objects (as opposed to just their values) and
1568if the current command is not being invoked from @var{PREFIX}. 1625if the current command is not being invoked from @var{PREFIX}.
1569@end defun 1626@end defun
1570 1627
1628@node Using Prefix Scope
1629@section Using Prefix Scope
1630
1631Some transients have a sort of secondary value, called a scope. A
1632prefix's scope can be accessed using @code{transient-scope}; similar to how
1633its value can be accessed using @code{transient-args}.
1634
1635@defun transient-scope prefixes classes
1636This function returns the scope of the active or current transient
1637prefix command.
1638
1639If optional PREFIXES and CLASSES are both nil, return the scope of
1640the prefix currently being setup, making this variation useful, e.g.,
1641in @code{:if*} predicates. If no prefix is being setup, but the current
1642command was invoked from some prefix, then return the scope of that.
1643
1644If PREFIXES is non-nil, it must be a prefix command or a list of such
1645commands. If CLASSES is non-nil, it must be a prefix class or a list
1646of such classes. When this function is called from the body or the
1647@code{interactive} form of a suffix command, PREFIXES and/or CLASSES should
1648be non-nil. If either is non-nil, try the following in order:
1649
1650@itemize
1651@item
1652If the current suffix command was invoked from a prefix, which
1653appears in PREFIXES, return the scope of that prefix.
1654
1655@item
1656If the current suffix command was invoked from a prefix, and its
1657class derives from one of the CLASSES, return the scope of that
1658prefix.
1659
1660@item
1661If a prefix is being setup and it appears in PREFIXES, return its
1662scope.
1663
1664@item
1665If a prefix is being setup and its class derives from one of the
1666CLASSES, return its scope.
1667
1668@item
1669Finally try to return the default scope of the first command in
1670PREFIXES@. This only works if that slot is set in the respective
1671class definition or using its `transient-init-scope' method.
1672@end itemize
1673
1674If no prefix matches, return nil.
1675@end defun
1676
1571@node Current Suffix Command 1677@node Current Suffix Command
1572@section Current Suffix Command 1678@section Current Suffix Command
1573 1679
@@ -2458,8 +2564,9 @@ being initialized. This slot is still experimental.
2458@code{transient-mode-line-format}. It should have the same type. 2564@code{transient-mode-line-format}. It should have the same type.
2459 2565
2460@item 2566@item
2461@code{column-width} is only respected inside @code{transient-columns} groups and 2567@code{column-widths} is only respected inside @code{transient-columns} groups and
2462allows aligning columns across separate instances of that. 2568allows aligning columns across separate instances of that. A list
2569of integers.
2463 2570
2464@item 2571@item
2465@code{variable-pitch} controls whether alignment is done pixel-wise to 2572@code{variable-pitch} controls whether alignment is done pixel-wise to
@@ -2535,8 +2642,9 @@ Also see @ref{Suffix Classes}.
2535@subheading Slots of @code{transient-child} 2642@subheading Slots of @code{transient-child}
2536 2643
2537This is the abstract superclass of @code{transient-suffix} and @code{transient-group}. 2644This is the abstract superclass of @code{transient-suffix} and @code{transient-group}.
2538This is where the shared @code{if*} and @code{inapt-if*} slots (see @ref{Predicate Slots}) 2645This is where the shared @code{if*} and @code{inapt-if*} slots (see @ref{Predicate Slots}),
2539and the @code{level} slot (see @ref{Enabling and Disabling Suffixes}) are defined. 2646the @code{level} slot (see @ref{Enabling and Disabling Suffixes}), and the @code{advice}
2647and @code{advice*} slots (see @ref{Slots of @code{transient-suffix}}) are defined.
2540 2648
2541@itemize 2649@itemize
2542@item 2650@item
@@ -2595,6 +2703,24 @@ for details.
2595defining a command using @code{transient-define-suffix}. 2703defining a command using @code{transient-define-suffix}.
2596@end itemize 2704@end itemize
2597 2705
2706The following two slots are experimental. They can also be set for a
2707group, in which case they apply to all suffixes in that group, except
2708for suffixes that set the same slot to a non-nil value.
2709
2710@itemize
2711@item
2712@code{advice} A function used to advise the command. The advise is called
2713using @code{(apply advice command args)}, i.e., it behaves like an "around"
2714advice.
2715
2716@item
2717@code{advice*} A function used to advise the command. Unlike @code{advice}, this
2718advises not only the command body but also its @code{interactive} spec. If
2719both slots are non-nil, @code{advice} is used for the body and @code{advice*} is
2720used for the @code{interactive} form. When advising the @code{interactive} spec,
2721called using @code{(funcall advice #'advice-eval-interactive-spec spec)}.
2722@end itemize
2723
2598@anchor{Slots of @code{transient-infix}} 2724@anchor{Slots of @code{transient-infix}}
2599@subheading Slots of @code{transient-infix} 2725@subheading Slots of @code{transient-infix}
2600 2726
diff --git a/lisp/transient.el b/lisp/transient.el
index 24ab56e830b..610e5871ccc 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -5,7 +5,7 @@
5;; Author: Jonas Bernoulli <jonas@bernoul.li> 5;; Author: Jonas Bernoulli <jonas@bernoul.li>
6;; URL: https://github.com/magit/transient 6;; URL: https://github.com/magit/transient
7;; Keywords: extensions 7;; Keywords: extensions
8;; Version: 0.8.3 8;; Version: 0.8.4
9 9
10;; SPDX-License-Identifier: GPL-3.0-or-later 10;; SPDX-License-Identifier: GPL-3.0-or-later
11 11
@@ -32,7 +32,7 @@
32 32
33;;; Code: 33;;; Code:
34 34
35(defconst transient-version "v0.8.3-2-gf0478b29-builtin") 35(defconst transient-version "v0.8.4-7-gabee7353-builtin")
36 36
37(require 'cl-lib) 37(require 'cl-lib)
38(require 'eieio) 38(require 'eieio)
@@ -281,6 +281,20 @@ number is positive, or hide the menu if it is negative."
281 :format "\n %t: %v" 281 :format "\n %t: %v"
282 :value -20))) 282 :value -20)))
283 283
284(defcustom transient-show-docstring-format "%s"
285 "How to display suffix docstrings.
286
287The command `transient-toggle-docstrings' toggles between showing suffix
288descriptions as usual, and instead or additionally displaying the suffix
289docstrings. The format specified here controls how that is done. %c is
290the description and %s is the docstring. Use \"%-14c %s\" or similar to
291display both.
292
293This command is not bound by default, see its docstring for instructions."
294 :package-version '(transient . "0.8.4")
295 :group 'transient
296 :type 'string)
297
284(defcustom transient-read-with-initial-input nil 298(defcustom transient-read-with-initial-input nil
285 "Whether to use the last history element as initial minibuffer input." 299 "Whether to use the last history element as initial minibuffer input."
286 :package-version '(transient . "0.2.0") 300 :package-version '(transient . "0.2.0")
@@ -709,7 +723,7 @@ the prototype is stored in the clone's `prototype' slot.")
709 :documentation "The parent group object.") 723 :documentation "The parent group object.")
710 (level 724 (level
711 :initarg :level 725 :initarg :level
712 :initform (symbol-value 'transient--default-child-level) 726 :initform nil
713 :documentation "Enable if level of prefix is equal or greater.") 727 :documentation "Enable if level of prefix is equal or greater.")
714 (if 728 (if
715 :initarg :if 729 :initarg :if
@@ -779,7 +793,15 @@ the prototype is stored in the clone's `prototype' slot.")
779 (inapt-if-not-derived 793 (inapt-if-not-derived
780 :initarg :inapt-if-not-derived 794 :initarg :inapt-if-not-derived
781 :initform nil 795 :initform nil
782 :documentation "Inapt if major-mode does not derive from value.")) 796 :documentation "Inapt if major-mode does not derive from value.")
797 (advice
798 :initarg :advice
799 :initform nil
800 :documentation "Advise applied to the command body.")
801 (advice*
802 :initarg :advice*
803 :initform nil
804 :documentation "Advise applied to the command body and interactive spec."))
783 "Abstract superclass for group and suffix classes. 805 "Abstract superclass for group and suffix classes.
784 806
785It is undefined which predicates are used if more than one `if*' 807It is undefined which predicates are used if more than one `if*'
@@ -1188,14 +1210,15 @@ commands are aliases for."
1188 (cond ((eq key :class) 1210 (cond ((eq key :class)
1189 (setq class val)) 1211 (setq class val))
1190 ((or (symbolp val) 1212 ((or (symbolp val)
1191 (and (listp val) (not (eq (car val) 'lambda)))) 1213 (and (listp val)
1214 (not (memq (car val) (list 'lambda (intern ""))))))
1192 (setq args (plist-put args key (macroexp-quote val)))) 1215 (setq args (plist-put args key (macroexp-quote val))))
1193 ((setq args (plist-put args key val)))))) 1216 ((setq args (plist-put args key val))))))
1194 (unless (or spec class (not (plist-get args :setup-children))) 1217 (unless (or spec class (not (plist-get args :setup-children)))
1195 (message "WARNING: %s: When %s is used, %s must also be specified" 1218 (message "WARNING: %s: When %s is used, %s must also be specified"
1196 'transient-define-prefix :setup-children :class)) 1219 'transient-define-prefix :setup-children :class))
1197 (list 'vector 1220 (list 'vector
1198 (or level transient--default-child-level) 1221 level
1199 (list 'quote 1222 (list 'quote
1200 (cond (class) 1223 (cond (class)
1201 ((cl-typep (car spec) 1224 ((cl-typep (car spec)
@@ -1286,7 +1309,8 @@ commands are aliases for."
1286 ((guard (eq (car-safe val) '\,)) 1309 ((guard (eq (car-safe val) '\,))
1287 (use key (cadr val))) 1310 (use key (cadr val)))
1288 ((guard (or (symbolp val) 1311 ((guard (or (symbolp val)
1289 (and (listp val) (not (eq (car val) 'lambda))))) 1312 (and (listp val)
1313 (not (memq (car val) (list 'lambda (intern "")))))))
1290 (use key (macroexp-quote val))) 1314 (use key (macroexp-quote val)))
1291 (_ (use key val))))) 1315 (_ (use key val)))))
1292 (when spec 1316 (when spec
@@ -1295,7 +1319,7 @@ commands are aliases for."
1295 (shortarg (plist-get args :shortarg))) 1319 (shortarg (plist-get args :shortarg)))
1296 (use :key shortarg))) 1320 (use :key shortarg)))
1297 (list 'list 1321 (list 'list
1298 (or level transient--default-child-level) 1322 level
1299 (macroexp-quote (or class 'transient-suffix)) 1323 (macroexp-quote (or class 'transient-suffix))
1300 (cons 'list args)))) 1324 (cons 'list args))))
1301 1325
@@ -1530,6 +1554,21 @@ See info node `(transient)Modifying Existing Transients'."
1530(defun transient--nthcdr (n list) 1554(defun transient--nthcdr (n list)
1531 (nthcdr (if (< n 0) (- (length list) (abs n)) n) list)) 1555 (nthcdr (if (< n 0) (- (length list) (abs n)) n) list))
1532 1556
1557(defun transient-set-default-level (command level)
1558 "Set the default level of suffix COMMAND to LEVEL.
1559
1560The default level is shadowed if the binding of the suffix in a
1561prefix menu specifies a level, and also if the user changes the
1562level of such a binding.
1563
1564The default level can only be set for commands that were defined
1565using `transient-define-suffix', `transient-define-infix' or
1566`transient-define-argument'."
1567 (if-let ((proto (transient--suffix-prototype command)))
1568 (oset proto level level)
1569 (user-error "Cannot set level for `%s'; no prototype object exists"
1570 command)))
1571
1533;;; Variables 1572;;; Variables
1534 1573
1535(defvar transient-current-prefix nil 1574(defvar transient-current-prefix nil
@@ -2216,7 +2255,8 @@ value. Otherwise return CHILDREN as is.")
2216 (string (list spec)))) 2255 (string (list spec))))
2217 2256
2218(defun transient--init-group (levels spec parent) 2257(defun transient--init-group (levels spec parent)
2219 (pcase-let ((`(,level ,class ,args ,children) (append spec nil))) 2258 (pcase-let* ((`(,level ,class ,args ,children) (append spec nil))
2259 (level (or level transient--default-child-level)))
2220 (and-let* (((transient--use-level-p level)) 2260 (and-let* (((transient--use-level-p level))
2221 (obj (apply class :parent parent :level level args)) 2261 (obj (apply class :parent parent :level level args))
2222 ((transient--use-suffix-p obj)) 2262 ((transient--use-suffix-p obj))
@@ -2233,9 +2273,12 @@ value. Otherwise return CHILDREN as is.")
2233 (pcase-let* ((`(,level ,class ,args) spec) 2273 (pcase-let* ((`(,level ,class ,args) spec)
2234 (cmd (plist-get args :command)) 2274 (cmd (plist-get args :command))
2235 (key (transient--kbd (plist-get args :key))) 2275 (key (transient--kbd (plist-get args :key)))
2276 (proto (and cmd (transient--suffix-prototype cmd)))
2236 (level (or (alist-get (cons cmd key) levels nil nil #'equal) 2277 (level (or (alist-get (cons cmd key) levels nil nil #'equal)
2237 (alist-get cmd levels) 2278 (alist-get cmd levels)
2238 level))) 2279 level
2280 (and proto (oref proto level))
2281 transient--default-child-level)))
2239 (let ((fn (and (symbolp cmd) 2282 (let ((fn (and (symbolp cmd)
2240 (symbol-function cmd)))) 2283 (symbol-function cmd))))
2241 (when (autoloadp fn) 2284 (when (autoloadp fn)
@@ -2246,7 +2289,7 @@ value. Otherwise return CHILDREN as is.")
2246 (apply class :parent parent :level level args) 2289 (apply class :parent parent :level level args)
2247 (unless (and cmd (symbolp cmd)) 2290 (unless (and cmd (symbolp cmd))
2248 (error "BUG: Non-symbolic suffix command: %s" cmd)) 2291 (error "BUG: Non-symbolic suffix command: %s" cmd))
2249 (if-let* ((proto (and cmd (transient--suffix-prototype cmd)))) 2292 (if proto
2250 (apply #'clone proto :level level args) 2293 (apply #'clone proto :level level args)
2251 (apply class :command cmd :parent parent :level level 2294 (apply class :command cmd :parent parent :level level
2252 args))))) 2295 args)))))
@@ -2436,6 +2479,8 @@ value. Otherwise return CHILDREN as is.")
2436 (setq transient--redisplay-map nil) 2479 (setq transient--redisplay-map nil)
2437 (setq transient--redisplay-key nil) 2480 (setq transient--redisplay-key nil)
2438 (setq transient--helpp nil) 2481 (setq transient--helpp nil)
2482 (unless (eq transient--docsp 'permanent)
2483 (setq transient--docsp nil))
2439 (setq transient--editp nil) 2484 (setq transient--editp nil)
2440 (setq transient--prefix nil) 2485 (setq transient--prefix nil)
2441 (setq transient--layout nil) 2486 (setq transient--layout nil)
@@ -2563,7 +2608,13 @@ value. Otherwise return CHILDREN as is.")
2563 (let ((abort t)) 2608 (let ((abort t))
2564 (unwind-protect 2609 (unwind-protect
2565 (prog1 (let ((debugger #'transient--exit-and-debug)) 2610 (prog1 (let ((debugger #'transient--exit-and-debug))
2566 (advice-eval-interactive-spec spec)) 2611 (if-let* ((obj (transient-suffix-object suffix))
2612 (grp (oref obj parent))
2613 (adv (or (oref obj advice*)
2614 (oref grp advice*))))
2615 (funcall
2616 adv #'advice-eval-interactive-spec spec)
2617 (advice-eval-interactive-spec spec)))
2567 (setq abort nil)) 2618 (setq abort nil))
2568 (when abort 2619 (when abort
2569 (when-let* ((unwind (oref prefix unwind-suffix))) 2620 (when-let* ((unwind (oref prefix unwind-suffix)))
@@ -2573,7 +2624,14 @@ value. Otherwise return CHILDREN as is.")
2573 (oset prefix unwind-suffix nil)))))) 2624 (oset prefix unwind-suffix nil))))))
2574 (unwind-protect 2625 (unwind-protect
2575 (let ((debugger #'transient--exit-and-debug)) 2626 (let ((debugger #'transient--exit-and-debug))
2576 (apply fn args)) 2627 (if-let* ((obj (transient-suffix-object suffix))
2628 (grp (oref obj parent))
2629 (adv (or (oref obj advice)
2630 (oref grp advice)
2631 (oref obj advice*)
2632 (oref grp advice*))))
2633 (apply adv fn args)
2634 (apply fn args)))
2577 (when-let* ((unwind (oref prefix unwind-suffix))) 2635 (when-let* ((unwind (oref prefix unwind-suffix)))
2578 (transient--debug 'unwind-command) 2636 (transient--debug 'unwind-command)
2579 (funcall unwind suffix)) 2637 (funcall unwind suffix))
@@ -3212,12 +3270,21 @@ For example:
3212 (interactive) 3270 (interactive)
3213 (setq transient-show-common-commands (not transient-show-common-commands))) 3271 (setq transient-show-common-commands (not transient-show-common-commands)))
3214 3272
3215(transient-define-suffix transient-toggle-docstrings () 3273(transient-define-suffix transient-toggle-docstrings (&optional permanent)
3216 "Toggle whether to show docstrings instead of suffix descriptions. 3274 "Toggle whether to show docstrings instead of suffix descriptions.
3217To make this available in all menus, bind it in `transient-map'." 3275
3276By default this is only enabled temporarily for the current transient
3277menu invocation. With a prefix argument, enable this until explicitly
3278disabled again.
3279
3280Infix arguments are not affected by this, because otherwise many menus
3281would likely become unreadable. To make this command available in all
3282menus, bind it in `transient-map'. `transient-show-docstring-format'
3283controls how the docstrings are displayed and whether descriptions are
3284also displayed."
3218 :transient t 3285 :transient t
3219 (interactive) 3286 (interactive (list current-prefix-arg))
3220 (setq transient--docsp (not transient--docsp))) 3287 (setq transient--docsp (if permanent 'permanent (not transient--docsp))))
3221 3288
3222(defun transient-toggle-debug () 3289(defun transient-toggle-debug ()
3223 "Toggle debugging statements for transient commands." 3290 "Toggle debugging statements for transient commands."
@@ -3789,37 +3856,48 @@ a default implementation, which is a noop.")
3789 3856
3790;;;; Get 3857;;;; Get
3791 3858
3792(defun transient-scope (&optional prefixes) 3859(defun transient-scope (&optional prefixes classes)
3793 "Return the scope of the active or current transient prefix command. 3860 "Return the scope of the active or current transient prefix command.
3794 3861
3795If optional PREFIXES is nil, return the scope of the prefix currently 3862If optional PREFIXES and CLASSES are both nil, return the scope of
3796being setup, making this variant useful, e.g., in `:if*' predicates. 3863the prefix currently being setup, making this variation useful, e.g.,
3797If no prefix is being setup, but the current command was invoked from 3864in `:if*' predicates. If no prefix is being setup, but the current
3798some prefix, then return the scope of that. 3865command was invoked from some prefix, then return the scope of that.
3799
3800When this function is called from the body or `interactive' form of a
3801suffix command, PREFIXES should be non-nil.
3802 3866
3803If PREFIXES is non-nil, it must be a prefix command or a list of such 3867If PREFIXES is non-nil, it must be a prefix command or a list of such
3804commands. In this case try the following in order: 3868commands. If CLASSES is non-nil, it must be a prefix class or a list
3869of such classes. When this function is called from the body or the
3870`interactive' form of a suffix command, PREFIXES and/or CLASSES should
3871be non-nil. If either is non-nil, try the following in order:
3805 3872
3806- If the current suffix command was invoked from a prefix, which 3873- If the current suffix command was invoked from a prefix, which
3807 appears in PREFIXES, then return the scope of that prefix. 3874 appears in PREFIXES, return the scope of that prefix.
3875
3876- If the current suffix command was invoked from a prefix, and its
3877 class derives from one of the CLASSES, return the scope of that
3878 prefix.
3879
3880- If a prefix is being setup and it appears in PREFIXES, return its
3881 scope.
3808 3882
3809- If a prefix is being setup and it appears in PREFIXES, then return 3883- If a prefix is being setup and its class derives from one of the
3810 its scope. 3884 CLASSES, return its scope.
3811 3885
3812- Finally try to return the default scope of the first prefix in 3886- Finally try to return the default scope of the first command in
3813 PREFIXES. This only works if that slot is set in the respective 3887 PREFIXES. This only works if that slot is set in the respective
3814 class definition or using its `transient-init-scope' method. 3888 class definition or using its `transient-init-scope' method.
3815 3889
3816If no prefix matches, return nil." 3890If no prefix matches, return nil."
3817 (if prefixes 3891 (if (or prefixes classes)
3818 (let ((prefixes (ensure-list prefixes))) 3892 (let ((prefixes (ensure-list prefixes))
3819 (if-let* ((obj (or (and-let* ((obj transient-current-prefix)) 3893 (type (if (symbolp classes) classes (cons 'or classes))))
3820 (and (memq (oref obj command) prefixes) obj)) 3894 (if-let ((obj (cl-flet ((match (obj)
3821 (and-let* ((obj transient--prefix)) 3895 (and obj
3822 (and (memq (oref obj command) prefixes) obj))))) 3896 (or (memq (oref obj command) prefixes)
3897 (cl-typep obj type))
3898 obj)))
3899 (or (match transient-current-prefix)
3900 (match transient--prefix)))))
3823 (oref obj scope) 3901 (oref obj scope)
3824 (and (get (car prefixes) 'transient--prefix) 3902 (and (get (car prefixes) 'transient--prefix)
3825 (oref (transient--init-prefix (car prefixes)) scope)))) 3903 (oref (transient--init-prefix (car prefixes)) scope))))
@@ -4247,16 +4325,21 @@ face `transient-heading' to the complete string."
4247If the result is nil, then use \"(BUG: no description)\" as the 4325If the result is nil, then use \"(BUG: no description)\" as the
4248description. If the OBJ's `key' is currently unreachable, then 4326description. If the OBJ's `key' is currently unreachable, then
4249apply the face `transient-unreachable' to the complete string." 4327apply the face `transient-unreachable' to the complete string."
4250 (let ((desc (if-let* ((transient--docsp) 4328 (let ((desc (or (cl-call-next-method obj)
4251 (cmd (oref obj command)) 4329 (and (slot-boundp transient--prefix 'suffix-description)
4252 (doc (ignore-errors (documentation cmd))) 4330 (funcall (oref transient--prefix suffix-description)
4253 ((not (equal doc (documentation 4331 obj)))))
4254 'transient--default-infix-command))))) 4332 (when-let* ((transient--docsp)
4255 (substring doc 0 (string-match "\\.?\n" doc)) 4333 (cmd (oref obj command))
4256 (or (cl-call-next-method obj) 4334 ((not (memq 'transient--default-infix-command
4257 (and (slot-boundp transient--prefix 'suffix-description) 4335 (function-alias-p cmd))))
4258 (funcall (oref transient--prefix suffix-description) 4336 (docstr (ignore-errors (documentation cmd)))
4259 obj)))))) 4337 (docstr (string-trim
4338 (substring docstr 0 (string-match "\\.?\n" docstr))))
4339 ((not (equal docstr ""))))
4340 (setq desc (format-spec transient-show-docstring-format
4341 `((?c . ,desc)
4342 (?s . ,docstr)))))
4260 (if desc 4343 (if desc
4261 (when-let* ((face (transient--get-face obj 'face))) 4344 (when-let* ((face (transient--get-face obj 'face)))
4262 (setq desc (transient--add-face desc face t))) 4345 (setq desc (transient--add-face desc face t)))
@@ -4568,34 +4651,44 @@ Select the help window, and make the help buffer current and return it."
4568 (insert "\n")) 4651 (insert "\n"))
4569 (when transient--helpp 4652 (when transient--helpp
4570 (insert 4653 (insert
4571 (format (propertize "\ 4654 (format
4655 (propertize "\
4572Type a %s to show help for that suffix command, or %s to show manual. 4656Type a %s to show help for that suffix command, or %s to show manual.
4573Type %s to exit help.\n" 4657Type %s to exit help.\n"
4574 'face 'transient-heading) 4658 'face 'transient-heading)
4575 (propertize "<KEY>" 'face 'transient-key) 4659 (propertize "<KEY>" 'face 'transient-key)
4576 (propertize "?" 'face 'transient-key) 4660 (propertize "?" 'face 'transient-key)
4577 (propertize "C-g" 'face 'transient-key)))) 4661 (propertize "C-g" 'face 'transient-key))))
4578 (when transient--editp 4662 (when transient--editp
4579 (unless transient--helpp 4663 (unless transient--helpp
4580 (insert 4664 (insert
4581 (format (propertize "\ 4665 (format
4582Type a %s to set level for that suffix command. 4666 (propertize "\
4583Type %s to set what levels are available for this prefix command.\n" 4667Type %s and then %s to put the respective suffix command on level %s.
4584 'face 'transient-heading) 4668Type %s and then %s to display suffixes up to level %s in this menu.
4585 (propertize "<KEY>" 'face 'transient-key) 4669Type %s and then %s to describe the respective suffix command.\n"
4586 (propertize "C-x l" 'face 'transient-key)))) 4670 'face 'transient-heading)
4671 (propertize "<KEY>" 'face 'transient-key)
4672 (propertize "<N>" 'face 'transient-key)
4673 (propertize " N " 'face 'transient-enabled-suffix)
4674 (propertize "C-x l" 'face 'transient-key)
4675 (propertize "<N>" 'face 'transient-key)
4676 (propertize " N " 'face 'transient-enabled-suffix)
4677 (propertize "C-h" 'face 'transient-key)
4678 (propertize "<KEY>" 'face 'transient-key))))
4587 (with-slots (level) transient--prefix 4679 (with-slots (level) transient--prefix
4588 (insert 4680 (insert
4589 (format (propertize " 4681 (format
4590Suffixes on levels %s are available. 4682 (propertize "
4591Suffixes on levels %s and %s are unavailable.\n" 4683The current level of this menu is %s, so
4592 'face 'transient-heading) 4684 commands on levels %s are displayed, and
4593 (propertize (format "1-%s" level) 4685 commands on levels %s and %s are not displayed.\n"
4594 'face 'transient-enabled-suffix) 4686 'face 'transient-heading)
4595 (propertize " 0 " 4687 (propertize (format " %s " level) 'face 'transient-enabled-suffix)
4596 'face 'transient-disabled-suffix) 4688 (propertize (format " 1..%s " level) 'face 'transient-enabled-suffix)
4597 (propertize (format ">=%s" (1+ level)) 4689 (propertize (format " >= %s " (1+ level))
4598 'face 'transient-disabled-suffix)))))) 4690 'face 'transient-disabled-suffix)
4691 (propertize " 0 " 'face 'transient-disabled-suffix))))))
4599 4692
4600(cl-defgeneric transient-show-summary (obj &optional return) 4693(cl-defgeneric transient-show-summary (obj &optional return)
4601 "Show brief summary about the command at point in the echo area. 4694 "Show brief summary about the command at point in the echo area.