diff options
| author | Jonas Bernoulli | 2024-06-18 17:02:20 +0200 |
|---|---|---|
| committer | Jonas Bernoulli | 2024-06-18 17:02:20 +0200 |
| commit | dceb28a1cfad276cdf070a9b2ca4d8f3ab3c1a85 (patch) | |
| tree | d42badfbdf37aa45b314cdbaddf3b1520a34b8e0 | |
| parent | dc308348a904d69916ca6ab1eb587aff03e8421c (diff) | |
| download | emacs-dceb28a1cfad276cdf070a9b2ca4d8f3ab3c1a85.tar.gz emacs-dceb28a1cfad276cdf070a9b2ca4d8f3ab3c1a85.zip | |
Update to Transient v0.7.0-1-g482bc777
| -rw-r--r-- | doc/misc/transient.texi | 37 | ||||
| -rw-r--r-- | lisp/transient.el | 361 |
2 files changed, 231 insertions, 167 deletions
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi index 0aa520237f7..7e8ffcf91bf 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.6.0 | 34 | @subtitle for version 0.7.0 |
| 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.6.0. | 56 | This manual is for Transient version 0.7.0. |
| 57 | 57 | ||
| 58 | @insertcopying | 58 | @insertcopying |
| 59 | @end ifnottex | 59 | @end ifnottex |
| @@ -1112,7 +1112,8 @@ Transients}) and adds the transient's infix and suffix bindings, as | |||
| 1112 | described below. | 1112 | described below. |
| 1113 | 1113 | ||
| 1114 | Users and third-party packages can add additional bindings using | 1114 | Users and third-party packages can add additional bindings using |
| 1115 | functions such as @code{transient-insert-suffix} (@pxref{Modifying Existing Transients}). These functions take a ``suffix specification'' as one of | 1115 | functions such as @code{transient-insert-suffix} (@pxref{Modifying Existing Transients}). |
| 1116 | These functions take a ``suffix specification'' as one of | ||
| 1116 | their arguments, which has the same form as the specifications used in | 1117 | their arguments, which has the same form as the specifications used in |
| 1117 | @code{transient-define-prefix}. | 1118 | @code{transient-define-prefix}. |
| 1118 | 1119 | ||
| @@ -1380,16 +1381,12 @@ This macro defines @var{NAME} as a transient infix command. | |||
| 1380 | reserved for future use. @var{DOCSTRING} is the documentation string and | 1381 | reserved for future use. @var{DOCSTRING} is the documentation string and |
| 1381 | is optional. | 1382 | is optional. |
| 1382 | 1383 | ||
| 1383 | The keyword-value pairs are mandatory. All transient infix commands | 1384 | At least one key-value pair is required. All transient infix |
| 1384 | are @code{equal} to each other (but not @code{eq}), so it is meaningless to define | 1385 | commands are @code{equal} to each other (but not @code{eq}). It is meaningless |
| 1385 | an infix command without also setting at least @code{:class} and one other | 1386 | to define an infix command, without providing at least one keyword |
| 1386 | keyword (which it is depends on the used class, usually @code{:argument} or | 1387 | argument (usually @code{:argument} or @code{:variable}, depending on the class). |
| 1387 | @code{:variable}). | 1388 | The suffix class defaults to @code{transient-switch} and can be set using |
| 1388 | 1389 | the @code{:class} keyword. | |
| 1389 | Each keyword has to be a keyword symbol, either @code{:class} or a keyword | ||
| 1390 | argument supported by the constructor of that class. The | ||
| 1391 | @code{transient-switch} class is used if the class is not specified | ||
| 1392 | explicitly. | ||
| 1393 | 1390 | ||
| 1394 | The function definition is always: | 1391 | The function definition is always: |
| 1395 | 1392 | ||
| @@ -2372,6 +2369,20 @@ the transient popup, you will be able to yank it in another buffer. | |||
| 2372 | #'transient--do-stay) | 2369 | #'transient--do-stay) |
| 2373 | @end lisp | 2370 | @end lisp |
| 2374 | 2371 | ||
| 2372 | @anchor{How can I autoload prefix and suffix commands?} | ||
| 2373 | @appendixsec How can I autoload prefix and suffix commands? | ||
| 2374 | |||
| 2375 | If your package only supports Emacs 30, just prefix the definition | ||
| 2376 | with @code{;;;###autoload}. If your package supports released versions of | ||
| 2377 | Emacs, you unfortunately have to use a long form autoload comment | ||
| 2378 | as described in @ref{Autoload,,,elisp,}. | ||
| 2379 | |||
| 2380 | @lisp | ||
| 2381 | ;;;###autoload (autoload 'magit-dispatch "magit" nil t) | ||
| 2382 | (transient-define-prefix magit-dispatch () | ||
| 2383 | ...) | ||
| 2384 | @end lisp | ||
| 2385 | |||
| 2375 | @anchor{How does Transient compare to prefix keys and universal arguments?} | 2386 | @anchor{How does Transient compare to prefix keys and universal arguments?} |
| 2376 | @appendixsec How does Transient compare to prefix keys and universal arguments? | 2387 | @appendixsec How does Transient compare to prefix keys and universal arguments? |
| 2377 | 2388 | ||
diff --git a/lisp/transient.el b/lisp/transient.el index c9b6e457d00..34458bec688 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.6.0 | 8 | ;; Version: 0.7.0 |
| 9 | 9 | ||
| 10 | ;; SPDX-License-Identifier: GPL-3.0-or-later | 10 | ;; SPDX-License-Identifier: GPL-3.0-or-later |
| 11 | 11 | ||
| @@ -38,7 +38,7 @@ | |||
| 38 | (require 'format-spec) | 38 | (require 'format-spec) |
| 39 | 39 | ||
| 40 | (eval-and-compile | 40 | (eval-and-compile |
| 41 | (when (and (featurep' seq) | 41 | (when (and (featurep 'seq) |
| 42 | (not (fboundp 'seq-keep))) | 42 | (not (fboundp 'seq-keep))) |
| 43 | (unload-feature 'seq 'force))) | 43 | (unload-feature 'seq 'force))) |
| 44 | (require 'seq) | 44 | (require 'seq) |
| @@ -721,24 +721,12 @@ the prototype is stored in the clone's `prototype' slot.") | |||
| 721 | (if-not-derived | 721 | (if-not-derived |
| 722 | :initarg :if-not-derived | 722 | :initarg :if-not-derived |
| 723 | :initform nil | 723 | :initform nil |
| 724 | :documentation "Enable if major-mode does not derive from value.")) | 724 | :documentation "Enable if major-mode does not derive from value.") |
| 725 | "Abstract superclass for group and suffix classes. | 725 | (inapt |
| 726 | 726 | :initform nil) | |
| 727 | It is undefined what happens if more than one `if*' predicate | 727 | (inapt-face |
| 728 | slot is non-nil." | 728 | :initarg :inapt-face |
| 729 | :abstract t) | 729 | :initform 'transient-inapt-suffix) |
| 730 | |||
| 731 | (defclass transient-suffix (transient-child) | ||
| 732 | ((definition :allocation :class :initform nil) | ||
| 733 | (key :initarg :key) | ||
| 734 | (command :initarg :command) | ||
| 735 | (transient :initarg :transient) | ||
| 736 | (format :initarg :format :initform " %k %d") | ||
| 737 | (description :initarg :description :initform nil) | ||
| 738 | (face :initarg :face :initform nil) | ||
| 739 | (show-help :initarg :show-help :initform nil) | ||
| 740 | (inapt-face :initarg :inapt-face :initform 'transient-inapt-suffix) | ||
| 741 | (inapt :initform nil) | ||
| 742 | (inapt-if | 730 | (inapt-if |
| 743 | :initarg :inapt-if | 731 | :initarg :inapt-if |
| 744 | :initform nil | 732 | :initform nil |
| @@ -771,13 +759,33 @@ slot is non-nil." | |||
| 771 | :initarg :inapt-if-not-derived | 759 | :initarg :inapt-if-not-derived |
| 772 | :initform nil | 760 | :initform nil |
| 773 | :documentation "Inapt if major-mode does not derive from value.")) | 761 | :documentation "Inapt if major-mode does not derive from value.")) |
| 762 | "Abstract superclass for group and suffix classes. | ||
| 763 | |||
| 764 | It is undefined what happens if more than one `if*' predicate | ||
| 765 | slot is non-nil." | ||
| 766 | :abstract t) | ||
| 767 | |||
| 768 | (defclass transient-suffix (transient-child) | ||
| 769 | ((definition :allocation :class :initform nil) | ||
| 770 | (key :initarg :key) | ||
| 771 | (command :initarg :command) | ||
| 772 | (transient :initarg :transient) | ||
| 773 | (format :initarg :format :initform " %k %d") | ||
| 774 | (description :initarg :description :initform nil) | ||
| 775 | (face :initarg :face :initform nil) | ||
| 776 | (show-help :initarg :show-help :initform nil)) | ||
| 774 | "Superclass for suffix command.") | 777 | "Superclass for suffix command.") |
| 775 | 778 | ||
| 776 | (defclass transient-information (transient-suffix) | 779 | (defclass transient-information (transient-suffix) |
| 777 | ((format :initform " %k %d") | 780 | ((format :initform " %k %d") |
| 778 | (key :initform " ")) | 781 | (key :initform " ")) |
| 779 | "Display-only information. | 782 | "Display-only information, aligned with suffix keys. |
| 780 | A suffix object with no associated command.") | 783 | Technically a suffix object with no associated command.") |
| 784 | |||
| 785 | (defclass transient-information* (transient-information) | ||
| 786 | ((format :initform " %d")) | ||
| 787 | "Display-only information, aligned with suffix descriptions. | ||
| 788 | Technically a suffix object with no associated command.") | ||
| 781 | 789 | ||
| 782 | (defclass transient-infix (transient-suffix) | 790 | (defclass transient-infix (transient-suffix) |
| 783 | ((transient :initform t) | 791 | ((transient :initform t) |
| @@ -834,6 +842,7 @@ They become the value of this argument.") | |||
| 834 | (hide :initarg :hide :initform nil) | 842 | (hide :initarg :hide :initform nil) |
| 835 | (description :initarg :description :initform nil) | 843 | (description :initarg :description :initform nil) |
| 836 | (pad-keys :initarg :pad-keys :initform nil) | 844 | (pad-keys :initarg :pad-keys :initform nil) |
| 845 | (info-format :initarg :info-format :initform nil) | ||
| 837 | (setup-children :initarg :setup-children)) | 846 | (setup-children :initarg :setup-children)) |
| 838 | "Abstract superclass of all group classes." | 847 | "Abstract superclass of all group classes." |
| 839 | :abstract t) | 848 | :abstract t) |
| @@ -907,8 +916,9 @@ to the setup function: | |||
| 907 | [&optional ("interactive" interactive) def-body])) | 916 | [&optional ("interactive" interactive) def-body])) |
| 908 | (indent defun) | 917 | (indent defun) |
| 909 | (doc-string 3)) | 918 | (doc-string 3)) |
| 910 | (pcase-let ((`(,class ,slots ,suffixes ,docstr ,body) | 919 | (pcase-let |
| 911 | (transient--expand-define-args args arglist))) | 920 | ((`(,class ,slots ,suffixes ,docstr ,body ,interactive-only) |
| 921 | (transient--expand-define-args args arglist 'transient-define-prefix))) | ||
| 912 | `(progn | 922 | `(progn |
| 913 | (defalias ',name | 923 | (defalias ',name |
| 914 | ,(if body | 924 | ,(if body |
| @@ -916,7 +926,7 @@ to the setup function: | |||
| 916 | `(lambda () | 926 | `(lambda () |
| 917 | (interactive) | 927 | (interactive) |
| 918 | (transient-setup ',name)))) | 928 | (transient-setup ',name)))) |
| 919 | (put ',name 'interactive-only t) | 929 | (put ',name 'interactive-only ,interactive-only) |
| 920 | (put ',name 'function-documentation ,docstr) | 930 | (put ',name 'function-documentation ,docstr) |
| 921 | (put ',name 'transient--prefix | 931 | (put ',name 'transient--prefix |
| 922 | (,(or class 'transient-prefix) :command ',name ,@slots)) | 932 | (,(or class 'transient-prefix) :command ',name ,@slots)) |
| @@ -940,42 +950,50 @@ The BODY must begin with an `interactive' form that matches | |||
| 940 | ARGLIST. The infix arguments are usually accessed by using | 950 | ARGLIST. The infix arguments are usually accessed by using |
| 941 | `transient-args' inside `interactive'. | 951 | `transient-args' inside `interactive'. |
| 942 | 952 | ||
| 943 | \(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]... BODY...)" | 953 | \(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]... [BODY...])" |
| 944 | (declare (debug ( &define name lambda-list | 954 | (declare (debug ( &define name lambda-list |
| 945 | [&optional lambda-doc] | 955 | [&optional lambda-doc] |
| 946 | [&rest keywordp sexp] | 956 | [&rest keywordp sexp] |
| 947 | ("interactive" interactive) | 957 | [&optional ("interactive" interactive) def-body])) |
| 948 | def-body)) | ||
| 949 | (indent defun) | 958 | (indent defun) |
| 950 | (doc-string 3)) | 959 | (doc-string 3)) |
| 951 | (pcase-let ((`(,class ,slots ,_ ,docstr ,body) | 960 | (pcase-let |
| 952 | (transient--expand-define-args args arglist))) | 961 | ((`(,class ,slots ,_ ,docstr ,body ,interactive-only) |
| 962 | (transient--expand-define-args args arglist 'transient-define-suffix))) | ||
| 953 | `(progn | 963 | `(progn |
| 954 | (defalias ',name | 964 | (defalias ',name |
| 955 | ,(if (and (not body) class (oref-default class definition)) | 965 | ,(if (and (not body) class (oref-default class definition)) |
| 956 | `(oref-default ',class definition) | 966 | `(oref-default ',class definition) |
| 957 | `(lambda ,arglist ,@body))) | 967 | `(lambda ,arglist ,@body))) |
| 958 | (put ',name 'interactive-only t) | 968 | (put ',name 'interactive-only ,interactive-only) |
| 959 | (put ',name 'function-documentation ,docstr) | 969 | (put ',name 'function-documentation ,docstr) |
| 960 | (put ',name 'transient--suffix | 970 | (put ',name 'transient--suffix |
| 961 | (,(or class 'transient-suffix) :command ',name ,@slots))))) | 971 | (,(or class 'transient-suffix) :command ',name ,@slots))))) |
| 962 | 972 | ||
| 973 | (defmacro transient-augment-suffix (name &rest args) | ||
| 974 | "Augment existing command NAME with a new transient suffix object. | ||
| 975 | Similar to `transient-define-suffix' but define a suffix object only. | ||
| 976 | \n\(fn NAME [KEYWORD VALUE]...)" | ||
| 977 | (declare (debug (&define name [&rest keywordp sexp])) | ||
| 978 | (indent defun)) | ||
| 979 | (pcase-let | ||
| 980 | ((`(,class ,slots) | ||
| 981 | (transient--expand-define-args args nil 'transient-augment-suffix t))) | ||
| 982 | `(put ',name 'transient--suffix | ||
| 983 | (,(or class 'transient-suffix) :command ',name ,@slots)))) | ||
| 984 | |||
| 963 | (defmacro transient-define-infix (name arglist &rest args) | 985 | (defmacro transient-define-infix (name arglist &rest args) |
| 964 | "Define NAME as a transient infix command. | 986 | "Define NAME as a transient infix command. |
| 965 | 987 | ||
| 966 | ARGLIST is always ignored and reserved for future use. | 988 | ARGLIST is always ignored and reserved for future use. |
| 967 | DOCSTRING is the documentation string and is optional. | 989 | DOCSTRING is the documentation string and is optional. |
| 968 | 990 | ||
| 969 | The key-value pairs are mandatory. All transient infix commands | 991 | At least one key-value pair is required. All transient infix |
| 970 | are equal to each other (but not eq), so it is meaningless to | 992 | commands are equal to each other (but not eq). It is meaning- |
| 971 | define an infix command without also setting at least `:class' | 993 | less to define an infix command, without providing at least one |
| 972 | and one other keyword (which it is depends on the used class, | 994 | keyword argument (usually `:argument' or `:variable', depending |
| 973 | usually `:argument' or `:variable'). | 995 | on the class). The suffix class defaults to `transient-switch' |
| 974 | 996 | and can be set using the `:class' keyword. | |
| 975 | Each key has to be a keyword symbol, either `:class' or a keyword | ||
| 976 | argument supported by the constructor of that class. The | ||
| 977 | `transient-switch' class is used if the class is not specified | ||
| 978 | explicitly. | ||
| 979 | 997 | ||
| 980 | The function definitions is always: | 998 | The function definitions is always: |
| 981 | 999 | ||
| @@ -994,17 +1012,19 @@ that case you have to use `transient-define-suffix' to define | |||
| 994 | the infix command and use t as the value of the `:transient' | 1012 | the infix command and use t as the value of the `:transient' |
| 995 | keyword. | 1013 | keyword. |
| 996 | 1014 | ||
| 997 | \(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]...)" | 1015 | \(fn NAME ARGLIST [DOCSTRING] KEYWORD VALUE [KEYWORD VALUE]...)" |
| 998 | (declare (debug ( &define name lambda-list | 1016 | (declare (debug ( &define name lambda-list |
| 999 | [&optional lambda-doc] | 1017 | [&optional lambda-doc] |
| 1018 | keywordp sexp | ||
| 1000 | [&rest keywordp sexp])) | 1019 | [&rest keywordp sexp])) |
| 1001 | (indent defun) | 1020 | (indent defun) |
| 1002 | (doc-string 3)) | 1021 | (doc-string 3)) |
| 1003 | (pcase-let ((`(,class ,slots ,_ ,docstr ,_) | 1022 | (pcase-let |
| 1004 | (transient--expand-define-args args arglist))) | 1023 | ((`(,class ,slots ,_ ,docstr ,_ ,interactive-only) |
| 1024 | (transient--expand-define-args args arglist 'transient-define-infix t))) | ||
| 1005 | `(progn | 1025 | `(progn |
| 1006 | (defalias ',name #'transient--default-infix-command) | 1026 | (defalias ',name #'transient--default-infix-command) |
| 1007 | (put ',name 'interactive-only t) | 1027 | (put ',name 'interactive-only ,interactive-only) |
| 1008 | (put ',name 'completion-predicate #'transient--suffix-only) | 1028 | (put ',name 'completion-predicate #'transient--suffix-only) |
| 1009 | (put ',name 'function-documentation ,docstr) | 1029 | (put ',name 'function-documentation ,docstr) |
| 1010 | (put ',name 'transient--suffix | 1030 | (put ',name 'transient--suffix |
| @@ -1044,7 +1064,8 @@ falling back to that of the same aliased command." | |||
| 1044 | (put 'transient--default-infix-command 'completion-predicate | 1064 | (put 'transient--default-infix-command 'completion-predicate |
| 1045 | #'transient--suffix-only) | 1065 | #'transient--suffix-only) |
| 1046 | 1066 | ||
| 1047 | (defun transient--find-function-advised-original (fn func) | 1067 | (define-advice find-function-advised-original |
| 1068 | (:around (fn func) transient-default-infix) | ||
| 1048 | "Return nil instead of `transient--default-infix-command'. | 1069 | "Return nil instead of `transient--default-infix-command'. |
| 1049 | When using `find-function' to jump to the definition of a transient | 1070 | When using `find-function' to jump to the definition of a transient |
| 1050 | infix command/argument, then we want to actually jump to that, not to | 1071 | infix command/argument, then we want to actually jump to that, not to |
| @@ -1052,14 +1073,12 @@ the definition of `transient--default-infix-command', which all infix | |||
| 1052 | commands are aliases for." | 1073 | commands are aliases for." |
| 1053 | (let ((val (funcall fn func))) | 1074 | (let ((val (funcall fn func))) |
| 1054 | (and val (not (eq val 'transient--default-infix-command)) val))) | 1075 | (and val (not (eq val 'transient--default-infix-command)) val))) |
| 1055 | (advice-add 'find-function-advised-original :around | ||
| 1056 | #'transient--find-function-advised-original) | ||
| 1057 | 1076 | ||
| 1058 | (eval-and-compile | 1077 | (eval-and-compile ;transient--expand-define-args |
| 1059 | (defun transient--expand-define-args (args &optional arglist) | 1078 | (defun transient--expand-define-args (args arglist form &optional nobody) |
| 1060 | (unless (listp arglist) | 1079 | (unless (listp arglist) |
| 1061 | (error "Mandatory ARGLIST is missing")) | 1080 | (error "Mandatory ARGLIST is missing")) |
| 1062 | (let (class keys suffixes docstr) | 1081 | (let (class keys suffixes docstr declare (interactive-only t)) |
| 1063 | (when (stringp (car args)) | 1082 | (when (stringp (car args)) |
| 1064 | (setq docstr (pop args))) | 1083 | (setq docstr (pop args))) |
| 1065 | (while (keywordp (car args)) | 1084 | (while (keywordp (car args)) |
| @@ -1073,13 +1092,28 @@ commands are aliases for." | |||
| 1073 | (or (vectorp arg) | 1092 | (or (vectorp arg) |
| 1074 | (and arg (symbolp arg)))) | 1093 | (and arg (symbolp arg)))) |
| 1075 | (push (pop args) suffixes)) | 1094 | (push (pop args) suffixes)) |
| 1095 | (when (eq (car-safe (car args)) 'declare) | ||
| 1096 | (setq declare (car args)) | ||
| 1097 | (setq args (cdr args)) | ||
| 1098 | (when-let ((int (assq 'interactive-only declare))) | ||
| 1099 | (setq interactive-only (cadr int)) | ||
| 1100 | (delq int declare)) | ||
| 1101 | (unless (cdr declare) | ||
| 1102 | (setq declare nil))) | ||
| 1103 | (cond | ||
| 1104 | ((not args)) | ||
| 1105 | (nobody | ||
| 1106 | (error "%s: No function body allowed" form)) | ||
| 1107 | ((not (eq (car-safe (nth (if declare 1 0) args)) 'interactive)) | ||
| 1108 | (error "%s: Interactive form missing" form))) | ||
| 1076 | (list (if (eq (car-safe class) 'quote) | 1109 | (list (if (eq (car-safe class) 'quote) |
| 1077 | (cadr class) | 1110 | (cadr class) |
| 1078 | class) | 1111 | class) |
| 1079 | (nreverse keys) | 1112 | (nreverse keys) |
| 1080 | (nreverse suffixes) | 1113 | (nreverse suffixes) |
| 1081 | docstr | 1114 | docstr |
| 1082 | args)))) | 1115 | (if declare (cons declare args) args) |
| 1116 | interactive-only)))) | ||
| 1083 | 1117 | ||
| 1084 | (defun transient--parse-child (prefix spec) | 1118 | (defun transient--parse-child (prefix spec) |
| 1085 | (cl-typecase spec | 1119 | (cl-typecase spec |
| @@ -1150,9 +1184,9 @@ commands are aliases for." | |||
| 1150 | (commandp (cadr spec))) | 1184 | (commandp (cadr spec))) |
| 1151 | (setq args (plist-put args :description (macroexp-quote pop))))) | 1185 | (setq args (plist-put args :description (macroexp-quote pop))))) |
| 1152 | (cond | 1186 | (cond |
| 1153 | ((eq car :info)) | 1187 | ((memq car '(:info :info*))) |
| 1154 | ((keywordp car) | 1188 | ((keywordp car) |
| 1155 | (error "Need command or `:info', got `%s'" car)) | 1189 | (error "Need command, `:info' or `:info*', got `%s'" car)) |
| 1156 | ((symbolp car) | 1190 | ((symbolp car) |
| 1157 | (setq args (plist-put args :command (macroexp-quote pop)))) | 1191 | (setq args (plist-put args :command (macroexp-quote pop)))) |
| 1158 | ((and (commandp car) | 1192 | ((and (commandp car) |
| @@ -1212,6 +1246,9 @@ commands are aliases for." | |||
| 1212 | ((eq key :info) | 1246 | ((eq key :info) |
| 1213 | (setq class 'transient-information) | 1247 | (setq class 'transient-information) |
| 1214 | (setq args (plist-put args :description val))) | 1248 | (setq args (plist-put args :description val))) |
| 1249 | ((eq key :info*) | ||
| 1250 | (setq class 'transient-information*) | ||
| 1251 | (setq args (plist-put args :description val))) | ||
| 1215 | ((eq (car-safe val) '\,) | 1252 | ((eq (car-safe val) '\,) |
| 1216 | (setq args (plist-put args key (cadr val)))) | 1253 | (setq args (plist-put args key (cadr val)))) |
| 1217 | ((or (symbolp val) | 1254 | ((or (symbolp val) |
| @@ -1479,6 +1516,10 @@ variable instead.") | |||
| 1479 | (defvar transient-exit-hook nil | 1516 | (defvar transient-exit-hook nil |
| 1480 | "Hook run after exiting a transient.") | 1517 | "Hook run after exiting a transient.") |
| 1481 | 1518 | ||
| 1519 | (defvar transient-setup-buffer-hook nil | ||
| 1520 | "Hook run when setting up the transient buffer. | ||
| 1521 | That buffer is current and empty when this hook runs.") | ||
| 1522 | |||
| 1482 | (defvar transient--prefix nil) | 1523 | (defvar transient--prefix nil) |
| 1483 | (defvar transient--layout nil) | 1524 | (defvar transient--layout nil) |
| 1484 | (defvar transient--suffixes nil) | 1525 | (defvar transient--suffixes nil) |
| @@ -1506,6 +1547,9 @@ variable instead.") | |||
| 1506 | (defvar transient--buffer-name " *transient*" | 1547 | (defvar transient--buffer-name " *transient*" |
| 1507 | "Name of the transient buffer.") | 1548 | "Name of the transient buffer.") |
| 1508 | 1549 | ||
| 1550 | (defvar transient--buffer nil | ||
| 1551 | "The transient menu buffer.") | ||
| 1552 | |||
| 1509 | (defvar transient--window nil | 1553 | (defvar transient--window nil |
| 1510 | "The window used to display the transient popup buffer.") | 1554 | "The window used to display the transient popup buffer.") |
| 1511 | 1555 | ||
| @@ -1859,15 +1903,20 @@ of the corresponding object." | |||
| 1859 | (setq key (save-match-data | 1903 | (setq key (save-match-data |
| 1860 | (funcall transient-substitute-key-function obj))) | 1904 | (funcall transient-substitute-key-function obj))) |
| 1861 | (oset obj key key)) | 1905 | (oset obj key key)) |
| 1862 | (let ((kbd (kbd key)) | 1906 | (let* ((kbd (kbd key)) |
| 1863 | (cmd (oref obj command))) | 1907 | (cmd (oref obj command)) |
| 1864 | (when-let ((conflict (and transient-detect-key-conflicts | 1908 | (alt (transient--lookup-key map kbd))) |
| 1865 | (transient--lookup-key map kbd)))) | 1909 | (cond ((not alt) |
| 1866 | (unless (eq cmd conflict) | 1910 | (define-key map kbd cmd)) |
| 1867 | (error "Cannot bind %S to %s and also %s" | 1911 | ((eq alt cmd)) |
| 1868 | (string-trim key) | 1912 | ((transient--inapt-suffix-p obj)) |
| 1869 | cmd conflict))) | 1913 | ((and-let* ((obj (transient-suffix-object alt))) |
| 1870 | (define-key map kbd cmd)))) | 1914 | (transient--inapt-suffix-p obj)) |
| 1915 | (define-key map kbd cmd)) | ||
| 1916 | (transient-detect-key-conflicts | ||
| 1917 | (error "Cannot bind %S to %s and also %s" | ||
| 1918 | (string-trim key) cmd alt)) | ||
| 1919 | ((define-key map kbd cmd)))))) | ||
| 1871 | (when-let ((b (keymap-lookup map "-"))) (keymap-set map "<kp-subtract>" b)) | 1920 | (when-let ((b (keymap-lookup map "-"))) (keymap-set map "<kp-subtract>" b)) |
| 1872 | (when-let ((b (keymap-lookup map "="))) (keymap-set map "<kp-equal>" b)) | 1921 | (when-let ((b (keymap-lookup map "="))) (keymap-set map "<kp-equal>" b)) |
| 1873 | (when-let ((b (keymap-lookup map "+"))) (keymap-set map "<kp-add>" b)) | 1922 | (when-let ((b (keymap-lookup map "+"))) (keymap-set map "<kp-add>" b)) |
| @@ -2039,7 +2088,7 @@ value. Otherwise return CHILDREN as is." | |||
| 2039 | 2088 | ||
| 2040 | (defun transient--init-suffixes (name) | 2089 | (defun transient--init-suffixes (name) |
| 2041 | (let ((levels (alist-get name transient-levels))) | 2090 | (let ((levels (alist-get name transient-levels))) |
| 2042 | (cl-mapcan (lambda (c) (transient--init-child levels c)) | 2091 | (cl-mapcan (lambda (c) (transient--init-child levels c nil)) |
| 2043 | (append (get name 'transient--layout) | 2092 | (append (get name 'transient--layout) |
| 2044 | (and (not transient--editp) | 2093 | (and (not transient--editp) |
| 2045 | (get 'transient-common-commands | 2094 | (get 'transient-common-commands |
| @@ -2057,24 +2106,29 @@ value. Otherwise return CHILDREN as is." | |||
| 2057 | (list def))))) | 2106 | (list def))))) |
| 2058 | (cl-mapcan #'s layout))) | 2107 | (cl-mapcan #'s layout))) |
| 2059 | 2108 | ||
| 2060 | (defun transient--init-child (levels spec) | 2109 | (defun transient--init-child (levels spec parent) |
| 2061 | (cl-etypecase spec | 2110 | (cl-etypecase spec |
| 2062 | (vector (transient--init-group levels spec)) | 2111 | (vector (transient--init-group levels spec parent)) |
| 2063 | (list (transient--init-suffix levels spec)) | 2112 | (list (transient--init-suffix levels spec parent)) |
| 2064 | (string (list spec)))) | 2113 | (string (list spec)))) |
| 2065 | 2114 | ||
| 2066 | (defun transient--init-group (levels spec) | 2115 | (defun transient--init-group (levels spec parent) |
| 2067 | (pcase-let ((`(,level ,class ,args ,children) (append spec nil))) | 2116 | (pcase-let ((`(,level ,class ,args ,children) (append spec nil))) |
| 2068 | (and-let* ((- (transient--use-level-p level)) | 2117 | (and-let* (((transient--use-level-p level)) |
| 2069 | (obj (apply class :level level args)) | 2118 | (obj (apply class :level level args)) |
| 2070 | (- (transient--use-suffix-p obj)) | 2119 | ((transient--use-suffix-p obj)) |
| 2071 | (suffixes (cl-mapcan (lambda (c) (transient--init-child levels c)) | 2120 | ((prog1 t |
| 2072 | (transient-setup-children obj children)))) | 2121 | (when (or (and parent (oref parent inapt)) |
| 2122 | (transient--inapt-suffix-p obj)) | ||
| 2123 | (oset obj inapt t)))) | ||
| 2124 | (suffixes (cl-mapcan | ||
| 2125 | (lambda (c) (transient--init-child levels c obj)) | ||
| 2126 | (transient-setup-children obj children)))) | ||
| 2073 | (progn ; work around debbugs#31840 | 2127 | (progn ; work around debbugs#31840 |
| 2074 | (oset obj suffixes suffixes) | 2128 | (oset obj suffixes suffixes) |
| 2075 | (list obj))))) | 2129 | (list obj))))) |
| 2076 | 2130 | ||
| 2077 | (defun transient--init-suffix (levels spec) | 2131 | (defun transient--init-suffix (levels spec parent) |
| 2078 | (pcase-let* ((`(,level ,class ,args) spec) | 2132 | (pcase-let* ((`(,level ,class ,args) spec) |
| 2079 | (cmd (plist-get args :command)) | 2133 | (cmd (plist-get args :command)) |
| 2080 | (key (transient--kbd (plist-get args :key))) | 2134 | (key (transient--kbd (plist-get args :key))) |
| @@ -2107,7 +2161,8 @@ value. Otherwise return CHILDREN as is." | |||
| 2107 | (unless (cl-typep obj 'transient-information) | 2161 | (unless (cl-typep obj 'transient-information) |
| 2108 | (transient--init-suffix-key obj)) | 2162 | (transient--init-suffix-key obj)) |
| 2109 | (when (transient--use-suffix-p obj) | 2163 | (when (transient--use-suffix-p obj) |
| 2110 | (if (transient--inapt-suffix-p obj) | 2164 | (if (or (and parent (oref parent inapt)) |
| 2165 | (transient--inapt-suffix-p obj)) | ||
| 2111 | (oset obj inapt t) | 2166 | (oset obj inapt t) |
| 2112 | (transient-init-scope obj) | 2167 | (transient-init-scope obj) |
| 2113 | (transient-init-value obj)) | 2168 | (transient-init-value obj)) |
| @@ -2296,8 +2351,9 @@ value. Otherwise return CHILDREN as is." | |||
| 2296 | 'other) | 2351 | 'other) |
| 2297 | (with-demoted-errors "Error while exiting transient: %S" | 2352 | (with-demoted-errors "Error while exiting transient: %S" |
| 2298 | (delete-window transient--window))) | 2353 | (delete-window transient--window))) |
| 2299 | (when-let ((buffer (get-buffer transient--buffer-name))) | 2354 | (when (buffer-live-p transient--buffer) |
| 2300 | (kill-buffer buffer)) | 2355 | (kill-buffer transient--buffer)) |
| 2356 | (setq transient--buffer nil) | ||
| 2301 | (when remain-in-minibuffer-window | 2357 | (when remain-in-minibuffer-window |
| 2302 | (select-window remain-in-minibuffer-window))))) | 2358 | (select-window remain-in-minibuffer-window))))) |
| 2303 | 2359 | ||
| @@ -2468,7 +2524,7 @@ value. Otherwise return CHILDREN as is." | |||
| 2468 | ;; We cannot use `current-prefix-arg' because it is set | 2524 | ;; We cannot use `current-prefix-arg' because it is set |
| 2469 | ;; too late (in `command-execute'), and if it were set | 2525 | ;; too late (in `command-execute'), and if it were set |
| 2470 | ;; earlier, then we likely still would not be able to | 2526 | ;; earlier, then we likely still would not be able to |
| 2471 | ;; rely on it and `prefix-command-preserve-state-hook' | 2527 | ;; rely on it, and `prefix-command-preserve-state-hook' |
| 2472 | ;; would have to be used to record that a universal | 2528 | ;; would have to be used to record that a universal |
| 2473 | ;; argument is in effect. | 2529 | ;; argument is in effect. |
| 2474 | (not prefix-arg))) | 2530 | (not prefix-arg))) |
| @@ -2546,8 +2602,7 @@ value. Otherwise return CHILDREN as is." | |||
| 2546 | mouse-set-region)) | 2602 | mouse-set-region)) |
| 2547 | (equal (key-description (this-command-keys-vector)) | 2603 | (equal (key-description (this-command-keys-vector)) |
| 2548 | "<mouse-movement>")) | 2604 | "<mouse-movement>")) |
| 2549 | (and (eq (current-buffer) | 2605 | (and (eq (current-buffer) transient--buffer)))) |
| 2550 | (get-buffer transient--buffer-name))))) | ||
| 2551 | (transient--show)) | 2606 | (transient--show)) |
| 2552 | (when (and (numberp transient-show-popup) | 2607 | (when (and (numberp transient-show-popup) |
| 2553 | (not (zerop transient-show-popup)) | 2608 | (not (zerop transient-show-popup)) |
| @@ -2575,11 +2630,12 @@ value. Otherwise return CHILDREN as is." | |||
| 2575 | (if (symbolp arg) | 2630 | (if (symbolp arg) |
| 2576 | (message "-- %-22s (cmd: %s, event: %S, exit: %s%s)" | 2631 | (message "-- %-22s (cmd: %s, event: %S, exit: %s%s)" |
| 2577 | arg | 2632 | arg |
| 2578 | (if (fboundp 'help-fns-function-name) | 2633 | (cond ((and (symbolp this-command) this-command)) |
| 2579 | (help-fns-function-name this-command) | 2634 | ((fboundp 'help-fns-function-name) |
| 2580 | (if (byte-code-function-p this-command) | 2635 | (help-fns-function-name this-command)) |
| 2581 | "#[...]" | 2636 | ((byte-code-function-p this-command) |
| 2582 | this-command)) | 2637 | "#[...]") |
| 2638 | (this-command)) | ||
| 2583 | (key-description (this-command-keys-vector)) | 2639 | (key-description (this-command-keys-vector)) |
| 2584 | transient--exitp | 2640 | transient--exitp |
| 2585 | (cond ((keywordp (car args)) | 2641 | (cond ((keywordp (car args)) |
| @@ -3357,7 +3413,7 @@ prompt." | |||
| 3357 | 3413 | ||
| 3358 | (cl-defmethod transient-infix-set :after ((obj transient-argument) value) | 3414 | (cl-defmethod transient-infix-set :after ((obj transient-argument) value) |
| 3359 | "Unset incompatible infix arguments." | 3415 | "Unset incompatible infix arguments." |
| 3360 | (when-let* ((--- value) | 3416 | (when-let* ((value) |
| 3361 | (val (transient-infix-value obj)) | 3417 | (val (transient-infix-value obj)) |
| 3362 | (arg (if (slot-boundp obj 'argument) | 3418 | (arg (if (slot-boundp obj 'argument) |
| 3363 | (oref obj argument) | 3419 | (oref obj argument) |
| @@ -3371,15 +3427,15 @@ prompt." | |||
| 3371 | (and (not (equal val arg)) | 3427 | (and (not (equal val arg)) |
| 3372 | (cl-mapcan (apply-partially filter val) spec))))) | 3428 | (cl-mapcan (apply-partially filter val) spec))))) |
| 3373 | (dolist (obj transient--suffixes) | 3429 | (dolist (obj transient--suffixes) |
| 3374 | (when-let* ((--- (cl-typep obj 'transient-argument)) | 3430 | (when-let* (((cl-typep obj 'transient-argument)) |
| 3375 | (val (transient-infix-value obj)) | 3431 | (val (transient-infix-value obj)) |
| 3376 | (arg (if (slot-boundp obj 'argument) | 3432 | (arg (if (slot-boundp obj 'argument) |
| 3377 | (oref obj argument) | 3433 | (oref obj argument) |
| 3378 | (oref obj argument-format))) | 3434 | (oref obj argument-format))) |
| 3379 | (--- (if (equal val arg) | 3435 | ((if (equal val arg) |
| 3380 | (member arg incomp) | 3436 | (member arg incomp) |
| 3381 | (or (member val incomp) | 3437 | (or (member val incomp) |
| 3382 | (member arg incomp))))) | 3438 | (member arg incomp))))) |
| 3383 | (transient-infix-set obj nil))))) | 3439 | (transient-infix-set obj nil))))) |
| 3384 | 3440 | ||
| 3385 | (cl-defgeneric transient-set-value (obj) | 3441 | (cl-defgeneric transient-set-value (obj) |
| @@ -3515,6 +3571,10 @@ the option does not appear in ARGS." | |||
| 3515 | (or (match-string 1 match) ""))) | 3571 | (or (match-string 1 match) ""))) |
| 3516 | (and (member arg args) t))) | 3572 | (and (member arg args) t))) |
| 3517 | 3573 | ||
| 3574 | (defun transient-scope () | ||
| 3575 | "Return the value of the `scope' slot of the current prefix." | ||
| 3576 | (oref (transient-prefix-object) scope)) | ||
| 3577 | |||
| 3518 | ;;; History | 3578 | ;;; History |
| 3519 | 3579 | ||
| 3520 | (cl-defgeneric transient--history-key (obj) | 3580 | (cl-defgeneric transient--history-key (obj) |
| @@ -3580,15 +3640,18 @@ have a history of their own.") | |||
| 3580 | (transient--timer-cancel) | 3640 | (transient--timer-cancel) |
| 3581 | (setq transient--showp t) | 3641 | (setq transient--showp t) |
| 3582 | (let ((transient--shadowed-buffer (current-buffer)) | 3642 | (let ((transient--shadowed-buffer (current-buffer)) |
| 3583 | (buf (get-buffer-create transient--buffer-name)) | ||
| 3584 | (focus nil)) | 3643 | (focus nil)) |
| 3585 | (with-current-buffer buf | 3644 | (setq transient--buffer (get-buffer-create transient--buffer-name)) |
| 3645 | (with-current-buffer transient--buffer | ||
| 3586 | (when transient-enable-popup-navigation | 3646 | (when transient-enable-popup-navigation |
| 3587 | (setq focus (or (button-get (point) 'command) | 3647 | (setq focus (or (button-get (point) 'command) |
| 3588 | (and (not (bobp)) | 3648 | (and (not (bobp)) |
| 3589 | (button-get (1- (point)) 'command)) | 3649 | (button-get (1- (point)) 'command)) |
| 3590 | (transient--heading-at-point)))) | 3650 | (transient--heading-at-point)))) |
| 3591 | (erase-buffer) | 3651 | (erase-buffer) |
| 3652 | (run-hooks 'transient-setup-buffer-hook) | ||
| 3653 | (when transient-force-fixed-pitch | ||
| 3654 | (transient--force-fixed-pitch)) | ||
| 3592 | (setq window-size-fixed t) | 3655 | (setq window-size-fixed t) |
| 3593 | (when (bound-and-true-p tab-line-format) | 3656 | (when (bound-and-true-p tab-line-format) |
| 3594 | (setq tab-line-format nil)) | 3657 | (setq tab-line-format nil)) |
| @@ -3609,12 +3672,11 @@ have a history of their own.") | |||
| 3609 | (when (or transient--helpp transient--editp) | 3672 | (when (or transient--helpp transient--editp) |
| 3610 | (transient--insert-help)) | 3673 | (transient--insert-help)) |
| 3611 | (when-let ((line (transient--separator-line))) | 3674 | (when-let ((line (transient--separator-line))) |
| 3612 | (insert line)) | 3675 | (insert line))) |
| 3613 | (when transient-force-fixed-pitch | ||
| 3614 | (transient--force-fixed-pitch))) | ||
| 3615 | (unless (window-live-p transient--window) | 3676 | (unless (window-live-p transient--window) |
| 3616 | (setq transient--window | 3677 | (setq transient--window |
| 3617 | (display-buffer buf transient-display-buffer-action))) | 3678 | (display-buffer transient--buffer |
| 3679 | transient-display-buffer-action))) | ||
| 3618 | (when (window-live-p transient--window) | 3680 | (when (window-live-p transient--window) |
| 3619 | (with-selected-window transient--window | 3681 | (with-selected-window transient--window |
| 3620 | (goto-char (point-min)) | 3682 | (goto-char (point-min)) |
| @@ -3657,9 +3719,8 @@ have a history of their own.") | |||
| 3657 | (transient-with-shadowed-buffer | 3719 | (transient-with-shadowed-buffer |
| 3658 | (funcall hide)))) | 3720 | (funcall hide)))) |
| 3659 | (list group)))) | 3721 | (list group)))) |
| 3660 | transient--layout)) | 3722 | transient--layout))) |
| 3661 | group) | 3723 | (while-let ((group (pop groups))) |
| 3662 | (while (setq group (pop groups)) | ||
| 3663 | (transient--insert-group group) | 3724 | (transient--insert-group group) |
| 3664 | (when groups | 3725 | (when groups |
| 3665 | (insert ?\n))))) | 3726 | (insert ?\n))))) |
| @@ -3702,9 +3763,9 @@ have a history of their own.") | |||
| 3702 | (transient-with-shadowed-buffer | 3763 | (transient-with-shadowed-buffer |
| 3703 | (let* ((transient--pending-group column) | 3764 | (let* ((transient--pending-group column) |
| 3704 | (rows (mapcar #'transient-format (oref column suffixes)))) | 3765 | (rows (mapcar #'transient-format (oref column suffixes)))) |
| 3705 | (when-let ((desc (transient-format-description column))) | 3766 | (if-let ((desc (transient-format-description column))) |
| 3706 | (push desc rows)) | 3767 | (cons desc rows) |
| 3707 | (flatten-tree rows)))) | 3768 | rows)))) |
| 3708 | (oref group suffixes))) | 3769 | (oref group suffixes))) |
| 3709 | (vp (or (oref transient--prefix variable-pitch) | 3770 | (vp (or (oref transient--prefix variable-pitch) |
| 3710 | transient-align-variable-pitch)) | 3771 | transient-align-variable-pitch)) |
| @@ -3721,7 +3782,7 @@ have a history of their own.") | |||
| 3721 | col)))) | 3782 | col)))) |
| 3722 | columns)) | 3783 | columns)) |
| 3723 | (cc (transient--seq-reductions-from | 3784 | (cc (transient--seq-reductions-from |
| 3724 | (apply-partially #'+ (* 3 (if vp (transient--pixel-width " ") 1))) | 3785 | (apply-partially #'+ (* 2 (if vp (transient--pixel-width " ") 1))) |
| 3725 | cw 0))) | 3786 | cw 0))) |
| 3726 | (if transient-force-single-column | 3787 | (if transient-force-single-column |
| 3727 | (dotimes (c cs) | 3788 | (dotimes (c cs) |
| @@ -3750,14 +3811,12 @@ have a history of their own.") | |||
| 3750 | (insert ?\n)))))))) | 3811 | (insert ?\n)))))))) |
| 3751 | 3812 | ||
| 3752 | (cl-defmethod transient--insert-group ((group transient-subgroups)) | 3813 | (cl-defmethod transient--insert-group ((group transient-subgroups)) |
| 3753 | (let* ((subgroups (oref group suffixes)) | 3814 | (let ((subgroups (oref group suffixes))) |
| 3754 | (n (length subgroups))) | 3815 | (while-let ((subgroup (pop subgroups))) |
| 3755 | (dotimes (s n) | 3816 | (transient--maybe-pad-keys subgroup group) |
| 3756 | (let ((subgroup (nth s subgroups))) | 3817 | (transient--insert-group subgroup) |
| 3757 | (transient--maybe-pad-keys subgroup group) | 3818 | (when subgroups |
| 3758 | (transient--insert-group subgroup) | 3819 | (insert ?\n))))) |
| 3759 | (when (< s (1- n)) | ||
| 3760 | (insert ?\n)))))) | ||
| 3761 | 3820 | ||
| 3762 | (cl-defgeneric transient-format (obj) | 3821 | (cl-defgeneric transient-format (obj) |
| 3763 | "Format and return OBJ for display. | 3822 | "Format and return OBJ for display. |
| @@ -3889,28 +3948,22 @@ as a button." | |||
| 3889 | (cl-defgeneric transient-format-description (obj) | 3948 | (cl-defgeneric transient-format-description (obj) |
| 3890 | "Format OBJ's `description' for display and return the result.") | 3949 | "Format OBJ's `description' for display and return the result.") |
| 3891 | 3950 | ||
| 3892 | (cl-defmethod transient-format-description ((obj transient-child)) | 3951 | (cl-defmethod transient-format-description ((obj transient-suffix)) |
| 3893 | "The `description' slot may be a function, in which case that is | 3952 | "The `description' slot may be a function, in which case that is |
| 3894 | called inside the correct buffer (see `transient--insert-group') | 3953 | called inside the correct buffer (see `transient--insert-group') |
| 3895 | and its value is returned to the caller." | 3954 | and its value is returned to the caller." |
| 3896 | (and-let* ((desc (oref obj description)) | 3955 | (transient--get-description obj)) |
| 3897 | (desc (if (functionp desc) | ||
| 3898 | (if (= (car (func-arity desc)) 1) | ||
| 3899 | (funcall desc obj) | ||
| 3900 | (funcall desc)) | ||
| 3901 | desc))) | ||
| 3902 | (if-let* ((face (transient--get-face obj 'face))) | ||
| 3903 | (transient--add-face desc face t) | ||
| 3904 | desc))) | ||
| 3905 | 3956 | ||
| 3906 | (cl-defmethod transient-format-description ((obj transient-group)) | 3957 | (cl-defmethod transient-format-description ((obj transient-group)) |
| 3907 | "Format the description by calling the next method. If the result | 3958 | "Format the description by calling the next method. If the result |
| 3908 | doesn't use the `face' property at all, then apply the face | 3959 | doesn't use the `face' property at all, then apply the face |
| 3909 | `transient-heading' to the complete string." | 3960 | `transient-heading' to the complete string." |
| 3910 | (and-let* ((desc (cl-call-next-method obj))) | 3961 | (and-let* ((desc (transient--get-description obj))) |
| 3911 | (if (text-property-not-all 0 (length desc) 'face nil desc) | 3962 | (cond ((oref obj inapt) |
| 3912 | desc | 3963 | (propertize desc 'face 'transient-inapt-suffix)) |
| 3913 | (propertize desc 'face 'transient-heading)))) | 3964 | ((text-property-not-all 0 (length desc) 'face nil desc) |
| 3965 | desc) | ||
| 3966 | ((propertize desc 'face 'transient-heading))))) | ||
| 3914 | 3967 | ||
| 3915 | (cl-defmethod transient-format-description :around ((obj transient-suffix)) | 3968 | (cl-defmethod transient-format-description :around ((obj transient-suffix)) |
| 3916 | "Format the description by calling the next method. If the result | 3969 | "Format the description by calling the next method. If the result |
| @@ -3920,8 +3973,11 @@ If the OBJ's `key' is currently unreachable, then apply the face | |||
| 3920 | (let ((desc (or (cl-call-next-method obj) | 3973 | (let ((desc (or (cl-call-next-method obj) |
| 3921 | (and (slot-boundp transient--prefix 'suffix-description) | 3974 | (and (slot-boundp transient--prefix 'suffix-description) |
| 3922 | (funcall (oref transient--prefix suffix-description) | 3975 | (funcall (oref transient--prefix suffix-description) |
| 3923 | obj)) | 3976 | obj))))) |
| 3924 | (propertize "(BUG: no description)" 'face 'error)))) | 3977 | (if desc |
| 3978 | (when-let ((face (transient--get-face obj 'face))) | ||
| 3979 | (setq desc (transient--add-face desc face t))) | ||
| 3980 | (setq desc (propertize "(BUG: no description)" 'face 'error))) | ||
| 3925 | (when (if transient--all-levels-p | 3981 | (when (if transient--all-levels-p |
| 3926 | (> (oref obj level) transient--default-prefix-level) | 3982 | (> (oref obj level) transient--default-prefix-level) |
| 3927 | (and transient-highlight-higher-levels | 3983 | (and transient-highlight-higher-levels |
| @@ -3983,23 +4039,30 @@ If the OBJ's `key' is currently unreachable, then apply the face | |||
| 3983 | choices | 4039 | choices |
| 3984 | (propertize "|" 'face 'transient-delimiter)))))) | 4040 | (propertize "|" 'face 'transient-delimiter)))))) |
| 3985 | 4041 | ||
| 3986 | (defun transient--add-face (string face &optional append beg end) | 4042 | (cl-defmethod transient--get-description ((obj transient-child)) |
| 3987 | (let ((str (copy-sequence string))) | 4043 | (and-let* ((desc (oref obj description))) |
| 3988 | (add-face-text-property (or beg 0) (or end (length str)) face append str) | 4044 | (if (functionp desc) |
| 3989 | str)) | 4045 | (if (= (car (transient--func-arity desc)) 1) |
| 4046 | (funcall desc obj) | ||
| 4047 | (funcall desc)) | ||
| 4048 | desc))) | ||
| 3990 | 4049 | ||
| 3991 | (defun transient--get-face (obj slot) | 4050 | (cl-defmethod transient--get-face ((obj transient-suffix) slot) |
| 3992 | (and-let* ((! (slot-exists-p obj slot)) | 4051 | (and-let* (((slot-boundp obj slot)) |
| 3993 | (! (slot-boundp obj slot)) | ||
| 3994 | (face (slot-value obj slot))) | 4052 | (face (slot-value obj slot))) |
| 3995 | (if (and (not (facep face)) | 4053 | (if (and (not (facep face)) |
| 3996 | (functionp face)) | 4054 | (functionp face)) |
| 3997 | (let ((transient--pending-suffix obj)) | 4055 | (let ((transient--pending-suffix obj)) |
| 3998 | (if (= (car (func-arity face)) 1) | 4056 | (if (= (car (transient--func-arity face)) 1) |
| 3999 | (funcall face obj) | 4057 | (funcall face obj) |
| 4000 | (funcall face))) | 4058 | (funcall face))) |
| 4001 | face))) | 4059 | face))) |
| 4002 | 4060 | ||
| 4061 | (defun transient--add-face (string face &optional append beg end) | ||
| 4062 | (let ((str (copy-sequence string))) | ||
| 4063 | (add-face-text-property (or beg 0) (or end (length str)) face append str) | ||
| 4064 | str)) | ||
| 4065 | |||
| 4003 | (defun transient--key-face (&optional cmd enforce-type) | 4066 | (defun transient--key-face (&optional cmd enforce-type) |
| 4004 | (or (and transient-semantic-coloring | 4067 | (or (and transient-semantic-coloring |
| 4005 | (not transient--helpp) | 4068 | (not transient--helpp) |
| @@ -4025,12 +4088,13 @@ If the OBJ's `key' is currently unreachable, then apply the face | |||
| 4025 | (when-let ((pad (or (oref group pad-keys) | 4088 | (when-let ((pad (or (oref group pad-keys) |
| 4026 | (and parent (oref parent pad-keys))))) | 4089 | (and parent (oref parent pad-keys))))) |
| 4027 | (oset group pad-keys | 4090 | (oset group pad-keys |
| 4028 | (apply #'max (cons (if (integerp pad) pad 0) | 4091 | (apply #'max |
| 4029 | (seq-keep (lambda (suffix) | 4092 | (if (integerp pad) pad 0) |
| 4030 | (and (eieio-object-p suffix) | 4093 | (seq-keep (lambda (suffix) |
| 4031 | (slot-boundp suffix 'key) | 4094 | (and (eieio-object-p suffix) |
| 4032 | (length (oref suffix key)))) | 4095 | (slot-boundp suffix 'key) |
| 4033 | (oref group suffixes))))))) | 4096 | (length (oref suffix key)))) |
| 4097 | (oref group suffixes)))))) | ||
| 4034 | 4098 | ||
| 4035 | (defun transient--pixel-width (string) | 4099 | (defun transient--pixel-width (string) |
| 4036 | (save-window-excursion | 4100 | (save-window-excursion |
| @@ -4386,7 +4450,8 @@ we stop there." | |||
| 4386 | (face-remap-reset-base 'default) | 4450 | (face-remap-reset-base 'default) |
| 4387 | (face-remap-add-relative 'default 'fixed-pitch)) | 4451 | (face-remap-add-relative 'default 'fixed-pitch)) |
| 4388 | 4452 | ||
| 4389 | ;;;; Missing from Emacs | 4453 | (defun transient--func-arity (fn) |
| 4454 | (func-arity (advice--cd*r (if (symbolp fn) (symbol-function fn) fn)))) | ||
| 4390 | 4455 | ||
| 4391 | (defun transient--seq-reductions-from (function sequence initial-value) | 4456 | (defun transient--seq-reductions-from (function sequence initial-value) |
| 4392 | (let ((acc (list initial-value))) | 4457 | (let ((acc (list initial-value))) |
| @@ -4394,18 +4459,6 @@ we stop there." | |||
| 4394 | (push (funcall function (car acc) elt) acc)) | 4459 | (push (funcall function (car acc) elt) acc)) |
| 4395 | (nreverse acc))) | 4460 | (nreverse acc))) |
| 4396 | 4461 | ||
| 4397 | (defun transient-plist-to-alist (plist) | ||
| 4398 | (let (alist) | ||
| 4399 | (while plist | ||
| 4400 | (push (cons (let* ((symbol (pop plist)) | ||
| 4401 | (name (symbol-name symbol))) | ||
| 4402 | (if (eq (aref name 0) ?:) | ||
| 4403 | (intern (substring name 1)) | ||
| 4404 | symbol)) | ||
| 4405 | (pop plist)) | ||
| 4406 | alist)) | ||
| 4407 | (nreverse alist))) | ||
| 4408 | |||
| 4409 | ;;; Font-Lock | 4462 | ;;; Font-Lock |
| 4410 | 4463 | ||
| 4411 | (defconst transient-font-lock-keywords | 4464 | (defconst transient-font-lock-keywords |