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)))))

Reply via email to