From fb191f8cf369a741a26d40456ca7291fda4ff3cc Mon Sep 17 00:00:00 2001 From: Jonas Bernoulli Date: Thu, 19 Oct 2023 16:20:09 +0200 Subject: [PATCH] Optionally refresh suffixes and keymaps after every command Closes #157. --- docs/transient.org | 11 +++++++++++ docs/transient.texi | 12 ++++++++++++ lisp/transient.el | 29 ++++++++++++++++++++++++----- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/docs/transient.org b/docs/transient.org index 1228f853..e034e0fb 100644 --- a/docs/transient.org +++ b/docs/transient.org @@ -1746,6 +1746,13 @@ functions use ~describe-function~. remains active/transient when a suffix or arbitrary non-suffix command is invoked. See [[*Transient State]]. +- ~refresh-suffixes~ Normally suffix objects and keymaps are only setup + once, when the prefix is invoked. Setting this to ~t~, causes them to + be recreated after every command. This is useful when using ~:if...~ + predicates, and those need to be rerun for some reason. Doing this + is somewhat costly, and there is a risk of losing state, so this is + disabled by default and still considered experimental. + - ~incompatible~ A list of lists. Each sub-list specifies a set of mutually exclusive arguments. Enabling one of these arguments causes the others to be disabled. An argument may appear in @@ -1919,6 +1926,10 @@ what happens if you use more than one. - ~if-derived~ Enable if major-mode derives from value. - ~if-not-derived~ Enable if major-mode does not derive from value. +By default these predicates run when the prefix command is invoked, +but this can be changes, using the ~refresh-suffixes~ prefix slot. +See [[*Prefix Slots]]. + One more slot is shared between group and suffix classes, ~level~. Like the slots documented above, it is a predicate, but it is used for a different purpose. The value has to be an integer between 1 diff --git a/docs/transient.texi b/docs/transient.texi index 637c5d1e..f2dcb14c 100644 --- a/docs/transient.texi +++ b/docs/transient.texi @@ -1990,6 +1990,14 @@ determining whether the currently active transient prefix command remains active/transient when a suffix or arbitrary non-suffix command is invoked. See @ref{Transient State}. +@item +@code{refresh-suffixes} Normally suffix objects and keymaps are only setup +once, when the prefix is invoked. Setting this to @code{t}, causes them to +be recreated after every command. This is useful when using @code{:if...} +predicates, and those need to be rerun for some reason. Doing this +is somewhat costly, and there is a risk of losing state, so this is +disabled by default and still considered experimental. + @item @code{incompatible} A list of lists. Each sub-list specifies a set of mutually exclusive arguments. Enabling one of these arguments @@ -2212,6 +2220,10 @@ what happens if you use more than one. @code{if-not-derived} Enable if major-mode does not derive from value. @end itemize +By default these predicates run when the prefix command is invoked, +but this can be changes, using the @code{refresh-suffixes} prefix slot. +See @ref{Prefix Slots}. + One more slot is shared between group and suffix classes, @code{level}. Like the slots documented above, it is a predicate, but it is used for a different purpose. The value has to be an integer between 1 diff --git a/lisp/transient.el b/lisp/transient.el index 6d7abea4..4542f2bf 100644 --- a/lisp/transient.el +++ b/lisp/transient.el @@ -634,6 +634,7 @@ If `transient-save-history' is nil, then do nothing." (man-page :initarg :man-page :initform nil) (transient-suffix :initarg :transient-suffix :initform nil) (transient-non-suffix :initarg :transient-non-suffix :initform nil) + (refresh-suffixes :initarg :refresh-suffixes :initform nil) (incompatible :initarg :incompatible :initform nil) (suffix-description :initarg :suffix-description) (variable-pitch :initarg :variable-pitch :initform nil) @@ -1811,10 +1812,8 @@ EDIT may be non-nil." ;; Returning from help to edit. (setq transient--editp t))) (transient--init-objects name layout params) + (transient--init-keymaps) (transient--history-init transient--prefix) - (setq transient--predicate-map (transient--make-predicate-map)) - (setq transient--transient-map (transient--make-transient-map)) - (setq transient--redisplay-map (transient--make-redisplay-map)) (setq transient--original-window (selected-window)) (setq transient--original-buffer (current-buffer)) (setq transient--minibuffer-depth (minibuffer-depth)) @@ -1831,8 +1830,15 @@ value. Otherwise return CHILDREN as is." (funcall (oref group setup-children) children) children)) -(defun transient--init-objects (name layout params) - (setq transient--prefix (transient--init-prefix name params)) +(defun transient--init-keymaps () + (setq transient--predicate-map (transient--make-predicate-map)) + (setq transient--transient-map (transient--make-transient-map)) + (setq transient--redisplay-map (transient--make-redisplay-map))) + +(defun transient--init-objects (&optional name layout params) + (if name + (setq transient--prefix (transient--init-prefix name params)) + (setq name (oref transient--prefix command))) (setq transient--layout (or layout (transient--init-suffixes name))) (setq transient--suffixes (transient--flatten-suffixes transient--layout))) @@ -2014,6 +2020,17 @@ value. Otherwise return CHILDREN as is." ;; that we just added. (setq transient--exitp 'replace))) +(defun transient--refresh-transient () + (transient--debug 'refresh-transient) + (transient--pop-keymap 'transient--predicate-map) + (transient--pop-keymap 'transient--transient-map) + (transient--pop-keymap 'transient--redisplay-map) + (transient--init-objects) + (transient--init-keymaps) + (transient--push-keymap 'transient--transient-map) + (transient--push-keymap 'transient--redisplay-map) + (transient--redisplay)) + (defun transient--pre-command () (transient--debug 'pre-command) (transient--with-emergency-exit @@ -2273,6 +2290,8 @@ value. Otherwise return CHILDREN as is." ;; would have to be used to record that a universal ;; argument is in effect. (not prefix-arg))) + ((oref transient--prefix refresh-suffixes) + (transient--refresh-transient)) ((let ((old transient--redisplay-map) (new (transient--make-redisplay-map))) (unless (equal old new)