diff options
| author | Jonas Bernoulli | 2023-08-25 22:22:47 +0200 |
|---|---|---|
| committer | Jonas Bernoulli | 2023-08-27 14:47:14 +0200 |
| commit | 45cf3a0cede6662418bbab4897a2f04a9ef9c962 (patch) | |
| tree | cd15bd4ebe792173b7e42eac30549f95e547c9d3 | |
| parent | 31d3808fb9df98b75d8b199885cc9875f26a9215 (diff) | |
| download | emacs-45cf3a0cede6662418bbab4897a2f04a9ef9c962.tar.gz emacs-45cf3a0cede6662418bbab4897a2f04a9ef9c962.zip | |
Update to Transient v0.4.3
| -rw-r--r-- | doc/misc/transient.texi | 66 | ||||
| -rw-r--r-- | lisp/transient.el | 205 |
2 files changed, 128 insertions, 143 deletions
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi index be9e8698ab4..e6144dcf2bc 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.4.1 | 34 | @subtitle for version 0.4.3 |
| 35 | @author Jonas Bernoulli | 35 | @author Jonas Bernoulli |
| 36 | @page | 36 | @page |
| 37 | @vskip 0pt plus 1filll | 37 | @vskip 0pt plus 1filll |
| @@ -74,7 +74,7 @@ that hurdle is Psionic K's interactive tutorial, available at | |||
| 74 | @end quotation | 74 | @end quotation |
| 75 | 75 | ||
| 76 | @noindent | 76 | @noindent |
| 77 | This manual is for Transient version 0.4.1. | 77 | This manual is for Transient version 0.4.3. |
| 78 | 78 | ||
| 79 | @insertcopying | 79 | @insertcopying |
| 80 | @end ifnottex | 80 | @end ifnottex |
| @@ -248,18 +248,18 @@ When using Transient, one can call a command with arguments that are | |||
| 248 | just as complex as when calling the same function non-interactively | 248 | just as complex as when calling the same function non-interactively |
| 249 | from Lisp. | 249 | from Lisp. |
| 250 | 250 | ||
| 251 | Invoking a transient command with arguments is similar to invoking a | 251 | Invoking a transient suffix command with arguments is similar to |
| 252 | command in a shell with command-line completion and history enabled. | 252 | invoking a command in a shell with command-line completion and history |
| 253 | One benefit of the Transient interface is that it remembers history | 253 | enabled. One benefit of the Transient interface is that it remembers |
| 254 | not only on a global level (“this command was invoked using these | 254 | history not only on a global level (“this command was invoked using |
| 255 | arguments, and previously it was invoked using those other arguments”), | 255 | these arguments, and previously it was invoked using those other |
| 256 | but also remembers the values of individual arguments independently. | 256 | arguments”), but also remembers the values of individual arguments |
| 257 | @xref{Using History}. | 257 | independently. See @xref{Using History}. |
| 258 | 258 | ||
| 259 | After a transient prefix command is invoked, @kbd{C-h @var{KEY}} can be used to | 259 | After a transient prefix command is invoked, @kbd{C-h @var{KEY}} can be used to |
| 260 | show the documentation for the infix or suffix command that @kbd{@var{KEY}} is | 260 | show the documentation for the infix or suffix command that @kbd{@var{KEY}} is |
| 261 | bound to (@pxref{Getting Help for Suffix Commands}), and infixes and | 261 | bound to (see @ref{Getting Help for Suffix Commands}), and infixes and |
| 262 | suffixes can be removed from the transient using @kbd{C-x l @var{KEY}}. Infixes | 262 | suffixes can be removed from the transient using @kbd{C-x l @var{KEY}}. Infixes |
| 263 | and suffixes that are disabled by default can be enabled the same way. | 263 | and suffixes that are disabled by default can be enabled the same way. |
| 264 | @xref{Enabling and Disabling Suffixes}. | 264 | @xref{Enabling and Disabling Suffixes}. |
| 265 | 265 | ||
| @@ -270,21 +270,26 @@ Additionally, Transient provides abstractions for defining new types, | |||
| 270 | which the author of Transient did not anticipate (or didn't get around | 270 | which the author of Transient did not anticipate (or didn't get around |
| 271 | to implementing yet). | 271 | to implementing yet). |
| 272 | 272 | ||
| 273 | Note that suffix commands also support regular prefix arguments. A | ||
| 274 | suffix command may even be called with both infix and prefix arguments | ||
| 275 | at the same time. If you invoke a command as a suffix of a transient | ||
| 276 | prefix command, but also want to pass prefix arguments to it, then | ||
| 277 | first invoke the prefix command, and only after doing that invoke the | ||
| 278 | prefix arguments, before finally invoking the suffix command. If you | ||
| 279 | instead began by providing the prefix arguments, then those would | ||
| 280 | apply to the prefix command, not the suffix command. Likewise, if you | ||
| 281 | want to change infix arguments before invoking a suffix command with | ||
| 282 | prefix arguments, then change the infix arguments before invoking the | ||
| 283 | prefix arguments. In other words, regular prefix arguments always | ||
| 284 | apply to the next command, and since transient prefix, infix and | ||
| 285 | suffix commands are just regular commands, the same applies to them. | ||
| 286 | (Regular prefix keys behave differently because they are not commands | ||
| 287 | at all, instead they are just incomplete key sequences, and those | ||
| 288 | cannot be interrupted with prefix commands.) | ||
| 289 | |||
| 273 | @node Usage | 290 | @node Usage |
| 274 | @chapter Usage | 291 | @chapter Usage |
| 275 | 292 | ||
| 276 | @menu | ||
| 277 | * Invoking Transients:: | ||
| 278 | * Aborting and Resuming Transients:: | ||
| 279 | * Common Suffix Commands:: | ||
| 280 | * Saving Values:: | ||
| 281 | * Using History:: | ||
| 282 | * Getting Help for Suffix Commands:: | ||
| 283 | * Enabling and Disabling Suffixes:: | ||
| 284 | * Other Commands:: | ||
| 285 | * Configuration:: | ||
| 286 | @end menu | ||
| 287 | |||
| 288 | @node Invoking Transients | 293 | @node Invoking Transients |
| 289 | @section Invoking Transients | 294 | @section Invoking Transients |
| 290 | 295 | ||
| @@ -997,14 +1002,6 @@ signal an error. | |||
| 997 | @node Defining New Commands | 1002 | @node Defining New Commands |
| 998 | @chapter Defining New Commands | 1003 | @chapter Defining New Commands |
| 999 | 1004 | ||
| 1000 | @menu | ||
| 1001 | * Defining Transients:: | ||
| 1002 | * Binding Suffix and Infix Commands:: | ||
| 1003 | * Defining Suffix and Infix Commands:: | ||
| 1004 | * Using Infix Arguments:: | ||
| 1005 | * Transient State:: | ||
| 1006 | @end menu | ||
| 1007 | |||
| 1008 | @node Defining Transients | 1005 | @node Defining Transients |
| 1009 | @section Defining Transients | 1006 | @section Defining Transients |
| 1010 | 1007 | ||
| @@ -2234,11 +2231,6 @@ available depending on user preference. | |||
| 2234 | @node Related Abstractions and Packages | 2231 | @node Related Abstractions and Packages |
| 2235 | @chapter Related Abstractions and Packages | 2232 | @chapter Related Abstractions and Packages |
| 2236 | 2233 | ||
| 2237 | @menu | ||
| 2238 | * Comparison With Prefix Keys and Prefix Arguments:: | ||
| 2239 | * Comparison With Other Packages:: | ||
| 2240 | @end menu | ||
| 2241 | |||
| 2242 | @node Comparison With Prefix Keys and Prefix Arguments | 2234 | @node Comparison With Prefix Keys and Prefix Arguments |
| 2243 | @section Comparison With Prefix Keys and Prefix Arguments | 2235 | @section Comparison With Prefix Keys and Prefix Arguments |
| 2244 | 2236 | ||
| @@ -2559,8 +2551,6 @@ currently exist. | |||
| 2559 | @node FAQ | 2551 | @node FAQ |
| 2560 | @appendix FAQ | 2552 | @appendix FAQ |
| 2561 | 2553 | ||
| 2562 | |||
| 2563 | |||
| 2564 | @anchor{Can I control how the popup buffer is displayed?} | 2554 | @anchor{Can I control how the popup buffer is displayed?} |
| 2565 | @appendixsec Can I control how the popup buffer is displayed? | 2555 | @appendixsec Can I control how the popup buffer is displayed? |
| 2566 | 2556 | ||
diff --git a/lisp/transient.el b/lisp/transient.el index 048554eee13..52c21871548 100644 --- a/lisp/transient.el +++ b/lisp/transient.el | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | ;; URL: https://github.com/magit/transient | 6 | ;; URL: https://github.com/magit/transient |
| 7 | ;; Keywords: extensions | 7 | ;; Keywords: extensions |
| 8 | 8 | ||
| 9 | ;; Package-Version: 0.4.1 | 9 | ;; Package-Version: 0.4.3 |
| 10 | ;; Package-Requires: ((emacs "26.1")) | 10 | ;; Package-Requires: ((emacs "26.1")) |
| 11 | 11 | ||
| 12 | ;; SPDX-License-Identifier: GPL-3.0-or-later | 12 | ;; SPDX-License-Identifier: GPL-3.0-or-later |
| @@ -67,6 +67,7 @@ | |||
| 67 | 67 | ||
| 68 | (defvar display-line-numbers) ; since Emacs 26.1 | 68 | (defvar display-line-numbers) ; since Emacs 26.1 |
| 69 | (defvar Man-notify-method) | 69 | (defvar Man-notify-method) |
| 70 | (defvar pp-default-function) ; since Emacs 29.1 | ||
| 70 | 71 | ||
| 71 | (defmacro transient--with-emergency-exit (&rest body) | 72 | (defmacro transient--with-emergency-exit (&rest body) |
| 72 | (declare (indent defun)) | 73 | (declare (indent defun)) |
| @@ -565,7 +566,9 @@ the previous prefix." | |||
| 565 | (setq list (cl-sort (copy-sequence list) #'string< :key #'car)) | 566 | (setq list (cl-sort (copy-sequence list) #'string< :key #'car)) |
| 566 | (with-temp-file file | 567 | (with-temp-file file |
| 567 | (let ((print-level nil) | 568 | (let ((print-level nil) |
| 568 | (print-length nil)) | 569 | (print-length nil) |
| 570 | (pp-default-function 'pp-28) | ||
| 571 | (fill-column 999)) | ||
| 569 | (pp list (current-buffer))))) | 572 | (pp list (current-buffer))))) |
| 570 | 573 | ||
| 571 | (defvar transient-values | 574 | (defvar transient-values |
| @@ -953,7 +956,7 @@ keyword. | |||
| 953 | (pcase-let ((`(,class ,slots ,_ ,docstr ,_) | 956 | (pcase-let ((`(,class ,slots ,_ ,docstr ,_) |
| 954 | (transient--expand-define-args args arglist))) | 957 | (transient--expand-define-args args arglist))) |
| 955 | `(progn | 958 | `(progn |
| 956 | (defalias ',name ,(transient--default-infix-command)) | 959 | (defalias ',name #'transient--default-infix-command) |
| 957 | (put ',name 'interactive-only t) | 960 | (put ',name 'interactive-only t) |
| 958 | (put ',name 'command-modes (list 'not-a-mode)) | 961 | (put ',name 'command-modes (list 'not-a-mode)) |
| 959 | (put ',name 'function-documentation ,docstr) | 962 | (put ',name 'function-documentation ,docstr) |
| @@ -969,6 +972,15 @@ example, sets a variable, use `transient-define-infix' instead. | |||
| 969 | 972 | ||
| 970 | \(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]...)") | 973 | \(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]...)") |
| 971 | 974 | ||
| 975 | (defun transient--default-infix-command () | ||
| 976 | "Most transient infix commands are but an alias for this command." | ||
| 977 | (interactive) | ||
| 978 | (let ((obj (transient-suffix-object))) | ||
| 979 | (transient-infix-set obj (transient-infix-read obj))) | ||
| 980 | (transient--show)) | ||
| 981 | (put 'transient--default-infix-command 'interactive-only t) | ||
| 982 | (put 'transient--default-infix-command 'command-modes (list 'not-a-mode)) | ||
| 983 | |||
| 972 | (defun transient--expand-define-args (args &optional arglist) | 984 | (defun transient--expand-define-args (args &optional arglist) |
| 973 | (unless (listp arglist) | 985 | (unless (listp arglist) |
| 974 | (error "Mandatory ARGLIST is missing")) | 986 | (error "Mandatory ARGLIST is missing")) |
| @@ -1071,11 +1083,16 @@ example, sets a variable, use `transient-define-infix' instead. | |||
| 1071 | (if (and desc (or (stringp desc) (symbolp desc))) | 1083 | (if (and desc (or (stringp desc) (symbolp desc))) |
| 1072 | desc | 1084 | desc |
| 1073 | (plist-get args :key))))))) | 1085 | (plist-get args :key))))))) |
| 1074 | (setq args (plist-put args :command | 1086 | (setq args (plist-put |
| 1075 | `(defalias ',sym ,(macroexp-quote cmd)))))) | 1087 | args :command |
| 1088 | `(prog1 ',sym | ||
| 1089 | (put ',sym 'interactive-only t) | ||
| 1090 | (put ',sym 'command-modes (list 'not-a-mode)) | ||
| 1091 | (defalias ',sym ,(macroexp-quote cmd))))))) | ||
| 1076 | ((or (stringp car) | 1092 | ((or (stringp car) |
| 1077 | (and car (listp car))) | 1093 | (and car (listp car))) |
| 1078 | (let ((arg pop)) | 1094 | (let ((arg pop) |
| 1095 | (sym nil)) | ||
| 1079 | (cl-typecase arg | 1096 | (cl-typecase arg |
| 1080 | (list | 1097 | (list |
| 1081 | (setq args (plist-put args :shortarg (car arg))) | 1098 | (setq args (plist-put args :shortarg (car arg))) |
| @@ -1085,9 +1102,13 @@ example, sets a variable, use `transient-define-infix' instead. | |||
| 1085 | (when-let ((shortarg (transient--derive-shortarg arg))) | 1102 | (when-let ((shortarg (transient--derive-shortarg arg))) |
| 1086 | (setq args (plist-put args :shortarg shortarg))) | 1103 | (setq args (plist-put args :shortarg shortarg))) |
| 1087 | (setq args (plist-put args :argument arg)))) | 1104 | (setq args (plist-put args :argument arg)))) |
| 1088 | (setq args (plist-put args :command | 1105 | (setq sym (intern (format "transient:%s:%s" prefix arg))) |
| 1089 | (list 'quote (intern (format "transient:%s:%s" | 1106 | (setq args (plist-put |
| 1090 | prefix arg))))) | 1107 | args :command |
| 1108 | `(prog1 ',sym | ||
| 1109 | (put ',sym 'interactive-only t) | ||
| 1110 | (put ',sym 'command-modes (list 'not-a-mode)) | ||
| 1111 | (defalias ',sym #'transient--default-infix-command)))) | ||
| 1091 | (cond ((and car (not (keywordp car))) | 1112 | (cond ((and car (not (keywordp car))) |
| 1092 | (setq class 'transient-option) | 1113 | (setq class 'transient-option) |
| 1093 | (setq args (plist-put args :reader (macroexp-quote pop)))) | 1114 | (setq args (plist-put args :reader (macroexp-quote pop)))) |
| @@ -1116,26 +1137,6 @@ example, sets a variable, use `transient-define-infix' instead. | |||
| 1116 | (macroexp-quote (or class 'transient-suffix)) | 1137 | (macroexp-quote (or class 'transient-suffix)) |
| 1117 | (cons 'list args)))) | 1138 | (cons 'list args)))) |
| 1118 | 1139 | ||
| 1119 | (defun transient--default-infix-command () | ||
| 1120 | (cons 'lambda | ||
| 1121 | '(() | ||
| 1122 | (interactive) | ||
| 1123 | (let ((obj (transient-suffix-object))) | ||
| 1124 | (transient-infix-set obj (transient-infix-read obj))) | ||
| 1125 | (transient--show)))) | ||
| 1126 | |||
| 1127 | (defun transient--ensure-infix-command (obj) | ||
| 1128 | (let ((cmd (oref obj command))) | ||
| 1129 | (unless (or (commandp cmd) | ||
| 1130 | (get cmd 'transient--infix-command)) | ||
| 1131 | (if (or (cl-typep obj 'transient-switch) | ||
| 1132 | (cl-typep obj 'transient-option)) | ||
| 1133 | (put cmd 'transient--infix-command | ||
| 1134 | (transient--default-infix-command)) | ||
| 1135 | ;; This is not an anonymous infix argument. | ||
| 1136 | (when (transient--use-suffix-p obj) | ||
| 1137 | (error "Suffix %s is not defined or autoloaded as a command" cmd)))))) | ||
| 1138 | |||
| 1139 | (defun transient--derive-shortarg (arg) | 1140 | (defun transient--derive-shortarg (arg) |
| 1140 | (save-match-data | 1141 | (save-match-data |
| 1141 | (and (string-match "\\`\\(-[a-zA-Z]\\)\\(\\'\\|=\\)" arg) | 1142 | (and (string-match "\\`\\(-[a-zA-Z]\\)\\(\\'\\|=\\)" arg) |
| @@ -1420,11 +1421,11 @@ Each suffix commands is associated with an object, which holds | |||
| 1420 | additional information about the suffix, such as its value (in | 1421 | additional information about the suffix, such as its value (in |
| 1421 | the case of an infix command, which is a kind of suffix command). | 1422 | the case of an infix command, which is a kind of suffix command). |
| 1422 | 1423 | ||
| 1423 | This function is intended to be called by infix commands, whose | 1424 | This function is intended to be called by infix commands, which |
| 1424 | command definition usually (at least when defined using | 1425 | are usually aliases of `transient--default-infix-command', which |
| 1425 | `transient-define-infix') is this: | 1426 | is defined like this: |
| 1426 | 1427 | ||
| 1427 | (lambda () | 1428 | (defun transient--default-infix-command () |
| 1428 | (interactive) | 1429 | (interactive) |
| 1429 | (let ((obj (transient-suffix-object))) | 1430 | (let ((obj (transient-suffix-object))) |
| 1430 | (transient-infix-set obj (transient-infix-read obj))) | 1431 | (transient-infix-set obj (transient-infix-read obj))) |
| @@ -1441,7 +1442,7 @@ commands) may also need the object to guide their behavior. | |||
| 1441 | This function attempts to return the object associated with the | 1442 | This function attempts to return the object associated with the |
| 1442 | current suffix command even if the suffix command was not invoked | 1443 | current suffix command even if the suffix command was not invoked |
| 1443 | from a transient. (For some suffix command that is a valid thing | 1444 | from a transient. (For some suffix command that is a valid thing |
| 1444 | to do, for others it is not.) In that case nil may be returned | 1445 | to do, for others it is not.) In that case nil may be returned, |
| 1445 | if the command was not defined using one of the macros intended | 1446 | if the command was not defined using one of the macros intended |
| 1446 | to define such commands. | 1447 | to define such commands. |
| 1447 | 1448 | ||
| @@ -1457,7 +1458,7 @@ probably use this instead: | |||
| 1457 | (let ((suffixes | 1458 | (let ((suffixes |
| 1458 | (cl-remove-if-not | 1459 | (cl-remove-if-not |
| 1459 | (lambda (obj) | 1460 | (lambda (obj) |
| 1460 | (eq (transient--suffix-command obj) | 1461 | (eq (oref obj command) |
| 1461 | (or command | 1462 | (or command |
| 1462 | (if (eq this-command 'transient-set-level) | 1463 | (if (eq this-command 'transient-set-level) |
| 1463 | ;; This is how it can look up for which | 1464 | ;; This is how it can look up for which |
| @@ -1480,38 +1481,6 @@ probably use this instead: | |||
| 1480 | (transient-init-value obj) | 1481 | (transient-init-value obj) |
| 1481 | obj))) | 1482 | obj))) |
| 1482 | 1483 | ||
| 1483 | (defun transient--suffix-command (object) | ||
| 1484 | "Return the command represented by OBJECT. | ||
| 1485 | |||
| 1486 | If the value of OBJECT's `command' slot is a command, then return | ||
| 1487 | that. Otherwise it is a symbol whose `transient--infix-command' | ||
| 1488 | property holds an anonymous command, which is returned instead." | ||
| 1489 | (cl-check-type object transient-suffix) | ||
| 1490 | (let ((sym (oref object command))) | ||
| 1491 | (if (commandp sym) | ||
| 1492 | sym | ||
| 1493 | (get sym 'transient--infix-command)))) | ||
| 1494 | |||
| 1495 | (defun transient--suffix-symbol (arg) | ||
| 1496 | "Return a symbol representing ARG. | ||
| 1497 | |||
| 1498 | ARG must be a command and/or a symbol. If it is a symbol, | ||
| 1499 | then just return it. Otherwise return the symbol whose | ||
| 1500 | `transient--infix-command' property's value is ARG." | ||
| 1501 | (or (cl-typep arg 'command) | ||
| 1502 | (cl-typep arg 'symbol) | ||
| 1503 | (signal 'wrong-type-argument `((command symbol) ,arg))) | ||
| 1504 | (if (symbolp arg) | ||
| 1505 | arg | ||
| 1506 | (let* ((obj (transient-suffix-object)) | ||
| 1507 | (sym (oref obj command))) | ||
| 1508 | (if (eq (get sym 'transient--infix-command) arg) | ||
| 1509 | sym | ||
| 1510 | (catch 'found | ||
| 1511 | (mapatoms (lambda (sym) | ||
| 1512 | (when (eq (get sym 'transient--infix-command) arg) | ||
| 1513 | (throw 'found sym))))))))) | ||
| 1514 | |||
| 1515 | ;;; Keymaps | 1484 | ;;; Keymaps |
| 1516 | 1485 | ||
| 1517 | (defvar-keymap transient-base-map | 1486 | (defvar-keymap transient-base-map |
| @@ -1709,7 +1678,7 @@ of the corresponding object." | |||
| 1709 | (funcall transient-substitute-key-function obj))) | 1678 | (funcall transient-substitute-key-function obj))) |
| 1710 | (oset obj key key)) | 1679 | (oset obj key key)) |
| 1711 | (let ((kbd (kbd key)) | 1680 | (let ((kbd (kbd key)) |
| 1712 | (cmd (transient--suffix-command obj))) | 1681 | (cmd (oref obj command))) |
| 1713 | (when-let ((conflict (and transient-detect-key-conflicts | 1682 | (when-let ((conflict (and transient-detect-key-conflicts |
| 1714 | (transient--lookup-key map kbd)))) | 1683 | (transient--lookup-key map kbd)))) |
| 1715 | (unless (eq cmd conflict) | 1684 | (unless (eq cmd conflict) |
| @@ -1737,13 +1706,12 @@ of the corresponding object." | |||
| 1737 | (keymap-set map "<handle-switch-frame>" #'transient--do-suspend)) | 1706 | (keymap-set map "<handle-switch-frame>" #'transient--do-suspend)) |
| 1738 | (dolist (obj transient--suffixes) | 1707 | (dolist (obj transient--suffixes) |
| 1739 | (let* ((cmd (oref obj command)) | 1708 | (let* ((cmd (oref obj command)) |
| 1740 | (sub-prefix (and (symbolp cmd) (get cmd 'transient--prefix) t)) | 1709 | (sub-prefix (and (symbolp cmd) (get cmd 'transient--prefix) t))) |
| 1741 | (sym (transient--suffix-symbol cmd))) | ||
| 1742 | (cond | 1710 | (cond |
| 1743 | ((oref obj inapt) | 1711 | ((oref obj inapt) |
| 1744 | (define-key map (vector sym) #'transient--do-warn-inapt)) | 1712 | (define-key map (vector cmd) #'transient--do-warn-inapt)) |
| 1745 | ((slot-boundp obj 'transient) | 1713 | ((slot-boundp obj 'transient) |
| 1746 | (define-key map (vector sym) | 1714 | (define-key map (vector cmd) |
| 1747 | (let ((do (oref obj transient))) | 1715 | (let ((do (oref obj transient))) |
| 1748 | (pcase (list do sub-prefix) | 1716 | (pcase (list do sub-prefix) |
| 1749 | ('(t t) #'transient--do-recurse) | 1717 | ('(t t) #'transient--do-recurse) |
| @@ -1753,8 +1721,8 @@ of the corresponding object." | |||
| 1753 | ('(nil t) #'transient--do-replace) | 1721 | ('(nil t) #'transient--do-replace) |
| 1754 | ('(nil nil) #'transient--do-exit) | 1722 | ('(nil nil) #'transient--do-exit) |
| 1755 | (_ do))))) | 1723 | (_ do))))) |
| 1756 | ((not (lookup-key transient-predicate-map (vector sym))) | 1724 | ((not (lookup-key transient-predicate-map (vector cmd))) |
| 1757 | (define-key map (vector sym) | 1725 | (define-key map (vector cmd) |
| 1758 | (if sub-prefix | 1726 | (if sub-prefix |
| 1759 | #'transient--do-replace | 1727 | #'transient--do-replace |
| 1760 | (or (oref transient--prefix transient-suffix) | 1728 | (or (oref transient--prefix transient-suffix) |
| @@ -1904,21 +1872,28 @@ value. Otherwise return CHILDREN as is." | |||
| 1904 | (defun transient--init-suffix (levels spec) | 1872 | (defun transient--init-suffix (levels spec) |
| 1905 | (pcase-let* ((`(,level ,class ,args) spec) | 1873 | (pcase-let* ((`(,level ,class ,args) spec) |
| 1906 | (cmd (plist-get args :command)) | 1874 | (cmd (plist-get args :command)) |
| 1907 | (level (or (alist-get (transient--suffix-symbol cmd) levels) | 1875 | (level (or (alist-get cmd levels) level))) |
| 1908 | level))) | ||
| 1909 | (let ((fn (and (symbolp cmd) | 1876 | (let ((fn (and (symbolp cmd) |
| 1910 | (symbol-function cmd)))) | 1877 | (symbol-function cmd)))) |
| 1911 | (when (autoloadp fn) | 1878 | (when (autoloadp fn) |
| 1912 | (transient--debug " autoload %s" cmd) | 1879 | (transient--debug " autoload %s" cmd) |
| 1913 | (autoload-do-load fn))) | 1880 | (autoload-do-load fn))) |
| 1914 | (when (transient--use-level-p level) | 1881 | (when (transient--use-level-p level) |
| 1915 | (let ((obj (if-let ((proto (and cmd | 1882 | (unless (and cmd (symbolp cmd)) |
| 1916 | (symbolp cmd) | 1883 | (error "BUG: Non-symbolic suffix command: %s" cmd)) |
| 1917 | (get cmd 'transient--suffix)))) | 1884 | (let ((obj (if-let ((proto (get cmd 'transient--suffix))) |
| 1918 | (apply #'clone proto :level level args) | 1885 | (apply #'clone proto :level level args) |
| 1919 | (apply class :level level args)))) | 1886 | (apply class :command cmd :level level args)))) |
| 1887 | (cond ((commandp cmd)) | ||
| 1888 | ((or (cl-typep obj 'transient-switch) | ||
| 1889 | (cl-typep obj 'transient-option)) | ||
| 1890 | ;; As a temporary special case, if the package was compiled | ||
| 1891 | ;; with an older version of Transient, then we must define | ||
| 1892 | ;; "anonymous" switch and option commands here. | ||
| 1893 | (defalias cmd #'transient--default-infix-command)) | ||
| 1894 | ((transient--use-suffix-p obj) | ||
| 1895 | (error "Suffix command %s is not defined or autoloaded" cmd))) | ||
| 1920 | (transient--init-suffix-key obj) | 1896 | (transient--init-suffix-key obj) |
| 1921 | (transient--ensure-infix-command obj) | ||
| 1922 | (when (transient--use-suffix-p obj) | 1897 | (when (transient--use-suffix-p obj) |
| 1923 | (if (transient--inapt-suffix-p obj) | 1898 | (if (transient--inapt-suffix-p obj) |
| 1924 | (oset obj inapt t) | 1899 | (oset obj inapt t) |
| @@ -2074,8 +2049,7 @@ value. Otherwise return CHILDREN as is." | |||
| 2074 | 2049 | ||
| 2075 | (defun transient--get-predicate-for (cmd &optional suffix-only) | 2050 | (defun transient--get-predicate-for (cmd &optional suffix-only) |
| 2076 | (or (ignore-errors | 2051 | (or (ignore-errors |
| 2077 | (lookup-key transient--predicate-map | 2052 | (lookup-key transient--predicate-map (vector cmd))) |
| 2078 | (vector (transient--suffix-symbol cmd)))) | ||
| 2079 | (and (not suffix-only) | 2053 | (and (not suffix-only) |
| 2080 | (let ((pred (oref transient--prefix transient-non-suffix))) | 2054 | (let ((pred (oref transient--prefix transient-non-suffix))) |
| 2081 | (pcase pred | 2055 | (pcase pred |
| @@ -2189,6 +2163,37 @@ value. Otherwise return CHILDREN as is." | |||
| 2189 | ,@body))) | 2163 | ,@body))) |
| 2190 | 2164 | ||
| 2191 | (defun transient--wrap-command () | 2165 | (defun transient--wrap-command () |
| 2166 | (if (>= emacs-major-version 30) | ||
| 2167 | (transient--wrap-command-30) | ||
| 2168 | (transient--wrap-command-29))) | ||
| 2169 | |||
| 2170 | (defun transient--wrap-command-30 () | ||
| 2171 | (letrec | ||
| 2172 | ((prefix transient--prefix) | ||
| 2173 | (suffix this-command) | ||
| 2174 | (advice (lambda (fn &rest args) | ||
| 2175 | (interactive | ||
| 2176 | (lambda (spec) | ||
| 2177 | (let ((abort t)) | ||
| 2178 | (unwind-protect | ||
| 2179 | (prog1 (advice-eval-interactive-spec spec) | ||
| 2180 | (setq abort nil)) | ||
| 2181 | (when abort | ||
| 2182 | (when-let ((unwind (oref prefix unwind-suffix))) | ||
| 2183 | (transient--debug 'unwind-interactive) | ||
| 2184 | (funcall unwind suffix)) | ||
| 2185 | (advice-remove suffix advice) | ||
| 2186 | (oset prefix unwind-suffix nil)))))) | ||
| 2187 | (unwind-protect | ||
| 2188 | (apply fn args) | ||
| 2189 | (when-let ((unwind (oref prefix unwind-suffix))) | ||
| 2190 | (transient--debug 'unwind-command) | ||
| 2191 | (funcall unwind suffix)) | ||
| 2192 | (advice-remove suffix advice) | ||
| 2193 | (oset prefix unwind-suffix nil))))) | ||
| 2194 | (advice-add suffix :around advice '((depth . -99))))) | ||
| 2195 | |||
| 2196 | (defun transient--wrap-command-29 () | ||
| 2192 | (let* ((prefix transient--prefix) | 2197 | (let* ((prefix transient--prefix) |
| 2193 | (suffix this-command) | 2198 | (suffix this-command) |
| 2194 | (advice nil) | 2199 | (advice nil) |
| @@ -2202,9 +2207,7 @@ value. Otherwise return CHILDREN as is." | |||
| 2202 | (when-let ((unwind (oref prefix unwind-suffix))) | 2207 | (when-let ((unwind (oref prefix unwind-suffix))) |
| 2203 | (transient--debug 'unwind-interactive) | 2208 | (transient--debug 'unwind-interactive) |
| 2204 | (funcall unwind suffix)) | 2209 | (funcall unwind suffix)) |
| 2205 | (if (symbolp suffix) | 2210 | (advice-remove suffix advice) |
| 2206 | (advice-remove suffix advice) | ||
| 2207 | (remove-function suffix advice)) | ||
| 2208 | (oset prefix unwind-suffix nil)))))) | 2211 | (oset prefix unwind-suffix nil)))))) |
| 2209 | (advice-body | 2212 | (advice-body |
| 2210 | (lambda (fn &rest args) | 2213 | (lambda (fn &rest args) |
| @@ -2213,16 +2216,12 @@ value. Otherwise return CHILDREN as is." | |||
| 2213 | (when-let ((unwind (oref prefix unwind-suffix))) | 2216 | (when-let ((unwind (oref prefix unwind-suffix))) |
| 2214 | (transient--debug 'unwind-command) | 2217 | (transient--debug 'unwind-command) |
| 2215 | (funcall unwind suffix)) | 2218 | (funcall unwind suffix)) |
| 2216 | (if (symbolp suffix) | 2219 | (advice-remove suffix advice) |
| 2217 | (advice-remove suffix advice) | ||
| 2218 | (remove-function suffix advice)) | ||
| 2219 | (oset prefix unwind-suffix nil))))) | 2220 | (oset prefix unwind-suffix nil))))) |
| 2220 | (setq advice `(lambda (fn &rest args) | 2221 | (setq advice `(lambda (fn &rest args) |
| 2221 | (interactive ,advice-interactive) | 2222 | (interactive ,advice-interactive) |
| 2222 | (apply ',advice-body fn args))) | 2223 | (apply ',advice-body fn args))) |
| 2223 | (if (symbolp suffix) | 2224 | (advice-add suffix :around advice '((depth . -99))))) |
| 2224 | (advice-add suffix :around advice '((depth . -99))) | ||
| 2225 | (add-function :around (var suffix) advice '((depth . -99)))))) | ||
| 2226 | 2225 | ||
| 2227 | (defun transient--premature-post-command () | 2226 | (defun transient--premature-post-command () |
| 2228 | (and (equal (this-command-keys-vector) []) | 2227 | (and (equal (this-command-keys-vector) []) |
| @@ -2343,7 +2342,7 @@ value. Otherwise return CHILDREN as is." | |||
| 2343 | (if (symbolp arg) | 2342 | (if (symbolp arg) |
| 2344 | (message "-- %-22s (cmd: %s, event: %S, exit: %s%s)" | 2343 | (message "-- %-22s (cmd: %s, event: %S, exit: %s%s)" |
| 2345 | arg | 2344 | arg |
| 2346 | (or (ignore-errors (transient--suffix-symbol this-command)) | 2345 | (or (and (symbolp this-command) this-command) |
| 2347 | (if (byte-code-function-p this-command) | 2346 | (if (byte-code-function-p this-command) |
| 2348 | "#[...]" | 2347 | "#[...]" |
| 2349 | this-command)) | 2348 | this-command)) |
| @@ -2526,12 +2525,9 @@ prefix argument and pivot to `transient-update'." | |||
| 2526 | (propertize "?" 'face 'transient-key) | 2525 | (propertize "?" 'face 'transient-key) |
| 2527 | ;; `this-command' is `transient-undefined' or `transient-inapt'. | 2526 | ;; `this-command' is `transient-undefined' or `transient-inapt'. |
| 2528 | ;; Show the command (`this-original-command') the user actually | 2527 | ;; Show the command (`this-original-command') the user actually |
| 2529 | ;; tried to invoke. For an anonymous inapt command that is a | 2528 | ;; tried to invoke. |
| 2530 | ;; lambda expression, which cannot be mapped to a symbol, so | 2529 | (if-let ((cmd (or (ignore-errors (symbol-name this-original-command)) |
| 2531 | ;; forgo displaying the command. | 2530 | (ignore-errors (symbol-name this-command))))) |
| 2532 | (if-let ((cmd (ignore-errors | ||
| 2533 | (symbol-name (transient--suffix-symbol | ||
| 2534 | this-original-command))))) | ||
| 2535 | (format " [%s]" (propertize cmd 'face 'font-lock-warning-face)) | 2531 | (format " [%s]" (propertize cmd 'face 'font-lock-warning-face)) |
| 2536 | "")) | 2532 | "")) |
| 2537 | (unless (and transient--transient-map | 2533 | (unless (and transient--transient-map |
| @@ -2621,8 +2617,7 @@ transient is active." | |||
| 2621 | (transient-suffix-object command))) | 2617 | (transient-suffix-object command))) |
| 2622 | (transient--show) | 2618 | (transient--show) |
| 2623 | (transient--read-number-N | 2619 | (transient--read-number-N |
| 2624 | (format "Set level for `%s': " | 2620 | (format "Set level for `%s': " command) |
| 2625 | (transient--suffix-symbol command)) | ||
| 2626 | nil nil (not (eq command prefix))))))))))) | 2621 | nil nil (not (eq command prefix))))))))))) |
| 2627 | (cond | 2622 | (cond |
| 2628 | ((not command) | 2623 | ((not command) |
| @@ -2631,7 +2626,7 @@ transient is active." | |||
| 2631 | (level | 2626 | (level |
| 2632 | (let* ((prefix (oref transient--prefix command)) | 2627 | (let* ((prefix (oref transient--prefix command)) |
| 2633 | (alist (alist-get prefix transient-levels)) | 2628 | (alist (alist-get prefix transient-levels)) |
| 2634 | (sym (transient--suffix-symbol command))) | 2629 | (sym command)) |
| 2635 | (if (eq command prefix) | 2630 | (if (eq command prefix) |
| 2636 | (progn (oset transient--prefix level level) | 2631 | (progn (oset transient--prefix level level) |
| 2637 | (setq sym t)) | 2632 | (setq sym t)) |
| @@ -3463,7 +3458,7 @@ Optional support for popup buttons is also implemented here." | |||
| 3463 | (if transient-enable-popup-navigation | 3458 | (if transient-enable-popup-navigation |
| 3464 | (make-text-button str nil | 3459 | (make-text-button str nil |
| 3465 | 'type 'transient | 3460 | 'type 'transient |
| 3466 | 'command (transient--suffix-command obj)) | 3461 | 'command (oref obj command)) |
| 3467 | str))) | 3462 | str))) |
| 3468 | 3463 | ||
| 3469 | (cl-defmethod transient-format ((obj transient-infix)) | 3464 | (cl-defmethod transient-format ((obj transient-infix)) |
| @@ -3663,7 +3658,7 @@ that, else its name. | |||
| 3663 | 3658 | ||
| 3664 | Intended to be temporarily used as the `:suffix-description' of | 3659 | Intended to be temporarily used as the `:suffix-description' of |
| 3665 | a prefix command, while porting a regular keymap to a transient." | 3660 | a prefix command, while porting a regular keymap to a transient." |
| 3666 | (let ((command (transient--suffix-symbol (oref obj command)))) | 3661 | (let ((command (oref obj command))) |
| 3667 | (if-let ((doc (documentation command))) | 3662 | (if-let ((doc (documentation command))) |
| 3668 | (propertize (car (split-string doc "\n")) 'face 'font-lock-doc-face) | 3663 | (propertize (car (split-string doc "\n")) 'face 'font-lock-doc-face) |
| 3669 | (propertize (symbol-name command) 'face 'font-lock-function-name-face)))) | 3664 | (propertize (symbol-name command) 'face 'font-lock-function-name-face)))) |
| @@ -3691,7 +3686,7 @@ prefix method." | |||
| 3691 | (cond | 3686 | (cond |
| 3692 | ((eq this-command 'transient-help) | 3687 | ((eq this-command 'transient-help) |
| 3693 | (transient-show-help transient--prefix)) | 3688 | (transient-show-help transient--prefix)) |
| 3694 | ((let ((prefix (get (transient--suffix-command obj) | 3689 | ((let ((prefix (get (oref obj command) |
| 3695 | 'transient--prefix))) | 3690 | 'transient--prefix))) |
| 3696 | (and prefix (not (eq (oref transient--prefix command) this-command)) | 3691 | (and prefix (not (eq (oref transient--prefix command) this-command)) |
| 3697 | (prog1 t (transient-show-help prefix))))) | 3692 | (prog1 t (transient-show-help prefix))))) |