diff options
| author | Jonas Bernoulli | 2025-02-01 18:14:47 +0100 |
|---|---|---|
| committer | Jonas Bernoulli | 2025-02-01 18:14:47 +0100 |
| commit | 3a86774ce55e9dc4dc6de01f6aca19fcaa41a5d3 (patch) | |
| tree | 57dc39d0e5eed587f125e4fffd31da2163ad2ae9 | |
| parent | 5a5706f943ae2677c6d73fed8de11affd3ef04aa (diff) | |
| download | emacs-3a86774ce55e9dc4dc6de01f6aca19fcaa41a5d3.tar.gz emacs-3a86774ce55e9dc4dc6de01f6aca19fcaa41a5d3.zip | |
Update to Transient v0.8.4-7-gabee7353
| -rw-r--r-- | doc/misc/transient.texi | 138 | ||||
| -rw-r--r-- | lisp/transient.el | 227 |
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, | |||
| 53 | available at @uref{https://github.com/positron-solutions/transient-showcase}. | 53 | available at @uref{https://github.com/positron-solutions/transient-showcase}. |
| 54 | 54 | ||
| 55 | @noindent | 55 | @noindent |
| 56 | This manual is for Transient version 0.8.3. | 56 | This 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 | |||
| 553 | available anyway. | 554 | available anyway. |
| 554 | @end table | 555 | @end table |
| 555 | 556 | ||
| 557 | @defun transient-set-default-level suffix level | ||
| 558 | This function sets the default level of the suffix COMMAND to LEVEL@. | ||
| 559 | |||
| 560 | If a suffix command appears in multiple menus, it may make sense to | ||
| 561 | consistently change its level in all those menus at once. For | ||
| 562 | example, the @code{--gpg-sign} argument (which is implemented using the | ||
| 563 | command @code{magit:--gpg-sign}), is bound in all of Magit's menu which | ||
| 564 | create commits. Users who sometimes sign their commits would want | ||
| 565 | that argument to be available in all of these menus, while for users | ||
| 566 | who never sign it is just unnecessary noise in any menus. | ||
| 567 | |||
| 568 | To always make @code{--gpg-sign} available, use: | ||
| 569 | |||
| 570 | @lisp | ||
| 571 | (transient-set-default-level 'magit:--gpg-sign 1) | ||
| 572 | @end lisp | ||
| 573 | |||
| 574 | To never make @code{--gpg-sign} available, use: | ||
| 575 | |||
| 576 | @lisp | ||
| 577 | (transient-set-default-level 'magit:--gpg-sign 0) | ||
| 578 | @end lisp | ||
| 579 | |||
| 580 | This sets the level in the suffix prototype object for this command. | ||
| 581 | Commands only have a suffix prototype if they were defined using one | ||
| 582 | of @code{transient-define-argument}, @code{transient-define-infix} and | ||
| 583 | @code{transient-define-suffix}. For all other commands this would signal | ||
| 584 | an error. (This is one of the reasons why package authors should | ||
| 585 | use one of these functions to define shared suffix commands, and | ||
| 586 | especially shared arguments.) | ||
| 587 | |||
| 588 | If the user changes the level of a suffix in a particular menu, | ||
| 589 | using @kbd{C-x l} as shown above, then that obviously shadows the default. | ||
| 590 | |||
| 591 | It is also possible to set the level of a suffix binding in a | ||
| 592 | particular menu, either when defining the menu using | ||
| 593 | @code{transient-define-prefix,} or later using @code{transient-insert-suffix}. If | ||
| 594 | such bindings specify a level, then that also overrides the default. | ||
| 595 | (Per-suffix default levels is a new feature, so you might encounter | ||
| 596 | this 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. | |||
| 1323 | The boolean @code{:pad-keys} argument controls whether keys of all suffixes | 1367 | The boolean @code{:pad-keys} argument controls whether keys of all suffixes |
| 1324 | contained in a group are right padded, effectively aligning the | 1368 | contained in a group are right padded, effectively aligning the |
| 1325 | descriptions. | 1369 | descriptions. |
| 1370 | |||
| 1371 | @item | ||
| 1372 | If 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 | ||
| 1375 | supported. Inside group specifications, the use of @code{##} is not | ||
| 1376 | supported anywhere but directly following a keyword symbol. | ||
| 1326 | @end itemize | 1377 | @end itemize |
| 1327 | 1378 | ||
| 1328 | The @var{ELEMENT}s are either all subgroups, or all suffixes and strings. | 1379 | The @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 | |||
| 1446 | Each keyword has to be a keyword symbol, either @code{:class} or a keyword | 1497 | Each keyword has to be a keyword symbol, either @code{:class} or a keyword |
| 1447 | argument supported by the constructor of that class. @xref{Suffix Slots}. | 1498 | argument supported by the constructor of that class. @xref{Suffix Slots}. |
| 1448 | 1499 | ||
| 1500 | If a keyword argument accepts a function as value, you an use a @code{lambda} | ||
| 1501 | expression. As a special case, the @code{##} macro (which returns a @code{lambda} | ||
| 1502 | expression and is implemented in the @code{llama} package) is also supported. | ||
| 1503 | Inside suffix bindings, the use of @code{##} is not supported anywhere but | ||
| 1504 | directly 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 | |||
| 1568 | if the current command is not being invoked from @var{PREFIX}. | 1625 | if 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 | |||
| 1631 | Some transients have a sort of secondary value, called a scope. A | ||
| 1632 | prefix's scope can be accessed using @code{transient-scope}; similar to how | ||
| 1633 | its value can be accessed using @code{transient-args}. | ||
| 1634 | |||
| 1635 | @defun transient-scope prefixes classes | ||
| 1636 | This function returns the scope of the active or current transient | ||
| 1637 | prefix command. | ||
| 1638 | |||
| 1639 | If optional PREFIXES and CLASSES are both nil, return the scope of | ||
| 1640 | the prefix currently being setup, making this variation useful, e.g., | ||
| 1641 | in @code{:if*} predicates. If no prefix is being setup, but the current | ||
| 1642 | command was invoked from some prefix, then return the scope of that. | ||
| 1643 | |||
| 1644 | If PREFIXES is non-nil, it must be a prefix command or a list of such | ||
| 1645 | commands. If CLASSES is non-nil, it must be a prefix class or a list | ||
| 1646 | of 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 | ||
| 1648 | be non-nil. If either is non-nil, try the following in order: | ||
| 1649 | |||
| 1650 | @itemize | ||
| 1651 | @item | ||
| 1652 | If the current suffix command was invoked from a prefix, which | ||
| 1653 | appears in PREFIXES, return the scope of that prefix. | ||
| 1654 | |||
| 1655 | @item | ||
| 1656 | If the current suffix command was invoked from a prefix, and its | ||
| 1657 | class derives from one of the CLASSES, return the scope of that | ||
| 1658 | prefix. | ||
| 1659 | |||
| 1660 | @item | ||
| 1661 | If a prefix is being setup and it appears in PREFIXES, return its | ||
| 1662 | scope. | ||
| 1663 | |||
| 1664 | @item | ||
| 1665 | If a prefix is being setup and its class derives from one of the | ||
| 1666 | CLASSES, return its scope. | ||
| 1667 | |||
| 1668 | @item | ||
| 1669 | Finally try to return the default scope of the first command in | ||
| 1670 | PREFIXES@. This only works if that slot is set in the respective | ||
| 1671 | class definition or using its `transient-init-scope' method. | ||
| 1672 | @end itemize | ||
| 1673 | |||
| 1674 | If 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 |
| 2462 | allows aligning columns across separate instances of that. | 2568 | allows aligning columns across separate instances of that. A list |
| 2569 | of 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 | ||
| 2537 | This is the abstract superclass of @code{transient-suffix} and @code{transient-group}. | 2644 | This is the abstract superclass of @code{transient-suffix} and @code{transient-group}. |
| 2538 | This is where the shared @code{if*} and @code{inapt-if*} slots (see @ref{Predicate Slots}) | 2645 | This is where the shared @code{if*} and @code{inapt-if*} slots (see @ref{Predicate Slots}), |
| 2539 | and the @code{level} slot (see @ref{Enabling and Disabling Suffixes}) are defined. | 2646 | the @code{level} slot (see @ref{Enabling and Disabling Suffixes}), and the @code{advice} |
| 2647 | and @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. | |||
| 2595 | defining a command using @code{transient-define-suffix}. | 2703 | defining a command using @code{transient-define-suffix}. |
| 2596 | @end itemize | 2704 | @end itemize |
| 2597 | 2705 | ||
| 2706 | The following two slots are experimental. They can also be set for a | ||
| 2707 | group, in which case they apply to all suffixes in that group, except | ||
| 2708 | for 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 | ||
| 2713 | using @code{(apply advice command args)}, i.e., it behaves like an "around" | ||
| 2714 | advice. | ||
| 2715 | |||
| 2716 | @item | ||
| 2717 | @code{advice*} A function used to advise the command. Unlike @code{advice}, this | ||
| 2718 | advises not only the command body but also its @code{interactive} spec. If | ||
| 2719 | both slots are non-nil, @code{advice} is used for the body and @code{advice*} is | ||
| 2720 | used for the @code{interactive} form. When advising the @code{interactive} spec, | ||
| 2721 | called 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 | |||
| 287 | The command `transient-toggle-docstrings' toggles between showing suffix | ||
| 288 | descriptions as usual, and instead or additionally displaying the suffix | ||
| 289 | docstrings. The format specified here controls how that is done. %c is | ||
| 290 | the description and %s is the docstring. Use \"%-14c %s\" or similar to | ||
| 291 | display both. | ||
| 292 | |||
| 293 | This 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 | ||
| 785 | It is undefined which predicates are used if more than one `if*' | 807 | It 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 | |||
| 1560 | The default level is shadowed if the binding of the suffix in a | ||
| 1561 | prefix menu specifies a level, and also if the user changes the | ||
| 1562 | level of such a binding. | ||
| 1563 | |||
| 1564 | The default level can only be set for commands that were defined | ||
| 1565 | using `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. |
| 3217 | To make this available in all menus, bind it in `transient-map'." | 3275 | |
| 3276 | By default this is only enabled temporarily for the current transient | ||
| 3277 | menu invocation. With a prefix argument, enable this until explicitly | ||
| 3278 | disabled again. | ||
| 3279 | |||
| 3280 | Infix arguments are not affected by this, because otherwise many menus | ||
| 3281 | would likely become unreadable. To make this command available in all | ||
| 3282 | menus, bind it in `transient-map'. `transient-show-docstring-format' | ||
| 3283 | controls how the docstrings are displayed and whether descriptions are | ||
| 3284 | also 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 | ||
| 3795 | If optional PREFIXES is nil, return the scope of the prefix currently | 3862 | If optional PREFIXES and CLASSES are both nil, return the scope of |
| 3796 | being setup, making this variant useful, e.g., in `:if*' predicates. | 3863 | the prefix currently being setup, making this variation useful, e.g., |
| 3797 | If no prefix is being setup, but the current command was invoked from | 3864 | in `:if*' predicates. If no prefix is being setup, but the current |
| 3798 | some prefix, then return the scope of that. | 3865 | command was invoked from some prefix, then return the scope of that. |
| 3799 | |||
| 3800 | When this function is called from the body or `interactive' form of a | ||
| 3801 | suffix command, PREFIXES should be non-nil. | ||
| 3802 | 3866 | ||
| 3803 | If PREFIXES is non-nil, it must be a prefix command or a list of such | 3867 | If PREFIXES is non-nil, it must be a prefix command or a list of such |
| 3804 | commands. In this case try the following in order: | 3868 | commands. If CLASSES is non-nil, it must be a prefix class or a list |
| 3869 | of such classes. When this function is called from the body or the | ||
| 3870 | `interactive' form of a suffix command, PREFIXES and/or CLASSES should | ||
| 3871 | be 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 | ||
| 3816 | If no prefix matches, return nil." | 3890 | If 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." | |||
| 4247 | If the result is nil, then use \"(BUG: no description)\" as the | 4325 | If the result is nil, then use \"(BUG: no description)\" as the |
| 4248 | description. If the OBJ's `key' is currently unreachable, then | 4326 | description. If the OBJ's `key' is currently unreachable, then |
| 4249 | apply the face `transient-unreachable' to the complete string." | 4327 | apply 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 "\ | ||
| 4572 | Type a %s to show help for that suffix command, or %s to show manual. | 4656 | Type a %s to show help for that suffix command, or %s to show manual. |
| 4573 | Type %s to exit help.\n" | 4657 | Type %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 |
| 4582 | Type a %s to set level for that suffix command. | 4666 | (propertize "\ |
| 4583 | Type %s to set what levels are available for this prefix command.\n" | 4667 | Type %s and then %s to put the respective suffix command on level %s. |
| 4584 | 'face 'transient-heading) | 4668 | Type %s and then %s to display suffixes up to level %s in this menu. |
| 4585 | (propertize "<KEY>" 'face 'transient-key) | 4669 | Type %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 |
| 4590 | Suffixes on levels %s are available. | 4682 | (propertize " |
| 4591 | Suffixes on levels %s and %s are unavailable.\n" | 4683 | The 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. |