branch: externals/transient commit f6c249c7f68deec44ed63d18e35aa112b0b294be Author: Jonas Bernoulli <jo...@bernoul.li> Commit: Jonas Bernoulli <jo...@bernoul.li>
Allow setting a suffix's default level via its prototype --- docs/transient.org | 42 ++++++++++++++++++++++++++++++++++++++++++ docs/transient.texi | 42 ++++++++++++++++++++++++++++++++++++++++++ lisp/transient.el | 31 +++++++++++++++++++++++++------ 3 files changed, 109 insertions(+), 6 deletions(-) diff --git a/docs/transient.org b/docs/transient.org index 5c27813dea..6d9c33c786 100644 --- a/docs/transient.org +++ b/docs/transient.org @@ -408,6 +408,48 @@ available even if the user lowers the transient level. the level specified by ~transient-default-level~ are temporarily available anyway. +- Function: transient-set-default-level suffix level :: + + This function sets the default level of the suffix COMMAND to LEVEL. + + If a suffix command appears in multiple menus, it may make sense to + consistently change its level in all those menus at once. For + example, the ~--gpg-sign~ argument (which is implemented using the + command ~magit:--gpg-sign~), is bound in all of Magit's menu which + create commits. Users who sometimes sign their commits would want + that argument to be available in all of these menus, while for users + who never sign it is just unnecessary noise in any menus. + + To always make ~--gpg-sign~ available, use: + + #+begin_src emacs-lisp + (transient-set-default-level 'magit:--gpg-sign 1) + #+end_src + + To never make ~--gpg-sign~ available, use: + + #+begin_src emacs-lisp + (transient-set-default-level 'magit:--gpg-sign 0) + #+end_src + + This sets the level in the suffix prototype object for this command. + Commands only have a suffix prototype if they were defined using one + of ~transient-define-argument~, ~transient-define-infix~ and + ~transient-define-suffix~. For all other commands this would signal + an error. (This is one of the reasons why package authors should + use one of these functions to define shared suffix commands, and + especially shared arguments.) + + If the user changes the level of a suffix in a particular menu, + using {{{kbd(C-x l)}}} as shown above, then that obviously shadows the default. + + It is also possible to set the level of a suffix binding in a + particular menu, either when defining the menu using + ~transient-define-prefix,~ or later using ~transient-insert-suffix~. If + such bindings specify a level, then that also overrides the default. + (Per-suffix default levels is a new feature, so you might encounter + this quite often.) + ** Other Commands When invoking a transient in a small frame, the transient window may diff --git a/docs/transient.texi b/docs/transient.texi index 70aa0200e2..5527e8bc2b 100644 --- a/docs/transient.texi +++ b/docs/transient.texi @@ -554,6 +554,48 @@ the level specified by @code{transient-default-level} are temporarily available anyway. @end table +@defun transient-set-default-level suffix level +This function sets the default level of the suffix COMMAND to LEVEL@. + +If a suffix command appears in multiple menus, it may make sense to +consistently change its level in all those menus at once. For +example, the @code{--gpg-sign} argument (which is implemented using the +command @code{magit:--gpg-sign}), is bound in all of Magit's menu which +create commits. Users who sometimes sign their commits would want +that argument to be available in all of these menus, while for users +who never sign it is just unnecessary noise in any menus. + +To always make @code{--gpg-sign} available, use: + +@lisp +(transient-set-default-level 'magit:--gpg-sign 1) +@end lisp + +To never make @code{--gpg-sign} available, use: + +@lisp +(transient-set-default-level 'magit:--gpg-sign 0) +@end lisp + +This sets the level in the suffix prototype object for this command. +Commands only have a suffix prototype if they were defined using one +of @code{transient-define-argument}, @code{transient-define-infix} and +@code{transient-define-suffix}. For all other commands this would signal +an error. (This is one of the reasons why package authors should +use one of these functions to define shared suffix commands, and +especially shared arguments.) + +If the user changes the level of a suffix in a particular menu, +using @kbd{C-x l} as shown above, then that obviously shadows the default. + +It is also possible to set the level of a suffix binding in a +particular menu, either when defining the menu using +@code{transient-define-prefix,} or later using @code{transient-insert-suffix}. If +such bindings specify a level, then that also overrides the default. +(Per-suffix default levels is a new feature, so you might encounter +this quite often.) +@end defun + @node Other Commands @section Other Commands diff --git a/lisp/transient.el b/lisp/transient.el index 3165d964aa..c2a25f167c 100644 --- a/lisp/transient.el +++ b/lisp/transient.el @@ -774,7 +774,7 @@ the prototype is stored in the clone's `prototype' slot.") :documentation "The parent group object.") (level :initarg :level - :initform (symbol-value 'transient--default-child-level) + :initform nil :documentation "Enable if level of prefix is equal or greater.") (if :initarg :if @@ -1269,7 +1269,7 @@ commands are aliases for." (message "WARNING: %s: When %s is used, %s must also be specified" 'transient-define-prefix :setup-children :class)) (list 'vector - (or level transient--default-child-level) + level (list 'quote (cond (class) ((cl-typep (car spec) @@ -1370,7 +1370,7 @@ commands are aliases for." (shortarg (plist-get args :shortarg))) (use :key shortarg))) (list 'list - (or level transient--default-child-level) + level (macroexp-quote (or class 'transient-suffix)) (cons 'list args)))) @@ -1605,6 +1605,21 @@ See info node `(transient)Modifying Existing Transients'." (defun transient--nthcdr (n list) (nthcdr (if (< n 0) (- (length list) (abs n)) n) list)) +(defun transient-set-default-level (command level) + "Set the default level of suffix COMMAND to LEVEL. + +The default level is shadowed if the binding of the suffix in a +prefix menu specifies a level, and also if the user changes the +level of such a binding. + +The default level can only be set for commands that were defined +using `transient-define-suffix', `transient-define-infix' or +`transient-define-argument'." + (if-let ((proto (transient--suffix-prototype command))) + (oset proto level level) + (user-error "Cannot set level for `%s'; no prototype object exists" + command))) + ;;; Variables (defvar transient-current-prefix nil @@ -2291,7 +2306,8 @@ value. Otherwise return CHILDREN as is.") (string (list spec)))) (defun transient--init-group (levels spec parent) - (pcase-let ((`(,level ,class ,args ,children) (append spec nil))) + (pcase-let* ((`(,level ,class ,args ,children) (append spec nil)) + (level (or level transient--default-child-level))) (and-let* (((transient--use-level-p level)) (obj (apply class :parent parent :level level args)) ((transient--use-suffix-p obj)) @@ -2308,9 +2324,12 @@ value. Otherwise return CHILDREN as is.") (pcase-let* ((`(,level ,class ,args) spec) (cmd (plist-get args :command)) (key (transient--kbd (plist-get args :key))) + (proto (and cmd (transient--suffix-prototype cmd))) (level (or (alist-get (cons cmd key) levels nil nil #'equal) (alist-get cmd levels) - level))) + level + (and proto (oref proto level)) + transient--default-child-level))) (let ((fn (and (symbolp cmd) (symbol-function cmd)))) (when (autoloadp fn) @@ -2321,7 +2340,7 @@ value. Otherwise return CHILDREN as is.") (apply class :parent parent :level level args) (unless (and cmd (symbolp cmd)) (error "BUG: Non-symbolic suffix command: %s" cmd)) - (if-let ((proto (and cmd (transient--suffix-prototype cmd)))) + (if proto (apply #'clone proto :level level args) (apply class :command cmd :parent parent :level level args)))))