From 11a83038585237b49262a6dff6d92464946bd619 Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Sun, 22 Dec 2024 13:21:24 +0100 Subject: [PATCH] update transient Signed-off-by: Andreas Gerler --- elpa/transient-20240729.1524/transient-pkg.el | 16 - .../dir | 0 .../gpl.info | 0 .../transient-autoloads.el | 0 elpa/transient-20241219.1713/transient-pkg.el | 12 + .../transient.el | 1352 +++++++++++------ .../transient.info | 882 ++++++++--- elpa/transient-readme.txt | 21 - 8 files changed, 1528 insertions(+), 755 deletions(-) delete mode 100644 elpa/transient-20240729.1524/transient-pkg.el rename elpa/{transient-20240729.1524 => transient-20241219.1713}/dir (100%) rename elpa/{transient-20240729.1524 => transient-20241219.1713}/gpl.info (100%) rename elpa/{transient-20240729.1524 => transient-20241219.1713}/transient-autoloads.el (100%) create mode 100644 elpa/transient-20241219.1713/transient-pkg.el rename elpa/{transient-20240729.1524 => transient-20241219.1713}/transient.el (80%) rename elpa/{transient-20240729.1524 => transient-20241219.1713}/transient.info (83%) delete mode 100644 elpa/transient-readme.txt diff --git a/elpa/transient-20240729.1524/transient-pkg.el b/elpa/transient-20240729.1524/transient-pkg.el deleted file mode 100644 index 178fb458..00000000 --- a/elpa/transient-20240729.1524/transient-pkg.el +++ /dev/null @@ -1,16 +0,0 @@ -(define-package "transient" "20240729.1524" "Transient commands" - '((emacs "26.1") - (compat "30.0.0.0") - (seq "2.24")) - :commit "6543000d5a509096f0f98eb4b814d7f6f2114ce3" :authors - '(("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) - :maintainers - '(("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) - :maintainer - '("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev") - :keywords - '("extensions") - :url "https://github.com/magit/transient") -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/transient-20240729.1524/dir b/elpa/transient-20241219.1713/dir similarity index 100% rename from elpa/transient-20240729.1524/dir rename to elpa/transient-20241219.1713/dir diff --git a/elpa/transient-20240729.1524/gpl.info b/elpa/transient-20241219.1713/gpl.info similarity index 100% rename from elpa/transient-20240729.1524/gpl.info rename to elpa/transient-20241219.1713/gpl.info diff --git a/elpa/transient-20240729.1524/transient-autoloads.el b/elpa/transient-20241219.1713/transient-autoloads.el similarity index 100% rename from elpa/transient-20240729.1524/transient-autoloads.el rename to elpa/transient-20241219.1713/transient-autoloads.el diff --git a/elpa/transient-20241219.1713/transient-pkg.el b/elpa/transient-20241219.1713/transient-pkg.el new file mode 100644 index 00000000..e905ce0c --- /dev/null +++ b/elpa/transient-20241219.1713/transient-pkg.el @@ -0,0 +1,12 @@ +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "transient" "20241219.1713" + "Transient commands." + '((emacs "26.1") + (compat "30.0.0.0") + (seq "2.24")) + :url "https://github.com/magit/transient" + :commit "5a18a79100bc5c4a5239f3917c1c1c4058a11769" + :revdesc "5a18a79100bc" + :keywords '("extensions") + :authors '(("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) + :maintainers '(("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev"))) diff --git a/elpa/transient-20240729.1524/transient.el b/elpa/transient-20241219.1713/transient.el similarity index 80% rename from elpa/transient-20240729.1524/transient.el rename to elpa/transient-20241219.1713/transient.el index 9630be66..48920070 100644 --- a/elpa/transient-20240729.1524/transient.el +++ b/elpa/transient-20241219.1713/transient.el @@ -6,7 +6,8 @@ ;; Homepage: https://github.com/magit/transient ;; Keywords: extensions -;; Package-Version: 0.7.3 +;; Package-Version: 20241219.1713 +;; Package-Revision: 5a18a79100bc ;; Package-Requires: ((emacs "26.1") (compat "30.0.0.0") (seq "2.24")) ;; SPDX-License-Identifier: GPL-3.0-or-later @@ -39,6 +40,7 @@ (require 'eieio) (require 'edmacro) (require 'format-spec) +(require 'pcase) (eval-and-compile (when (and (featurep 'seq) @@ -48,7 +50,7 @@ (unless (fboundp 'seq-keep) (display-warning 'transient (substitute-command-keys "\ Transient requires `seq' >= 2.24, -but due to bad defaults, Emacs' package manager, refuses to +but due to bad defaults, Emacs's package manager, refuses to upgrade this and other built-in packages to higher releases from GNU Elpa, when a package specifies that this is needed. @@ -85,6 +87,19 @@ similar defect.") :emergency)) (defvar Man-notify-method) (defvar pp-default-function) ; since Emacs 29.1 +(eval-and-compile + (when (< emacs-major-version 28) + (pcase-defmacro cl-type (type) + "Pcase pattern that matches objects of TYPE. +TYPE is a type descriptor as accepted by `cl-typep', which see." + (static-if (< emacs-major-version 30) + `(pred (pcase--flip cl-typep ',type)) + `(pred (cl-typep _ ',type)))))) + +(make-obsolete-variable 'transient-hide-during-minibuffer-read + "use `transient-show-during-minibuffer-read' instead." + "0.8.0") + (defmacro transient--with-emergency-exit (id &rest body) (declare (indent defun)) (unless (keywordp id) @@ -130,9 +145,12 @@ similar defect.") :emergency)) (const :tag "on demand (no summary)" 0) (number :tag "after delay" 1))) -(defcustom transient-enable-popup-navigation t +(defcustom transient-enable-popup-navigation 'verbose "Whether navigation commands are enabled in the transient popup. +If the value is `verbose', additionally show brief documentation +about the command under point in the echo area. + While a transient is active the transient popup buffer is not the current buffer, making it necessary to use dedicated commands to act on that buffer itself. If this is non-nil, then the following @@ -152,19 +170,20 @@ bindings are available: All other bindings are in `transient-popup-navigation-map'. By default \\`M-RET' is bound to `transient-push-button', instead of -\\`RET', because if a transient allows the invocation of non-suffixes -then it is likely that you would want \\`RET' to do what it would do +\\`RET', because if a transient allows the invocation of non-suffixes, +then it is likely, that you would want \\`RET' to do what it would do if no transient were active." - :package-version '(transient . "0.4.0") + :package-version '(transient . "0.7.8") :group 'transient - :type 'boolean) + :type '(choice (const :tag "enable navigation and echo summary" verbose) + (const :tag "enable navigation commands" t) + (const :tag "disable navigation commands" nil))) (defcustom transient-display-buffer-action '(display-buffer-in-side-window (side . bottom) (dedicated . t) - (inhibit-same-window . t) - (window-parameters (no-other-window . t))) + (inhibit-same-window . t)) "The action used to display the transient popup buffer. The transient popup buffer is displayed in a window using @@ -182,14 +201,11 @@ The default is: (display-buffer-in-side-window (side . bottom) (dedicated . t) - (inhibit-same-window . t) - (window-parameters (no-other-window . t))) + (inhibit-same-window . t)) This displays the window at the bottom of the selected frame. -Another useful FUNCTION is `display-buffer-below-selected', which -is what `magit-popup' used by default. For more alternatives see -info node `(elisp)Display Action Functions' and info node -`(elisp)Buffer Display Action Alists'. +For alternatives see info node `(elisp)Display Action Functions' +and info node `(elisp)Buffer Display Action Alists'. Note that the buffer that was current before the transient buffer is shown should remain the current buffer. Many suffix commands @@ -198,6 +214,11 @@ buffer became the current buffer, then that would change what is at point. To that effect `inhibit-same-window' ensures that the selected window is not used to show the transient buffer. +The use of a horizontal split to display the menu window can lead +to incompatibilities and is thus discouraged. Transient tries to +mitigate such issue but cannot proactively deal with all possible +configurations and combinations of third-party packages. + It may be possible to display the window in another frame, but whether that works in practice depends on the window-manager. If the window manager selects the new window (Emacs frame), @@ -205,11 +226,20 @@ then that unfortunately changes which buffer is current. If you change the value of this option, then you might also want to change the value of `transient-mode-line-format'." - :package-version '(transient . "0.3.0") + :package-version '(transient . "0.7.5") :group 'transient :type '(cons (choice function (repeat :tag "Functions" function)) alist)) +(defcustom transient-minimal-frame-width 83 + "Minimal width of dedicated frame used to display transient menu. +This is only used if the transient menu is actually displayed in a +dedicated frame (see `transient-display-buffer-action'). The value +is in characters." + :package-version '(transient . "0.8.1") + :group 'transient + :type 'natnum) + (defcustom transient-mode-line-format 'line "The mode-line format for the transient popup buffer. @@ -217,15 +247,14 @@ If nil, then the buffer has no mode-line. If the buffer is not displayed right above the echo area, then this probably is not a good value. -If `line' (the default) or a natural number, then the buffer -has no mode-line, but a line is drawn is drawn in its place. -If a number is used, that specifies the thickness of the line. -On termcap frames we cannot draw lines, so there `line' and -numbers are synonyms for nil. +If `line' (the default) or a natural number, then the buffer has no +mode-line, but a line is drawn in its place. If a number is used, +that specifies the thickness of the line. On termcap frames we +cannot draw lines, so there `line' and numbers are synonyms for nil. The color of the line is used to indicate if non-suffixes are allowed and whether they exit the transient. The foreground -color of `transient-key-noop' (if non-suffix are disallowed), +color of `transient-key-noop' (if non-suffixes are disallowed), `transient-key-stay' (if allowed and transient stays active), or `transient-key-exit' (if allowed and they exit the transient) is used to draw the line. @@ -252,6 +281,51 @@ of this variable use \"C-x t\" when a transient is active." :group 'transient :type 'boolean) +(defcustom transient-show-during-minibuffer-read nil + "Whether to show the transient menu while reading in the minibuffer. + +This is only relevant to commands that do not close the menu, such as +commands that set infix arguments. If a command exits the menu, and +uses the minibuffer, then the menu is always closed before the +minibuffer is entered, irrespective of the value of this option. + +When nil (the default), hide the menu while the minibuffer is in use. +When t, keep showing the menu, but allow for the menu window to be +resized, to ensure that completion candidates can be displayed. + +When `fixed', keep showing the menu and prevent it from being resized, +which may make it impossible to display the completion candidates. If +that ever happens for you, consider using t or an integer, as described +below. + +If the value is `fixed' and the menu window uses the full height of its +frame, then the former is ignored and resizing is allowed anyway. This +is necessary because individual menus may use unusual display actions +different from what `transient-display-buffer-action' specifies (likely +to display that menu in a side-window). + +When using a third-party mode, which automatically resizes windows +\(e.g., by calling `balance-windows' on `post-command-hook'), then +`fixed' (or nil) is likely a better choice than t. + +The value can also be an integer, in which case the behavior depends on +whether at least that many lines are left to display windows other than +the menu window. If that is the case, display the menu and preserve the +size of that window. Otherwise, allow resizing the menu window if the +number is positive, or hide the menu if it is negative." + :package-version '(transient . "0.8.0") + :group 'transient + :type '(choice + (const :tag "Hide menu" nil) + (const :tag "Show menu and preserve size" fixed) + (const :tag "Show menu and allow resizing" t) + (natnum :tag "Show menu, allow resizing if less than N lines left" + :format "\n %t: %v" + :value 20) + (integer :tag "Show menu, except if less than N lines left" + :format "\n %t: %v" + :value -20))) + (defcustom transient-read-with-initial-input nil "Whether to use the last history element as initial minibuffer input." :package-version '(transient . "0.2.0") @@ -346,7 +420,7 @@ used that breaks that relationship. This option is intended for users who use a variable-pitch font for the `default' face. -Also see `transient-force-fixed-pitch'." +See also `transient-force-fixed-pitch'." :package-version '(transient . "0.4.0") :group 'transient :type 'boolean) @@ -359,7 +433,7 @@ you might still want to use a monospaced font in transient's popup buffer. Setting this option to t causes `default' to be remapped to `fixed-pitch' in that buffer. -Also see `transient-align-variable-pitch'." +See also `transient-align-variable-pitch'." :package-version '(transient . "0.2.0") :group 'transient :type 'boolean) @@ -373,12 +447,6 @@ text and might otherwise have to scroll in two dimensions." :group 'transient :type 'boolean) -(defcustom transient-hide-during-minibuffer-read nil - "Whether to hide the transient buffer while reading in the minibuffer." - :package-version '(transient . "0.4.0") - :group 'transient - :type 'boolean) - (defconst transient--max-level 7) (defconst transient--default-child-level 1) (defconst transient--default-prefix-level 4) @@ -505,7 +573,7 @@ See info node `(transient)Enabling and Disabling Suffixes'." (or (and (not (eq color 'unspecified)) color) "grey60"))))) "Face optionally used to highlight suffixes on higher levels. -Also see option `transient-highlight-higher-levels'." +See also option `transient-highlight-higher-levels'." :group 'transient-faces) (defface transient-delimiter '((t :inherit shadow)) @@ -567,14 +635,14 @@ character used to separate possible values from each other." `((t :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1) :color "cyan"))) "Face optionally used to highlight keys conflicting with short-argument. -Also see option `transient-highlight-mismatched-keys'." +See also option `transient-highlight-mismatched-keys'." :group 'transient-faces) (defface transient-mismatched-key `((t :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1) :color "magenta"))) "Face optionally used to highlight keys without a short-argument. -Also see option `transient-highlight-mismatched-keys'." +See also option `transient-highlight-mismatched-keys'." :group 'transient-faces) ;;; Persistence @@ -646,7 +714,6 @@ If `transient-save-history' is nil, then do nothing." ((prototype :initarg :prototype) (command :initarg :command) (level :initarg :level) - (variable :initarg :variable :initform nil) (init-value :initarg :init-value) (value) (default-value :initarg :value) (scope :initarg :scope :initform nil) @@ -660,8 +727,11 @@ If `transient-save-history' is nil, then do nothing." (transient-non-suffix :initarg :transient-non-suffix :initform nil) (transient-switch-frame :initarg :transient-switch-frame) (refresh-suffixes :initarg :refresh-suffixes :initform nil) + (environment :initarg :environment :initform nil) (incompatible :initarg :incompatible :initform nil) (suffix-description :initarg :suffix-description) + (display-action :initarg :display-action :initform nil) + (mode-line-format :initarg :mode-line-format) (variable-pitch :initarg :variable-pitch :initform nil) (column-widths :initarg :column-widths :initform nil) (unwind-suffix :documentation "Internal use." :initform nil)) @@ -678,7 +748,11 @@ the prototype is stored in the clone's `prototype' slot.") ;;;; Suffix (defclass transient-child () - ((level + ((parent + :initarg :parent + :initform nil + :documentation "The parent group object.") + (level :initarg :level :initform (symbol-value 'transient--default-child-level) :documentation "Enable if level of prefix is equal or greater.") @@ -753,8 +827,8 @@ the prototype is stored in the clone's `prototype' slot.") :documentation "Inapt if major-mode does not derive from value.")) "Abstract superclass for group and suffix classes. -It is undefined what happens if more than one `if*' predicate -slot is non-nil." +It is undefined which predicates are used if more than one `if*' +predicate slots or more than one `inapt-if*' slots are non-nil." :abstract t) (defclass transient-suffix (transient-child) @@ -765,7 +839,8 @@ slot is non-nil." (format :initarg :format :initform " %k %d") (description :initarg :description :initform nil) (face :initarg :face :initform nil) - (show-help :initarg :show-help :initform nil)) + (show-help :initarg :show-help :initform nil) + (summary :initarg :summary :initform nil)) "Superclass for suffix command.") (defclass transient-information (transient-suffix) @@ -832,6 +907,12 @@ They become the value of this argument.") (set :initarg := :initform nil)) "Class used by the `transient-preset' suffix command.") +(defclass transient-describe-target (transient-suffix) + ((transient :initform #'transient--do-suspend) + (helper :initarg :helper :initform nil) + (target :initarg := :initform nil)) + "Class used by the `transient-describe' suffix command.") + ;;;; Group (defclass transient-group (transient-child) @@ -928,8 +1009,8 @@ to the setup function: (put ',name 'transient--prefix (,(or class 'transient-prefix) :command ',name ,@slots)) (put ',name 'transient--layout - (list ,@(cl-mapcan (lambda (s) (transient--parse-child name s)) - suffixes)))))) + (list ,@(mapcan (lambda (s) (transient--parse-child name s)) + suffixes)))))) (defmacro transient-define-suffix (name arglist &rest args) "Define NAME as a transient suffix command. @@ -1122,7 +1203,7 @@ commands are aliases for." (if (and (listp value) (or (listp (car value)) (vectorp (car value)))) - (cl-mapcan (lambda (s) (transient--parse-child prefix s)) value) + (mapcan (lambda (s) (transient--parse-child prefix s)) value) (transient--parse-child prefix value)))) (vector (and-let* ((c (transient--parse-group prefix spec))) (list c))) (list (and-let* ((c (transient--parse-suffix prefix spec))) (list c))) @@ -1130,134 +1211,134 @@ commands are aliases for." (t (error "Invalid transient--parse-child spec: %s" spec)))) (defun transient--parse-group (prefix spec) - (setq spec (append spec nil)) - (cl-symbol-macrolet - ((car (car spec)) - (pop (pop spec))) - (let (level class args) - (when (integerp car) - (setq level pop)) - (when (stringp car) - (setq args (plist-put args :description pop))) - (while (keywordp car) - (let ((key pop) - (val pop)) - (cond ((eq key :class) - (setq class (macroexp-quote val))) - ((or (symbolp val) - (and (listp val) (not (eq (car val) 'lambda)))) - (setq args (plist-put args key (macroexp-quote val)))) - ((setq args (plist-put args key val)))))) - (unless (or spec class (not (plist-get args :setup-children))) - (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) - (cond (class) - ((or (vectorp car) - (and car (symbolp car))) - (quote 'transient-columns)) - ((quote 'transient-column))) - (and args (cons 'list args)) - (cons 'list - (cl-mapcan (lambda (s) (transient--parse-child prefix s)) - spec)))))) + (let ((spec (append spec nil)) + level class args) + (when (integerp (car spec)) + (setq level (pop spec))) + (when (stringp (car spec)) + (setq args (plist-put args :description (pop spec)))) + ;; Merge value of [... GROUP-VARIABLE], if any. + (let ((spec* spec)) + (while (keywordp (car spec*)) + (setq spec* (cddr spec*))) + (when (and (length= spec* 1) (symbolp (car spec*))) + (let ((rest (append (symbol-value (car spec*)) nil)) + (args nil)) + (while (keywordp (car rest)) + (setq args (nconc (list (pop rest) (pop rest)) args))) + (setq spec (nconc args (butlast spec) rest))))) + (while (keywordp (car spec)) + (let* ((key (pop spec)) + (val (if spec (pop spec) (error "No value for `%s'" key)))) + (cond ((eq key :class) + (setq class val)) + ((or (symbolp val) + (and (listp val) (not (eq (car val) 'lambda)))) + (setq args (plist-put args key (macroexp-quote val)))) + ((setq args (plist-put args key val)))))) + (unless (or spec class (not (plist-get args :setup-children))) + (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) + (list 'quote + (cond (class) + ((cl-typep (car spec) + '(or vector (and symbol (not null)))) + 'transient-columns) + ('transient-column))) + (and args (cons 'list args)) + (cons 'list + (mapcan (lambda (s) (transient--parse-child prefix s)) spec))))) (defun transient--parse-suffix (prefix spec) (let (level class args) - (cl-symbol-macrolet - ((car (car spec)) - (pop (pop spec))) - (when (integerp car) - (setq level pop)) - (when (or (stringp car) - (vectorp car)) - (setq args (plist-put args :key pop))) - (cond - ((or (stringp car) - (and (eq (car-safe car) 'lambda) - (not (commandp car)))) - (setq args (plist-put args :description pop))) - ((and (symbolp car) - (not (keywordp car)) - (not (commandp car)) - (commandp (cadr spec))) - (setq args (plist-put args :description (macroexp-quote pop))))) - (cond - ((memq car '(:info :info*))) - ((keywordp car) - (error "Need command, `:info' or `:info*', got `%s'" car)) - ((symbolp car) - (setq args (plist-put args :command (macroexp-quote pop)))) - ((and (commandp car) - (not (stringp car))) - (let ((cmd pop) - (sym (intern - (format "transient:%s:%s" - prefix - (let ((desc (plist-get args :description))) - (if (and (stringp desc) - (length< desc 16)) - desc - (plist-get args :key))))))) - (setq args (plist-put - args :command - `(prog1 ',sym - (put ',sym 'interactive-only t) - (put ',sym 'completion-predicate #'transient--suffix-only) - (defalias ',sym - ,(if (eq (car-safe cmd) 'lambda) - cmd - (macroexp-quote cmd)))))))) - ((or (stringp car) - (and car (listp car))) - (let ((arg pop) - (sym nil)) - (cl-typecase arg - (list - (setq args (plist-put args :shortarg (car arg))) - (setq args (plist-put args :argument (cadr arg))) - (setq arg (cadr arg))) - (string - (when-let ((shortarg (transient--derive-shortarg arg))) - (setq args (plist-put args :shortarg shortarg))) - (setq args (plist-put args :argument arg)))) - (setq sym (intern (format "transient:%s:%s" prefix arg))) - (setq args (plist-put - args :command - `(prog1 ',sym - (put ',sym 'interactive-only t) - (put ',sym 'completion-predicate #'transient--suffix-only) - (defalias ',sym #'transient--default-infix-command)))) - (cond ((and car (not (keywordp car))) - (setq class 'transient-option) - (setq args (plist-put args :reader (macroexp-quote pop)))) - ((not (string-suffix-p "=" arg)) - (setq class 'transient-switch)) - (t - (setq class 'transient-option))))) - (t - (error "Needed command or argument, got %S" car))) - (while (keywordp car) - (let ((key pop) - (val pop)) - (cond ((eq key :class) (setq class val)) - ((eq key :level) (setq level val)) - ((eq key :info) - (setq class 'transient-information) - (setq args (plist-put args :description val))) - ((eq key :info*) - (setq class 'transient-information*) - (setq args (plist-put args :description val))) - ((eq (car-safe val) '\,) - (setq args (plist-put args key (cadr val)))) - ((or (symbolp val) - (and (listp val) (not (eq (car val) 'lambda)))) - (setq args (plist-put args key (macroexp-quote val)))) - ((setq args (plist-put args key val))))))) - (unless (plist-get args :key) - (when-let ((shortarg (plist-get args :shortarg))) - (setq args (plist-put args :key shortarg)))) + (cl-flet ((use (prop value) + (setq args (plist-put args prop value)))) + (pcase (car spec) + ((cl-type integer) + (setq level (pop spec)))) + (pcase (car spec) + ((cl-type (or string vector)) + (use :key (pop spec)))) + (pcase (car spec) + ((guard (or (stringp (car spec)) + (and (eq (car-safe (car spec)) 'lambda) + (not (commandp (car spec)))))) + (use :description (pop spec))) + ((and (cl-type (and symbol (not keyword) (not command))) + (guard (commandp (cadr spec)))) + (use :description (macroexp-quote (pop spec))))) + (pcase (car spec) + ((or :info :info*)) + ((and (cl-type keyword) invalid) + (error "Need command, argument, `:info' or `:info*'; got `%s'" invalid)) + ((cl-type symbol) + (use :command (macroexp-quote (pop spec)))) + ;; During macro-expansion this is expected to be a `lambda' + ;; expression (i.e., source code). When this is called from a + ;; `:setup-children' function, it may also be a function object + ;; (a.k.a a function value). However, we never treat a string + ;; as a command, so we have to check for that explicitly. + ((cl-type (and command (not string))) + (let ((cmd (pop spec)) + (sym (intern + (format + "transient:%s:%s:%d" prefix + (replace-regexp-in-string (plist-get args :key) " " "") + (prog1 gensym-counter (cl-incf gensym-counter)))))) + (use :command + `(prog1 ',sym + (put ',sym 'interactive-only t) + (put ',sym 'completion-predicate #'transient--suffix-only) + (defalias ',sym ,cmd))))) + ((cl-type (or string (and list (not null)))) + (let ((arg (pop spec))) + (cl-typecase arg + (list + (use :shortarg (car arg)) + (use :argument (cadr arg)) + (setq arg (cadr arg))) + (string + (when-let ((shortarg (transient--derive-shortarg arg))) + (use :shortarg shortarg)) + (use :argument arg))) + (use :command + (let ((sym (intern (format "transient:%s:%s" prefix arg)))) + `(prog1 ',sym + (put ',sym 'interactive-only t) + (put ',sym 'completion-predicate #'transient--suffix-only) + (defalias ',sym #'transient--default-infix-command)))) + (pcase (car spec) + ((cl-type (and (not null) (not keyword))) + (setq class 'transient-option) + (use :reader (macroexp-quote (pop spec)))) + ((guard (string-suffix-p "=" arg)) + (setq class 'transient-option)) + (_ (setq class 'transient-switch))))) + (invalid + (error "Need command, argument, `:info' or `:info*'; got %s" invalid))) + (while (keywordp (car spec)) + (let* ((key (pop spec)) + (val (if spec (pop spec) (error "No value for `%s'" key)))) + (pcase key + (:class (setq class val)) + (:level (setq level val)) + (:info (setq class 'transient-information) + (use :description val)) + (:info* (setq class 'transient-information*) + (use :description val)) + ((guard (eq (car-safe val) '\,)) + (use key (cadr val))) + ((guard (or (symbolp val) + (and (listp val) (not (eq (car val) 'lambda))))) + (use key (macroexp-quote val))) + (_ (use key val))))) + (when spec + (error "Need keyword, got %S" (car spec))) + (when-let* (((not (plist-get args :key))) + (shortarg (plist-get args :shortarg))) + (use :key shortarg))) (list 'list (or level transient--default-child-level) (macroexp-quote (or class 'transient-suffix)) @@ -1279,7 +1360,7 @@ in regular keymaps or by using `execute-extended-command')." (defalias 'transient--suffix-only #'ignore "Ignore ARGUMENTS, do nothing, and return nil. -Also see `transient-command-completion-not-suffix-only-p'. +See also `transient-command-completion-not-suffix-only-p'. Only use this alias as the value of the `completion-predicate' symbol property.") @@ -1530,6 +1611,7 @@ That buffer is current and empty when this hook runs.") (defvar transient--exitp nil "Whether to exit the transient.") (defvar transient--showp nil "Whether to show the transient popup buffer.") (defvar transient--helpp nil "Whether help-mode is active.") +(defvar transient--docsp nil "Whether docstring-mode is active.") (defvar transient--editp nil "Whether edit-mode is active.") (defvar transient--refreshp nil @@ -1603,13 +1685,13 @@ that is run directly by a command that is invoked while a transient is current, this function is also suitable for use in asynchronous code, such as timers and callbacks (this function's main use-case). -If optional PREFIXES is non-nil, it must be a list of prefix command -symbols, in which case the active transient object is only returned -if it matches one of the PREFIXES." +If optional PREFIXES is non-nil, it must be a prefix command symbol +or a list of symbols, in which case the active transient object is +only returned if it matches one of PREFIXES." (and transient--showp transient--prefix (or (not prefixes) - (memq (oref transient--prefix command) prefixes)) + (memq (oref transient--prefix command) (ensure-list prefixes))) (or (memq 'transient--pre-command pre-command-hook) (and (memq t pre-command-hook) (memq 'transient--pre-command @@ -1696,16 +1778,25 @@ probably use this instead: this-command)))) (or transient--suffixes transient-current-suffixes)))) - (or (and (cdr suffixes) - (cl-find-if - (lambda (obj) - (equal (listify-key-sequence (transient--kbd (oref obj key))) - (listify-key-sequence (this-command-keys)))) - suffixes)) - (car suffixes)))) + (or (if (cdr suffixes) + (cl-find-if + (lambda (obj) + (equal (listify-key-sequence (transient--kbd (oref obj key))) + (listify-key-sequence (this-command-keys)))) + suffixes) + (car suffixes)) + ;; COMMAND is only provided if `this-command' is meaningless, in + ;; which case `this-command-keys' is also meaningless, making it + ;; impossible to disambiguate redundant bindings. + (if command + (car suffixes) + ;; TODO Decide whether it is legimate to use this function + ;; as a predicate, and also whether to return an object for + ;; suffixes common to all prefixes. See #29 and #337. + (error "BUG: Cannot determine suffix object"))))) ((and-let* ((obj (transient--suffix-prototype (or command this-command))) (obj (clone obj))) - (progn ; work around debbugs#31840 + (progn (transient-init-scope obj) (transient-init-value obj) obj))))) @@ -1741,20 +1832,25 @@ to `transient-predicate-map'." "" #'transient-scroll-up "" #'transient-scroll-down) -(defvar-keymap transient-map - :doc "Top-level keymap used by all transients. +(defvar transient-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map transient-base-map) + (keymap-set map "C-u" #'universal-argument) + (keymap-set map "C--" #'negative-argument) + (keymap-set map "C-t" #'transient-show) + (keymap-set map "?" #'transient-help) + (keymap-set map "C-h" #'transient-help) + ;; Also bound to "C-x p" and "C-x n" in transient-common-commands. + (keymap-set map "C-M-p" #'transient-history-prev) + (keymap-set map "C-M-n" #'transient-history-next) + (when (fboundp 'other-frame-prefix) ;Emacs >= 28.1 + (keymap-set map "C-x 5 5" 'other-frame-prefix) + (keymap-set map "C-x 4 4" 'other-window-prefix)) + map) + "Top-level keymap used by all transients. If you add a new command here, then you must also add a binding -to `transient-predicate-map'. Also see `transient-base-map'." - :parent transient-base-map - "C-u" #'universal-argument - "C--" #'negative-argument - "C-t" #'transient-show - "?" #'transient-help - "C-h" #'transient-help - ;; Also bound to "C-x p" and "C-x n" in transient-common-commands. - "C-M-p" #'transient-history-prev - "C-M-n" #'transient-history-next) +to `transient-predicate-map'. See also `transient-base-map'.") (defvar-keymap transient-edit-map :doc "Keymap that is active while a transient in is in \"edit mode\"." @@ -1799,11 +1895,7 @@ to `transient-predicate-map'. Also see `transient-base-map'." (list "C-z" "Suspend transient stack" #'transient-suspend)) (vector "Customize" - (list "C-x t" 'transient-toggle-common :description - (lambda () - (if transient-show-common-commands - "Hide common commands" - "Show common permanently"))) + (list "C-x t" #'transient-toggle-common) (list "C-x l" "Show/hide suffixes" #'transient-set-level) (list "C-x a" #'transient-toggle-level-limit))))) t))) @@ -1861,13 +1953,14 @@ of the corresponding object." "" #'transient--do-stay "" #'transient--do-minus "" #'transient--do-stay + "" #'transient--do-stay + "" #'transient--do-stay "" #'transient--do-quit-all "" #'transient--do-quit-all "" #'transient--do-quit-one "" #'transient--do-stay "" #'transient--do-stay "" #'transient--do-stay - "" #'transient--do-stay "" #'transient--do-call "" #'transient--do-exit "" #'transient--do-call @@ -1886,6 +1979,8 @@ of the corresponding object." "" #'transient--do-move "" #'transient--do-move "" #'transient--do-move + "" #'transient--do-stay + "" #'transient--do-stay ;; If a valid but incomplete prefix sequence is followed by ;; an unbound key, then Emacs calls the `undefined' command ;; but does not set `this-command', `this-original-command' @@ -1969,36 +2064,40 @@ of the corresponding object." (define-key map [handle-switch-frame] #'transient--do-suspend)) (dolist (obj transient--suffixes) (let* ((cmd (oref obj command)) + (id (vector cmd)) (kind (cond ((get cmd 'transient--prefix) 'prefix) ((cl-typep obj 'transient-infix) 'infix) - (t 'suffix)))) - (cond - ((oref obj inapt) - (define-key map (vector cmd) #'transient--do-warn-inapt)) - ((slot-boundp obj 'transient) - (define-key map (vector cmd) - (pcase (list kind - (transient--resolve-pre-command (oref obj transient)) - return) - (`(prefix t ,_) #'transient--do-recurse) - (`(prefix nil ,_) #'transient--do-stack) - (`(infix t ,_) #'transient--do-stay) - (`(suffix t ,_) #'transient--do-call) - ('(suffix nil t) #'transient--do-return) - (`(,_ nil ,_) #'transient--do-exit) - (`(,_ ,do ,_) do)))) - ((not (lookup-key transient-predicate-map (vector cmd))) - (define-key map (vector cmd) - (pcase (list kind default return) - (`(prefix ,(or 'transient--do-stay 'transient--do-call) ,_) - #'transient--do-recurse) - (`(prefix t ,_) #'transient--do-recurse) - (`(prefix ,_ ,_) #'transient--do-stack) - (`(infix ,_ ,_) #'transient--do-stay) - (`(suffix t ,_) #'transient--do-call) - ('(suffix nil t) #'transient--do-return) - (`(suffix nil ,_) #'transient--do-exit) - (`(suffix ,do ,_) do))))))) + (t 'suffix))) + (pre (cond + ((oref obj inapt) #'transient--do-warn-inapt) + ((slot-boundp obj 'transient) + (pcase (list kind + (transient--resolve-pre-command + (oref obj transient)) + return) + (`(prefix t ,_) #'transient--do-recurse) + (`(prefix nil ,_) #'transient--do-stack) + (`(infix t ,_) #'transient--do-stay) + (`(suffix t ,_) #'transient--do-call) + ('(suffix nil t) #'transient--do-return) + (`(,_ nil ,_) #'transient--do-exit) + (`(,_ ,do ,_) do))) + ((not (lookup-key transient-predicate-map id)) + (pcase (list kind default return) + (`(prefix ,(or 'transient--do-stay 'transient--do-call) ,_) + #'transient--do-recurse) + (`(prefix t ,_) #'transient--do-recurse) + (`(prefix ,_ ,_) #'transient--do-stack) + (`(infix ,_ ,_) #'transient--do-stay) + (`(suffix t ,_) #'transient--do-call) + ('(suffix nil t) #'transient--do-return) + (`(suffix nil ,_) #'transient--do-exit) + (`(suffix ,do ,_) do)))))) + (when pre + (if-let ((alt (lookup-key map id))) + (unless (eq alt pre) + (define-key map (vconcat (oref obj key) id) pre)) + (define-key map id pre))))) map)) (defun transient--make-redisplay-map () @@ -2006,8 +2105,9 @@ of the corresponding object." (pcase this-command ('transient-update (setq transient--showp t) - (setq unread-command-events - (listify-key-sequence (this-single-command-raw-keys)))) + (let ((keys (listify-key-sequence (this-single-command-raw-keys)))) + (setq unread-command-events (mapcar (lambda (key) (cons t key)) keys)) + keys)) ('transient-quit-seq (setq unread-command-events (butlast (listify-key-sequence @@ -2068,25 +2168,46 @@ EDIT may be non-nil." (edit ;; 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--original-window (selected-window)) - (setq transient--original-buffer (current-buffer)) - (setq transient--minibuffer-depth (minibuffer-depth)) - (transient--redisplay) - (transient--init-transient) + (transient--env-apply + (lambda () + (transient--init-transient name layout params) + (transient--history-init transient--prefix) + (setq transient--original-window (selected-window)) + (setq transient--original-buffer (current-buffer)) + (setq transient--minibuffer-depth (minibuffer-depth)) + (transient--redisplay)) + (get name 'transient--prefix)) + (transient--setup-transient) (transient--suspend-which-key-mode))) (cl-defgeneric transient-setup-children (group children) "Setup the CHILDREN of GROUP. If the value of the `setup-children' slot is non-nil, then call that function with CHILDREN as the only argument and return the -value. Otherwise return CHILDREN as is." +value. Otherwise return CHILDREN as is.") + +(cl-defmethod transient-setup-children ((group transient-group) children) (if (slot-boundp group 'setup-children) (funcall (oref group setup-children) children) children)) +(defun transient--env-apply (fn &optional prefix) + (if-let ((env (oref (or prefix transient--prefix) environment))) + (funcall env fn) + (funcall fn))) + +(defun transient--init-transient (&optional name layout params) + (unless name + ;; Re-init. + (if (eq transient--refreshp 'updated-value) + ;; Preserve the prefix value this once, because the + ;; invoked suffix indicates that it has updated that. + (setq transient--refreshp (oref transient--prefix refresh-suffixes)) + ;; Otherwise update the prefix value from suffix values. + (oset transient--prefix value (transient-get-value)))) + (transient--init-objects name layout params) + (transient--init-keymaps)) + (defun transient--init-keymaps () (setq transient--predicate-map (transient--make-predicate-map)) (setq transient--transient-map (transient--make-transient-map)) @@ -2097,7 +2218,8 @@ value. Otherwise return CHILDREN as is." (setq transient--prefix (transient--init-prefix name params)) (setq name (oref transient--prefix command))) (setq transient--refreshp (oref transient--prefix refresh-suffixes)) - (setq transient--layout (or layout (transient--init-suffixes name))) + (setq transient--layout (or (and (not transient--refreshp) layout) + (transient--init-suffixes name))) (setq transient--suffixes (transient--flatten-suffixes transient--layout))) (defun transient--init-prefix (name &optional params) @@ -2108,28 +2230,29 @@ value. Otherwise return CHILDREN as is." transient-default-level) params)))) (transient--setup-recursion obj) + (transient-init-scope obj) (transient-init-value obj) obj)) (defun transient--init-suffixes (name) (let ((levels (alist-get name transient-levels))) - (cl-mapcan (lambda (c) (transient--init-child levels c nil)) - (append (get name 'transient--layout) - (and (not transient--editp) - (get 'transient-common-commands - 'transient--layout)))))) + (mapcan (lambda (c) (transient--init-child levels c nil)) + (append (get name 'transient--layout) + (and (not transient--editp) + (get 'transient-common-commands + 'transient--layout)))))) (defun transient--flatten-suffixes (layout) (cl-labels ((s (def) (cond ((stringp def) nil) ((cl-typep def 'transient-information) nil) - ((listp def) (cl-mapcan #'s def)) + ((listp def) (mapcan #'s def)) ((cl-typep def 'transient-group) - (cl-mapcan #'s (oref def suffixes))) + (mapcan #'s (oref def suffixes))) ((cl-typep def 'transient-suffix) (list def))))) - (cl-mapcan #'s layout))) + (mapcan #'s layout))) (defun transient--init-child (levels spec parent) (cl-etypecase spec @@ -2140,16 +2263,14 @@ value. Otherwise return CHILDREN as is." (defun transient--init-group (levels spec parent) (pcase-let ((`(,level ,class ,args ,children) (append spec nil))) (and-let* (((transient--use-level-p level)) - (obj (apply class :level level args)) + (obj (apply class :parent parent :level level args)) ((transient--use-suffix-p obj)) ((prog1 t - (when (or (and parent (oref parent inapt)) - (transient--inapt-suffix-p obj)) + (when (transient--inapt-suffix-p obj) (oset obj inapt t)))) - (suffixes (cl-mapcan - (lambda (c) (transient--init-child levels c obj)) - (transient-setup-children obj children)))) - (progn ; work around debbugs#31840 + (suffixes (mapcan (lambda (c) (transient--init-child levels c obj)) + (transient-setup-children obj children)))) + (progn (oset obj suffixes suffixes) (list obj))))) @@ -2167,12 +2288,13 @@ value. Otherwise return CHILDREN as is." (autoload-do-load fn))) (when (transient--use-level-p level) (let ((obj (if (child-of-class-p class 'transient-information) - (apply class :level level args) + (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)))) (apply #'clone proto :level level args) - (apply class :command cmd :level level args))))) + (apply class :command cmd :parent parent :level level + args))))) (cond ((not cmd)) ((commandp cmd)) ((or (cl-typep obj 'transient-switch) @@ -2186,8 +2308,7 @@ value. Otherwise return CHILDREN as is." (unless (cl-typep obj 'transient-information) (transient--init-suffix-key obj)) (when (transient--use-suffix-p obj) - (if (or (and parent (oref parent inapt)) - (transient--inapt-suffix-p obj)) + (if (transient--inapt-suffix-p obj) (oset obj inapt t) (transient-init-scope obj) (transient-init-value obj)) @@ -2200,9 +2321,9 @@ value. Otherwise return CHILDREN as is." (cl-defmethod transient--init-suffix-key ((obj transient-argument)) (if (transient-switches--eieio-childp obj) (cl-call-next-method obj) - (unless (slot-boundp obj 'shortarg) - (when-let ((shortarg (transient--derive-shortarg (oref obj argument)))) - (oset obj shortarg shortarg))) + (when-let* (((not (slot-boundp obj 'shortarg))) + (shortarg (transient--derive-shortarg (oref obj argument)))) + (oset obj shortarg shortarg)) (unless (slot-boundp obj 'key) (if (slot-boundp obj 'shortarg) (oset obj key (oref obj shortarg)) @@ -2229,18 +2350,20 @@ value. Otherwise return CHILDREN as is." t))) (defun transient--inapt-suffix-p (obj) - (let ((transient--shadowed-buffer (current-buffer)) - (transient--pending-suffix obj)) - (transient--do-suffix-p - (oref obj inapt-if) - (oref obj inapt-if-not) - (oref obj inapt-if-nil) - (oref obj inapt-if-non-nil) - (oref obj inapt-if-mode) - (oref obj inapt-if-not-mode) - (oref obj inapt-if-derived) - (oref obj inapt-if-not-derived) - nil))) + (or (and-let* ((parent (oref obj parent))) + (oref parent inapt)) + (let ((transient--shadowed-buffer (current-buffer)) + (transient--pending-suffix obj)) + (transient--do-suffix-p + (oref obj inapt-if) + (oref obj inapt-if-not) + (oref obj inapt-if-nil) + (oref obj inapt-if-non-nil) + (oref obj inapt-if-mode) + (oref obj inapt-if-not-mode) + (oref obj inapt-if-derived) + (oref obj inapt-if-not-derived) + nil)))) (defun transient--do-suffix-p (if if-not if-nil if-non-nil if-mode if-not-mode if-derived if-not-derived @@ -2282,8 +2405,8 @@ value. Otherwise return CHILDREN as is." ;;; Flow-Control -(defun transient--init-transient () - (transient--debug 'init-transient) +(defun transient--setup-transient () + (transient--debug 'setup-transient) (transient--push-keymap 'transient--transient-map) (transient--push-keymap 'transient--redisplay-map) (add-hook 'pre-command-hook #'transient--pre-command) @@ -2300,14 +2423,7 @@ value. Otherwise return CHILDREN as is." (transient--pop-keymap 'transient--predicate-map) (transient--pop-keymap 'transient--transient-map) (transient--pop-keymap 'transient--redisplay-map) - (if (eq transient--refreshp 'updated-value) - ;; Preserve the prefix value this once, because the - ;; invoked suffix indicates that it has updated that. - (setq transient--refreshp (oref transient--prefix refresh-suffixes)) - ;; Otherwise update the prefix value from suffix values. - (oset transient--prefix value (transient-get-value))) - (transient--init-objects) - (transient--init-keymaps) + (transient--init-transient) (transient--push-keymap 'transient--transient-map) (transient--push-keymap 'transient--redisplay-map) (transient--redisplay)) @@ -2320,8 +2436,8 @@ value. Otherwise return CHILDREN as is." ;; lead to a suffix being remapped to a non-suffix. We have to undo ;; the remapping in that case. However, remapping a non-suffix to ;; another should remain possible. - (when (and (transient--get-pre-command this-original-command 'suffix) - (not (transient--get-pre-command this-command 'suffix))) + (when (and (transient--get-pre-command this-original-command nil 'suffix) + (not (transient--get-pre-command this-command nil 'suffix))) (setq this-command this-original-command)) (cond ((memq this-command '(transient-update transient-quit-seq)) @@ -2337,7 +2453,8 @@ value. Otherwise return CHILDREN as is." ((not (transient--edebug-command-p)) (setq this-command 'transient-undefined)))) ((and transient--editp - (transient-suffix-object) + ;; See TODO in that function. + (ignore-errors (transient-suffix-object)) (not (memq this-command '(transient-quit-one transient-quit-all transient-help)))) @@ -2374,19 +2491,25 @@ value. Otherwise return CHILDREN as is." (defun transient--delete-window () (when (window-live-p transient--window) - (let ((remain-in-minibuffer-window + (let ((win transient--window) + (remain-in-minibuffer-window (and (minibuffer-selected-window) (selected-window)))) - ;; Only delete the window if it has never shown another buffer. - (unless (eq (car (window-parameter transient--window 'quit-restore)) - 'other) - (with-demoted-errors "Error while exiting transient: %S" - (delete-window transient--window))) - (when (buffer-live-p transient--buffer) - (kill-buffer transient--buffer)) - (setq transient--buffer nil) + (cond + ((eq (car (window-parameter win 'quit-restore)) 'other) + ;; Window used to display another buffer. + (set-window-parameter win 'no-other-window + (window-parameter win 'prev--no-other-window)) + (set-window-parameter win 'prev--no-other-window nil)) + ((with-demoted-errors "Error while exiting transient: %S" + (if (window-parent win) + (delete-window win) + (delete-frame (window-frame win) t))))) (when remain-in-minibuffer-window - (select-window remain-in-minibuffer-window))))) + (select-window remain-in-minibuffer-window)))) + (when (buffer-live-p transient--buffer) + (kill-buffer transient--buffer)) + (setq transient--buffer nil)) (defun transient--export () (setq transient-current-prefix transient--prefix) @@ -2397,15 +2520,27 @@ value. Otherwise return CHILDREN as is." (defun transient--suspend-override (&optional nohide) (transient--debug 'suspend-override) (transient--timer-cancel) - (cond ((and (not nohide) transient-hide-during-minibuffer-read) - (transient--delete-window)) - ((and transient--prefix transient--redisplay-key) - (setq transient--redisplay-key nil) - (when transient--showp - (if-let ((win (minibuffer-selected-window))) - (with-selected-window win - (transient--show)) - (transient--show))))) + (let ((show (if nohide 'fixed transient-show-during-minibuffer-read))) + (when (and (integerp show) + (< (frame-height (window-frame transient--window)) + (+ (abs show) + (window-height transient--window)))) + (setq show (natnump show))) + (cond ((not show) + (transient--delete-window)) + ((and transient--prefix transient--redisplay-key) + (setq transient--redisplay-key nil) + (when transient--showp + (if-let ((win (minibuffer-selected-window))) + (with-selected-window win + (transient--show)) + (transient--show))))) + (when (and (window-live-p transient--window) + (and show + (or (not (eq show 'fixed)) + (window-full-height-p transient--window)))) + (set-window-parameter transient--window 'window-preserved-size + (list (window-buffer transient--window) nil nil)))) (transient--pop-keymap 'transient--transient-map) (transient--pop-keymap 'transient--redisplay-map) (remove-hook 'pre-command-hook #'transient--pre-command) @@ -2413,8 +2548,10 @@ value. Otherwise return CHILDREN as is." (defun transient--resume-override (&optional _ignore) (transient--debug 'resume-override) - (when (and transient--showp transient-hide-during-minibuffer-read) - (transient--show)) + (cond ((and transient--showp (not (window-live-p transient--window))) + (transient--show)) + ((window-live-p transient--window) + (transient--fit-window-to-buffer transient--window))) (transient--push-keymap 'transient--transient-map) (transient--push-keymap 'transient--redisplay-map) (add-hook 'pre-command-hook #'transient--pre-command) @@ -2428,7 +2565,7 @@ value. Otherwise return CHILDREN as is." (funcall fn) ; Already unwind protected. (cond ((memq this-command '(top-level abort-recursive-edit)) (setq transient--exitp t) - (transient--post-exit) + (transient--post-exit this-command) (transient--delete-window)) (transient--prefix (transient--resume-override))))) @@ -2460,11 +2597,8 @@ value. Otherwise return CHILDREN as is." (remove-hook 'minibuffer-exit-hook ,exit))) ,@body))) -(static-if (>= emacs-major-version 30) ;transient--wrap-command - (defun transient--wrap-command () - (cl-assert - (>= emacs-major-version 30) nil - "Emacs was downgraded, making it necessary to recompile Transient") +(defun transient--wrap-command () + (static-if (>= emacs-major-version 30) (letrec ((prefix transient--prefix) (suffix this-command) @@ -2492,9 +2626,11 @@ value. Otherwise return CHILDREN as is." (advice-remove suffix advice) (oset prefix unwind-suffix nil))))) (when (symbolp this-command) - (advice-add suffix :around advice '((depth . -99)))))) - - (defun transient--wrap-command () + (advice-add suffix :around advice '((depth . -99)))) + (cl-assert + (>= emacs-major-version 30) nil + "Emacs was downgraded, making it necessary to recompile Transient")) + ;; (< emacs-major-version 30) (let* ((prefix transient--prefix) (suffix this-command) (advice nil) @@ -2560,14 +2696,14 @@ value. Otherwise return CHILDREN as is." ;; argument is in effect. (not prefix-arg))) (transient--refreshp - (transient--refresh-transient)) + (transient--env-apply #'transient--refresh-transient)) ((let ((old transient--redisplay-map) (new (transient--make-redisplay-map))) (unless (equal old new) (transient--pop-keymap 'transient--redisplay-map) (setq transient--redisplay-map new) (transient--push-keymap 'transient--redisplay-map)) - (transient--redisplay))))) + (transient--env-apply #'transient--redisplay))))) (setq transient-current-prefix nil) (setq transient-current-command nil) (setq transient-current-suffixes nil))) @@ -2603,6 +2739,10 @@ value. Otherwise return CHILDREN as is." (setq transient--all-levels-p nil) (setq transient--minibuffer-depth 0) (run-hooks 'transient-exit-hook) + (when command + (setq transient-current-prefix nil) + (setq transient-current-command nil) + (setq transient-current-suffixes nil)) (when resume (transient--stack-pop)))) @@ -2612,7 +2752,8 @@ value. Otherwise return CHILDREN as is." transient--layout transient--editp :transient-suffix (oref transient--prefix transient-suffix) - :scope (oref transient--prefix scope)) + :scope (oref transient--prefix scope) + :value (transient-get-value)) transient--stack)) (defun transient--stack-pop () @@ -2689,12 +2830,13 @@ exit." (setq transient--stack nil) (setq transient--exitp t) (transient--pre-exit) - (transient--post-exit))) + (transient--post-exit this-command))) ;;; Pre-Commands (defun transient--call-pre-command () - (if-let ((fn (transient--get-pre-command this-command))) + (if-let ((fn (transient--get-pre-command this-command + (this-command-keys-vector)))) (let ((action (funcall fn))) (when (eq action transient--exit) (setq transient--exitp (or transient--exitp t))) @@ -2706,10 +2848,14 @@ exit." (setq this-command 'transient-undefined))) transient--stay)) -(defun transient--get-pre-command (&optional cmd enforce-type) +(defun transient--get-pre-command (&optional cmd key enforce-type) (or (and (not (eq enforce-type 'non-suffix)) (symbolp cmd) - (lookup-key transient--predicate-map (vector cmd))) + (or (and key + (let ((def (lookup-key transient--predicate-map + (vconcat key (list cmd))))) + (and (symbolp def) def))) + (lookup-key transient--predicate-map (vector cmd)))) (and (not (eq enforce-type 'suffix)) (transient--resolve-pre-command (oref transient--prefix transient-non-suffix) @@ -2814,6 +2960,9 @@ Do not push the active transient to the transient stack." (defun transient--do-suspend () "Suspend the active transient, saving the transient stack." + ;; Export so that `transient-describe' instances can use + ;; `transient-suffix-object' to get their respective object. + (transient--export) (transient--stack-push) (setq transient--exitp 'suspend) transient--exit) @@ -2989,18 +3138,32 @@ transient is active." (when (lookup-key transient--transient-map (this-single-command-raw-keys)) (setq transient--helpp nil) - (let ((winconf (current-window-configuration))) - (transient-show-help - (if (eq this-original-command 'transient-help) - transient--prefix - (or (transient-suffix-object) - this-original-command))) - (setq-local transient--restore-winconf winconf)) - (fit-window-to-buffer nil (frame-height) (window-height)) - (transient-resume-mode) - (message (substitute-command-keys - "Type \\`q' to resume transient command.")) - t)))) + (transient--display-help #'transient-show-help + (if (eq this-original-command 'transient-help) + transient--prefix + (or (transient-suffix-object) + this-original-command))))))) + +(transient-define-suffix transient-describe () + "From a transient menu, describe something in another buffer. + +This command can be bound multiple times to describe different targets. +Each binding must specify the thing it describes, be setting the value +of its `target' slot, using the keyword argument `:='. + +The `helper' slot specifies the low-level function used to describe the +target, and can be omitted, in which case `transient--describe-function' +is used for a symbol, `transient--show-manual' is used for a string +beginning with a parenthesis, and `transient--show-manpage' is used for +any other string. + +For example: + [(\"e\" \"about emacs\" transient-describe := \"(emacs)\") + (\"g\" \"about git\" transient-describe := \"git\")]" + :class 'transient-describe-target + (interactive) + (with-slots (helper target) (transient-suffix-object) + (transient--display-help helper target))) ;;;; Level @@ -3120,11 +3283,23 @@ transient is active." ;;;; Auxiliary -(defun transient-toggle-common () +(transient-define-suffix transient-toggle-common () "Toggle whether common commands are permanently shown." + :transient t + :description (lambda () + (if transient-show-common-commands + "Hide common commands" + "Show common permanently")) (interactive) (setq transient-show-common-commands (not transient-show-common-commands))) +(transient-define-suffix transient-toggle-docstrings () + "Toggle whether to show docstrings instead of suffix descriptions. +To make this available in all menus, bind it in `transient-map'." + :transient t + (interactive) + (setq transient--docsp (not transient--docsp))) + (defun transient-toggle-debug () "Toggle debugging statements for transient commands." (interactive) @@ -3132,6 +3307,14 @@ transient is active." (message "Debugging transient %s" (if transient--debug "enabled" "disabled"))) +(defun transient-copy-menu-text () + "Copy the contents of the menu buffer to the kill ring. +To make this available in all menus, bind it in `transient-map'" + (interactive) + (transient--show) + (with-current-buffer (get-buffer transient--buffer-name) + (copy-region-as-kill (point-min) (point-max)))) + (transient-define-suffix transient-echo-arguments (arguments) "Show the transient's active ARGUMENTS in the echo area. Intended for use in prefixes used for demonstration purposes, @@ -3152,56 +3335,54 @@ such as when suggesting a new feature or reporting an issue." ;;; Value ;;;; Init -(cl-defgeneric transient-init-scope (obj) - "Set the scope of the suffix object OBJ. - -The scope is actually a property of the transient prefix, not of -individual suffixes. However it is possible to invoke a suffix -command directly instead of from a transient. In that case, if -the suffix expects a scope, then it has to determine that itself -and store it in its `scope' slot. - -This function is called for all suffix commands, but unless a -concrete method is implemented this falls through to the default -implementation, which is a noop.") - -(cl-defmethod transient-init-scope ((_ transient-suffix)) - "Noop." nil) - -(cl-defgeneric transient-init-value (_) - "Set the initial value of the object OBJ. +(cl-defgeneric transient-init-value (obj) + "Set the initial value of the prefix or suffix object OBJ. This function is called for all prefix and suffix commands. -For suffix commands (including infix argument commands) the -default implementation is a noop. Classes derived from the -abstract `transient-infix' class must implement this function. -Non-infix suffix commands usually don't have a value." - nil) +Third-party subclasses of `transient-infix' must implement a primary +method.") (cl-defmethod transient-init-value :around ((obj transient-prefix)) - "If bound, then call OBJ's `init-value' function. -Otherwise call the primary method according to object's class." + "If bound, use the value returned by OBJ' `init-value' function. +If the value of OBJ's `init-value' is non-nil, call that function to +determine the value. Otherwise call the primary method according to +OBJ's class." (if (slot-boundp obj 'init-value) (funcall (oref obj init-value) obj) (cl-call-next-method obj))) (cl-defmethod transient-init-value :around ((obj transient-infix)) - "If bound, then call OBJ's `init-value' function. -Otherwise call the primary method according to object's class." + "If bound, use the value returned by OBJ's `init-value' function. +If the value of OBJ's `init-value' is non-nil, call that function to +determine the value. Otherwise call the primary method according to +OBJ's class." (if (slot-boundp obj 'init-value) (funcall (oref obj init-value) obj) (cl-call-next-method obj))) (cl-defmethod transient-init-value ((obj transient-prefix)) + "Set OBJ's initial value to the set, saved or default value. +Use `transient-default-value' to determine the default value." (if (slot-boundp obj 'value) + ;; Already set because the live object is cloned from + ;; the prototype, were the set (if any) value is stored. (oref obj value) (oset obj value (if-let ((saved (assq (oref obj command) transient-values))) (cdr saved) (transient-default-value obj))))) +(cl-defmethod transient-init-value ((obj transient-suffix)) + "Non-infix suffixes usually don't have a value. +Call `transient-default-value' but because that is a noop for +`transient-suffix', this function is effectively also a noop." + (let ((value (transient-default-value obj))) + (unless (eq value eieio--unbound) + (oset obj value value)))) + (cl-defmethod transient-init-value ((obj transient-argument)) + "Extract OBJ's value from the value of the prefix object." (oset obj value (let ((value (oref transient--prefix value)) (argument (and (slot-boundp obj 'argument) @@ -3222,17 +3403,21 @@ Otherwise call the primary method according to object's class." (cl-some match value))))))) (cl-defmethod transient-init-value ((obj transient-switch)) + "Extract OBJ's value from the value of the prefix object." (oset obj value (car (member (oref obj argument) (oref transient--prefix value))))) ;;;; Default -(cl-defgeneric transient-default-value (_) - "Return the default value." - nil) +(cl-defgeneric transient-default-value (obj) + "Return the default value.") (cl-defmethod transient-default-value ((obj transient-prefix)) + "Return the default value as specified by the `default-value' slot. +If the value of the `default-value' slot is a function, call it to +determine the value. If the slot's value isn't a function, return +that. If the slot is unbound, return nil." (if-let ((default (and (slot-boundp obj 'default-value) (oref obj default-value)))) (if (functionp default) @@ -3240,6 +3425,11 @@ Otherwise call the primary method according to object's class." default) nil)) +(cl-defmethod transient-default-value ((_ transient-suffix)) + "Return `eieio--unbound' to indicate that there is no default value. +Doing so causes `transient-init-value' to skip setting the `value' slot." + eieio--unbound) + ;;;; Read (cl-defgeneric transient-infix-read (obj) @@ -3250,7 +3440,7 @@ is used to actually store the new value in the object. For most infix classes this is done by reading a value from the user using the reader specified by the `reader' slot (using the -`transient-infix' method described below). +method for `transient-infix', described below). For some infix classes the value is changed without reading anything in the minibuffer, i.e., the mere act of invoking the @@ -3460,9 +3650,9 @@ prompt." (and (member x rule) (remove x rule)))) (incomp (nconc - (cl-mapcan (apply-partially filter arg) spec) + (mapcan (apply-partially filter arg) spec) (and (not (equal val arg)) - (cl-mapcan (apply-partially filter val) spec))))) + (mapcan (apply-partially filter val) spec))))) (dolist (obj transient--suffixes) (when-let* (((cl-typep obj 'transient-argument)) (val (transient-infix-value obj)) @@ -3484,7 +3674,7 @@ Intended for use by transient suffix commands." (cl-defgeneric transient-set-value (obj) "Persist the value of the transient prefix OBJ. Only intended for use by `transient-set'. -Also see `transient-prefix-set'.") +See also `transient-prefix-set'.") (cl-defmethod transient-set-value ((obj transient-prefix)) (oset (oref obj prototype) value (transient-get-value)) @@ -3520,14 +3710,39 @@ Also see `transient-prefix-set'.") (defun transient-args (prefix) "Return the value of the transient prefix command PREFIX. -If the current command was invoked from the transient prefix -command PREFIX, then return the active infix arguments. If -the current command was not invoked from PREFIX, then return -the set, saved or default value for PREFIX." - (cl-mapcan #'transient--get-wrapped-value (transient-suffixes prefix))) + +If the current command was invoked from the transient prefix command +PREFIX, then return the active infix arguments. If the current command +was not invoked from PREFIX, then return the set, saved or default value +for PREFIX. + +PREFIX may also be a list of prefixes. If no prefix is active, the +fallback value of the first of these prefixes is used. + +The generic function `transient-prefix-value' is used to determine the +returned value." + (when (listp prefix) + (setq prefix (car (or (memq transient-current-command prefix) prefix)))) + (if-let ((obj (get prefix 'transient--prefix))) + (transient-prefix-value obj) + (error "Not a transient prefix: %s" prefix))) + +(cl-defgeneric transient-prefix-value (obj) + "Return the value of the prefix object OBJ. +This function is used by `transient-args'.") + +(cl-defmethod transient-prefix-value ((obj transient-prefix)) + "Return a list of the values of the suffixes the prefix object OBJ. +Use `transient-infix-value' to collect the values of individual suffix +objects." + (mapcan #'transient--get-wrapped-value + (transient-suffixes (oref obj command)))) (defun transient-suffixes (prefix) - "Return the suffix objects of the transient prefix command PREFIX." + "Return the suffix objects of the transient prefix command PREFIX. + +If PREFIX is not the current prefix, initialize the suffixes so that +they can be returned. Doing so doesn't have any side-effects." (if (eq transient-current-command prefix) transient-current-suffixes (let ((transient--prefix (transient--init-prefix prefix))) @@ -3535,14 +3750,27 @@ the set, saved or default value for PREFIX." (transient--init-suffixes prefix))))) (defun transient-get-value () + "Return the value of the current prefix. + +This is mostly intended for internal use, but may also be of use +in `transient-set-value' and `transient-save-value' methods. Unlike +`transient-args', this does not include the values of suffixes whose +`unsavable' slot is non-nil." (transient--with-emergency-exit :get-value - (cl-mapcan (lambda (obj) - (and (or (not (slot-exists-p obj 'unsavable)) - (not (oref obj unsavable))) - (transient--get-wrapped-value obj))) - (or transient--suffixes transient-current-suffixes)))) + (mapcan (lambda (obj) + (and (or (not (slot-exists-p obj 'unsavable)) + (not (oref obj unsavable))) + (transient--get-wrapped-value obj))) + (or transient--suffixes transient-current-suffixes)))) (defun transient--get-wrapped-value (obj) + "Return a list of the value(s) of suffix object OBJ. + +Internally a suffix only ever has one value, stored in its `value' +slot, but callers of `transient-args', wish to treat the values of +certain suffixes as multiple values. That translation is handled +here. The object's `multi-value' slot specifies whether and how +to interpret the `value' as multiple values." (and-let* ((value (transient-infix-value obj))) (pcase-exhaustive (and (slot-exists-p obj 'multi-value) (oref obj multi-value)) @@ -3553,9 +3781,9 @@ the set, saved or default value for PREFIX." (cl-defgeneric transient-infix-value (obj) "Return the value of the suffix object OBJ. -This function is called by `transient-args' (which see), meaning -this function is how the value of a transient is determined so -that the invoked suffix command can use it. +By default this function is involved when determining the prefix's +overall value, returned by `transient-args' (which see), so that +the invoked suffix command can use that. Currently most values are strings, but that is not set in stone. Nil is not a value, it means \"no value\". @@ -3603,7 +3831,9 @@ not contribute to the value of the transient." For a switch return a boolean. For an option return the value as a string, using the empty string for the empty value, or nil if -the option does not appear in ARGS." +the option does not appear in ARGS. + +Append \"=\ to ARG to indicate that it is an option." (if (string-suffix-p "=" arg) (save-match-data (and-let* ((match (let ((case-fold-search nil) @@ -3616,21 +3846,82 @@ the option does not appear in ARGS." (or (match-string 1 match) ""))) (and (member arg args) t))) -(defun transient-scope () - "Return the value of the `scope' slot of the current prefix." - (oref (transient-prefix-object) scope)) +;;; Scope +;;;; Init + +(cl-defgeneric transient-init-scope (obj) + "Set the scope of the prefix or suffix object OBJ. + +The scope is actually a property of the transient prefix, not of +individual suffixes. However it is possible to invoke a suffix +command directly instead of from a transient. In that case, if +the suffix expects a scope, then it has to determine that itself +and store it in its `scope' slot. + +This function is called for all prefix and suffix commands, but +unless a concrete method is implemented, this falls through to +a default implementation, which is a noop.") + +(cl-defmethod transient-init-scope ((_ transient-prefix)) + "Noop." nil) + +(cl-defmethod transient-init-scope ((_ transient-suffix)) + "Noop." nil) + +;;;; Get + +(defun transient-scope (&optional prefixes) + "Return the scope of the active or current transient prefix command. + +If optional PREFIXES is nil, return the scope of the prefix currently +being setup, making this variant useful, e.g., in `:if*' predicates. +If no prefix is being setup, but the current command was invoked from +some prefix, then return the scope of that. + +When this function is called from the body or `interactive' form of a +suffix command, PREFIXES should be non-nil. + +If PREFIXES is non-nil, it must be a prefix command or a list of such +commands. In this case try the following in order: + +- If the current suffix command was invoked from a prefix, which + appears in PREFIXES, then return the scope of that prefix. + +- If a prefix is being setup and it appears in PREFIXES, then return + its scope. + +- Finally try to return the default scope of the first prefix in + PREFIXES. This only works if that slot is set in the respective + class definition or using its `transient-init-scope' method. + +If no prefix matches, return nil." + (if prefixes + (let ((prefixes (ensure-list prefixes))) + (if-let* ((obj (or (and-let* ((obj transient-current-prefix)) + (and (memq (oref obj command) prefixes) obj)) + (and-let* ((obj transient--prefix)) + (and (memq (oref obj command) prefixes) obj))))) + (oref obj scope) + (and (get (car prefixes) 'transient--prefix) + (oref (transient--init-prefix (car prefixes)) scope)))) + (and-let* ((obj (transient-prefix-object))) + (oref obj scope)))) ;;; History (cl-defgeneric transient--history-key (obj) - "Return OBJ's history key. -If the value of the `history-key' slot is non-nil, then return -that. Otherwise return the value of the `command' slot." + "Return OBJ's history key.") + +(cl-defmethod transient--history-key ((obj transient-prefix)) + "If the value of the `history-key' slot is non-nil, return that. +Otherwise return the value of the `command' slot." (or (oref obj history-key) (oref obj command))) (cl-defgeneric transient--history-push (obj) - "Push the current value of OBJ to its entry in `transient-history'." + "Push the current value of OBJ to its entry in `transient-history'.") + +(cl-defmethod transient--history-push ((obj transient-prefix)) (let ((key (transient--history-key obj))) (setf (alist-get key transient-history) (let ((args (transient-get-value))) @@ -3661,7 +3952,7 @@ have a history of their own.") (mapconcat #'identity (sort - (cl-mapcan + (mapcan (lambda (suffix) (let ((key (kbd (oref suffix key)))) ;; Don't list any common commands. @@ -3685,6 +3976,7 @@ have a history of their own.") (transient--timer-cancel) (setq transient--showp t) (let ((transient--shadowed-buffer (current-buffer)) + (setup (not (get-buffer transient--buffer-name))) (focus nil)) (setq transient--buffer (get-buffer-create transient--buffer-name)) (with-current-buffer transient--buffer @@ -3694,25 +3986,23 @@ have a history of their own.") (button-get (1- (point)) 'command)) (transient--heading-at-point)))) (erase-buffer) - (run-hooks 'transient-setup-buffer-hook) - (when transient-force-fixed-pitch - (transient--force-fixed-pitch)) - (setq window-size-fixed t) - (when (bound-and-true-p tab-line-format) - (setq tab-line-format nil)) - (setq header-line-format nil) - (setq mode-line-format - (if (or (natnump transient-mode-line-format) - (eq transient-mode-line-format 'line)) - nil - transient-mode-line-format)) - (setq mode-line-buffer-identification - (symbol-name (oref transient--prefix command))) - (if transient-enable-popup-navigation - (setq-local cursor-in-non-selected-windows 'box) - (setq cursor-type nil)) - (setq display-line-numbers nil) - (setq show-trailing-whitespace nil) + (when setup + (when transient-force-fixed-pitch + (transient--force-fixed-pitch)) + (when (bound-and-true-p tab-line-format) + (setq tab-line-format nil)) + (setq header-line-format nil) + (setq mode-line-format + (let ((format (transient--mode-line-format))) + (if (or (natnump format) (eq format 'line)) nil format))) + (setq mode-line-buffer-identification + (symbol-name (oref transient--prefix command))) + (if transient-enable-popup-navigation + (setq-local cursor-in-non-selected-windows 'box) + (setq cursor-type nil)) + (setq display-line-numbers nil) + (setq show-trailing-whitespace nil) + (run-hooks 'transient-setup-buffer-hook)) (transient--insert-groups) (when (or transient--helpp transient--editp) (transient--insert-help)) @@ -3721,36 +4011,75 @@ have a history of their own.") (unless (window-live-p transient--window) (setq transient--window (display-buffer transient--buffer - transient-display-buffer-action))) + (transient--display-action))) + (with-selected-window transient--window + (set-window-parameter nil 'prev--no-other-window + (window-parameter nil 'no-other-window)))) (when (window-live-p transient--window) (with-selected-window transient--window + (set-window-parameter nil 'no-other-window t) (goto-char (point-min)) (when transient-enable-popup-navigation (transient--goto-button focus)) (transient--fit-window-to-buffer transient--window))))) +(defun transient--display-action () + (let ((action + (cond ((oref transient--prefix display-action)) + ((memq 'display-buffer-full-frame + (ensure-list (car transient-display-buffer-action))) + (user-error "%s disallowed in %s" + 'display-buffer-full-frame + 'transient-display-buffer-action)) + (transient-display-buffer-action)))) + (when (and (assq 'pop-up-frame-parameters (cdr action)) + (fboundp 'buffer-line-statistics)) ; Emacs >= 28.1 + (setq action (copy-tree action)) + (pcase-let ((`(,height ,width) + (buffer-line-statistics transient--buffer)) + (params (assq 'pop-up-frame-parameters (cdr action)))) + (setf (alist-get 'height params) height) + (setf (alist-get 'width params) + (max width (or transient-minimal-frame-width 0))))) + action)) + (defun transient--fit-window-to-buffer (window) - (let ((window-resize-pixelwise t) + (set-window-parameter window 'window-preserved-size nil) + (let ((fit-window-to-buffer-horizontally t) + (window-resize-pixelwise t) (window-size-fixed nil)) - (if (eq (car (window-parameter window 'quit-restore)) 'other) - ;; Grow but never shrink window that previously displayed - ;; another buffer and is going to display that again. - (fit-window-to-buffer window nil (window-height window)) - (fit-window-to-buffer window nil 1)))) + (cond ((not (window-parent window)) + (fit-frame-to-buffer (window-frame window) nil nil nil + transient-minimal-frame-width)) + ((eq (car (window-parameter window 'quit-restore)) 'other) + ;; Grow but never shrink window that previously displayed + ;; another buffer and is going to display that again. + (fit-window-to-buffer window nil (window-height window))) + ((fit-window-to-buffer window nil 1)))) + (set-window-parameter window 'window-preserved-size + (list (window-buffer window) + (window-body-width window t) + (window-body-height window t)))) + +(defun transient--mode-line-format () + (if (slot-boundp transient--prefix 'mode-line-format) + (oref transient--prefix mode-line-format) + transient-mode-line-format)) (defun transient--separator-line () - (and-let* ((height (cond ((not window-system) nil) - ((natnump transient-mode-line-format) - transient-mode-line-format) - ((eq transient-mode-line-format 'line) 1))) + (and-let* ((format (transient--mode-line-format)) + (height (cond ((not window-system) nil) + ((natnump format) format) + ((eq format 'line) 1))) (face `(,@(and (>= emacs-major-version 27) '(:extend t)) - :background - ,(or (face-foreground (transient--key-face nil 'non-suffix) - nil t) - "#gray60")))) + :background ,(transient--prefix-color)))) (concat (propertize "__" 'face face 'display `(space :height (,height))) (propertize "\n" 'face face 'line-height t)))) +(defun transient--prefix-color () + (or (face-foreground (transient--key-face nil nil 'non-suffix) nil t) + "#gray60")) + (defmacro transient-with-shadowed-buffer (&rest body) "While in the transient buffer, temporarily make the shadowed buffer current." (declare (indent 0) (debug t)) @@ -3758,13 +4087,13 @@ have a history of their own.") ,@body)) (defun transient--insert-groups () - (let ((groups (cl-mapcan (lambda (group) - (let ((hide (oref group hide))) - (and (not (and (functionp hide) - (transient-with-shadowed-buffer - (funcall hide)))) - (list group)))) - transient--layout))) + (let ((groups (mapcan (lambda (group) + (let ((hide (oref group hide))) + (and (not (and (functionp hide) + (transient-with-shadowed-buffer + (funcall hide)))) + (list group)))) + transient--layout))) (while-let ((group (pop groups))) (transient--insert-group group) (when groups @@ -3775,7 +4104,8 @@ have a history of their own.") (cl-defgeneric transient--insert-group (group) "Format GROUP and its elements and insert the result.") -(cl-defmethod transient--insert-group :around ((group transient-group)) +(cl-defmethod transient--insert-group :around ((group transient-group) + &optional _) "Insert GROUP's description, if any." (when-let ((desc (transient-with-shadowed-buffer (transient-format-description group)))) @@ -3803,7 +4133,7 @@ have a history of their own.") (insert ?\n)))))) (cl-defmethod transient--insert-group ((group transient-columns)) - (if transient-force-single-column + (if (or transient-force-single-column transient--docsp) (dolist (group (oref group suffixes)) (transient--insert-group group t)) (let* ((columns @@ -3876,6 +4206,7 @@ as a button." (slot-boundp obj 'command)) (setq str (make-text-button str nil 'type 'transient + 'suffix obj 'command (oref obj command)))) str)) @@ -3900,13 +4231,6 @@ as a button." (cl-defgeneric transient-format-key (obj) "Format OBJ's `key' for display and return the result.") -(cl-defmethod transient-format-key :around ((obj transient-suffix)) - "Add `transient-inapt-suffix' face if suffix is inapt." - (let ((str (cl-call-next-method))) - (if (oref obj inapt) - (transient--add-face str 'transient-inapt-suffix) - str))) - (cl-defmethod transient-format-key ((obj transient-suffix)) "Format OBJ's `key' for display and return the result." (let ((key (if (slot-boundp obj 'key) (oref obj key) "")) @@ -3939,16 +4263,16 @@ as a button." (setq suf (string-replace " " "" suf))) (concat (propertize pre 'face 'transient-unreachable-key) (and (string-prefix-p (concat pre " ") key) " ") - (propertize suf 'face (transient--key-face cmd)) + (propertize suf 'face (transient--key-face cmd key)) (save-excursion (and (string-match " +\\'" key) (propertize (match-string 0 key) 'face 'fixed-pitch)))))) ((transient--lookup-key transient-sticky-map (kbd key)) - (propertize key 'face (transient--key-face cmd))) + (propertize key 'face (transient--key-face cmd key))) (t (propertize key 'face 'transient-unreachable-key)))) - (propertize key 'face (transient--key-face cmd))))) + (propertize key 'face (transient--key-face cmd key))))) (cl-defmethod transient-format-key :around ((obj transient-argument)) "Handle `transient-highlight-mismatched-keys'." @@ -3989,9 +4313,9 @@ and its value is returned to the caller." set " "))))) (cl-defmethod transient-format-description ((obj transient-group)) - "Format the description by calling the next method. If the result -doesn't use the `face' property at all, then apply the face -`transient-heading' to the complete string." + "Format the description by calling the next method. +If the result doesn't use the `face' property at all, then apply the +face `transient-heading' to the complete string." (and-let* ((desc (transient--get-description obj))) (cond ((oref obj inapt) (propertize desc 'face 'transient-inapt-suffix)) @@ -4000,14 +4324,20 @@ doesn't use the `face' property at all, then apply the face ((propertize desc 'face 'transient-heading))))) (cl-defmethod transient-format-description :around ((obj transient-suffix)) - "Format the description by calling the next method. If the result -is nil, then use \"(BUG: no description)\" as the description. -If the OBJ's `key' is currently unreachable, then apply the face -`transient-unreachable' to the complete string." - (let ((desc (or (cl-call-next-method obj) - (and (slot-boundp transient--prefix 'suffix-description) - (funcall (oref transient--prefix suffix-description) - obj))))) + "Format the description by calling the next method. +If the result is nil, then use \"(BUG: no description)\" as the +description. If the OBJ's `key' is currently unreachable, then +apply the face `transient-unreachable' to the complete string." + (let ((desc (if-let ((transient--docsp) + (cmd (oref obj command)) + (doc (ignore-errors (documentation cmd))) + ((not (equal doc (documentation + 'transient--default-infix-command))))) + (substring doc 0 (string-match "\\.?\n" doc)) + (or (cl-call-next-method obj) + (and (slot-boundp transient--prefix 'suffix-description) + (funcall (oref transient--prefix suffix-description) + obj)))))) (if desc (when-let ((face (transient--get-face obj 'face))) (setq desc (transient--add-face desc face t))) @@ -4097,13 +4427,12 @@ If the OBJ's `key' is currently unreachable, then apply the face (add-face-text-property (or beg 0) (or end (length str)) face append str) str)) -(defun transient--key-face (&optional cmd enforce-type) +(defun transient--key-face (cmd key &optional enforce-type) (or (and transient-semantic-coloring (not transient--helpp) (not transient--editp) - (or (and cmd (get cmd 'transient-face)) - (get (transient--get-pre-command cmd enforce-type) - 'transient-face))) + (get (transient--get-pre-command cmd key enforce-type) + 'transient-face)) (if cmd 'transient-key 'transient-key-noop))) (defun transient--key-unreachable-p (obj) @@ -4222,16 +4551,40 @@ manpage, then try to jump to the correct location." "Show the command doc-string." (transient--describe-function cmd)) +(defmacro transient-with-help-window (&rest body) + "Evaluate BODY, send output to *Help* buffer, and display it in a window. +Select the help window, and make the help buffer current and return it." + (declare (indent 0)) + `(let ((buffer nil) + (help-window-select t)) + (with-help-window (help-buffer) + ,@body + (setq buffer (current-buffer))) + (set-buffer buffer))) + +(defun transient--display-help (helper target) + (let ((winconf (current-window-configuration))) + (funcall (cond (helper) + ((symbolp target) #'transient--describe-function) + ((stringp target) + (if (string-prefix-p "(" target) + #'transient--show-manual + #'transient--show-manpage)) + ((error "Unknown how to show help for %S" target))) + target) + (setq-local transient--restore-winconf winconf)) + (fit-window-to-buffer nil (frame-height) (window-height)) + (transient-resume-mode) + (message (substitute-command-keys "Type \\`q' to resume transient command."))) + (defun transient--describe-function (fn) - (describe-function fn) - (unless (derived-mode-p 'help-mode) - (when-let* ((buf (get-buffer "*Help*")) - (win (or (and buf (get-buffer-window buf)) - (cl-find-if (lambda (win) - (with-current-buffer (window-buffer win) - (derived-mode-p 'help-mode))) - (window-list))))) - (select-window win)))) + (let* ((buffer nil) + (help-window-select t) + (temp-buffer-window-setup-hook + (cons (lambda () (setq buffer (current-buffer))) + temp-buffer-window-setup-hook))) + (describe-function fn) + (set-buffer buffer))) (defun transient--show-manual (manual) (info manual)) @@ -4310,7 +4663,7 @@ Type %s to exit help.\n" Type a %s to set level for that suffix command. Type %s to set what levels are available for this prefix command.\n" 'face 'transient-heading) - (propertize "" 'face 'transient-key) + (propertize "" 'face 'transient-key) (propertize "C-x l" 'face 'transient-key)))) (with-slots (level) transient--prefix (insert @@ -4325,6 +4678,37 @@ Suffixes on levels %s and %s are unavailable.\n" (propertize (format ">=%s" (1+ level)) 'face 'transient-disabled-suffix)))))) +(cl-defgeneric transient-show-summary (obj &optional return) + "Show brief summary about the command at point in the echo area. + +If OBJ's `summary' slot is a string, use that. If it is a function, +call that with OBJ as the only argument and use the returned string. +If `summary' is or returns something other than a string or nil, +show no summary. If `summary' is or returns nil, use the first line +of the documentation string, if any. + +If RETURN is non-nil, return the summary instead of showing it. +This is used when a tooltip is needed.") + +(cl-defmethod transient-show-summary ((obj transient-suffix) &optional return) + (with-slots (command summary) obj + (when-let* + ((doc (cond ((functionp summary) + (funcall summary obj)) + (summary) + ((car (split-string (documentation command) "\n"))))) + ((stringp doc)) + ((not (equal doc + (car (split-string (documentation + 'transient--default-infix-command) + "\n")))))) + (when (string-suffix-p "." doc) + (setq doc (substring doc 0 -1))) + (if return + doc + (let ((message-log-max nil)) + (message "%s" doc)))))) + ;;; Popup Navigation (defun transient-scroll-up (&optional arg) @@ -4348,18 +4732,27 @@ around `scroll-down-command' (which see)." See `backward-button' for information about N." (interactive "p") (with-selected-window transient--window - (backward-button n t))) + (backward-button n t) + (when (eq transient-enable-popup-navigation 'verbose) + (transient-show-summary (get-text-property (point) 'suffix))))) (defun transient-forward-button (n) "Move to the next button in the transient popup buffer. See `forward-button' for information about N." (interactive "p") (with-selected-window transient--window - (forward-button n t))) + (forward-button n t) + (when (eq transient-enable-popup-navigation 'verbose) + (transient-show-summary (get-text-property (point) 'suffix))))) (define-button-type 'transient 'face nil - 'keymap transient-button-map) + 'keymap transient-button-map + 'help-echo (lambda (win buf pos) + (with-selected-window win + (with-current-buffer buf + (transient-show-summary + (get-text-property pos 'suffix) t))))) (defun transient--goto-button (command) (cond @@ -4367,11 +4760,14 @@ See `forward-button' for information about N." (when (re-search-forward (concat "^" (regexp-quote command)) nil t) (goto-char (match-beginning 0)))) (command - (while (and (ignore-errors (forward-button 1)) - (not (eq (button-get (button-at (point)) 'command) command)))) - (unless (eq (button-get (button-at (point)) 'command) command) - (goto-char (point-min)) - (forward-button 1))))) + (cl-flet ((found () (eq (button-get (button-at (point)) 'command) command))) + (while (and (ignore-errors (forward-button 1)) + (not (found)))) + (unless (found) + (goto-char (point-min)) + (ignore-errors (forward-button 1)) + (unless (found) + (goto-char (point-min)))))))) (defun transient--heading-at-point () (and (eq (get-text-property (point) 'face) 'transient-heading) @@ -4459,7 +4855,7 @@ search instead." 2) lisp-imenu-generic-expression :test #'equal) -(declare-function which-key-mode "which-key" (&optional arg)) +(declare-function which-key-mode "ext:which-key" (&optional arg)) (defun transient--suspend-which-key-mode () (when (bound-and-true-p which-key-mode) diff --git a/elpa/transient-20240729.1524/transient.info b/elpa/transient-20241219.1713/transient.info similarity index 83% rename from elpa/transient-20240729.1524/transient.info rename to elpa/transient-20241219.1713/transient.info index bdfce816..da245139 100644 --- a/elpa/transient-20240729.1524/transient.info +++ b/elpa/transient-20241219.1713/transient.info @@ -32,7 +32,7 @@ used to implement similar menus in other packages. resource to get over that hurdle is Psionic K’s interactive tutorial, available at . -This manual is for Transient version 0.7.3. +This manual is for Transient version 0.8.1. Copyright (C) 2018–2024 Free Software Foundation, Inc. @@ -81,6 +81,8 @@ Defining New Commands * Binding Suffix and Infix Commands:: * Defining Suffix and Infix Commands:: * Using Infix Arguments:: +* Current Suffix Command:: +* Current Prefix Command:: * Transient State:: Binding Suffix and Infix Commands @@ -95,6 +97,7 @@ Classes and Methods * Group Methods:: * Prefix Classes:: * Suffix Classes:: +* Prefix Methods:: * Suffix Methods:: * Prefix Slots:: * Suffix Slots:: @@ -208,13 +211,14 @@ A transient prefix command is invoked like any other command by pressing the key that is bound to that command. The main difference to other commands is that a transient prefix command activates a transient keymap, which temporarily binds the transient’s infix and suffix -commands. Bindings from other keymaps may, or may not, be disabled -while the transient state is in effect. +commands, and that those bindings are displayed in a transient menu, +displayed in a popup buffer. Bindings from other keymaps may, or may +not, be disabled while the transient state is in effect. There are two kinds of commands that are available after invoking a transient prefix command; infix and suffix commands. Infix commands set -some value (which is then shown in a popup buffer), without leaving the -transient. Suffix commands, on the other hand, usually quit the +some value (which is then shown in the popup buffer), without leaving +the transient. Suffix commands, on the other hand, usually quit the transient and they may use the values set by the infix commands, i.e., the infix *arguments*. @@ -314,9 +318,6 @@ common commands to always be shown for all transients. The other common commands are described in either the previous or in one of the following sections. - Some of Transient’s key bindings differ from the respective bindings -of Magit-Popup; see *note FAQ:: for more information. -  File: transient.info, Node: Saving Values, Next: Using History, Prev: Common Suffix Commands, Up: Usage @@ -342,11 +343,12 @@ but it is easily accessible (see *note Using History::). session. ‘C-x C-s’ (‘transient-save’) - Save the value of the active transient persistently across Emacs - sessions. + This command saves the value of the active transient persistently + across Emacs sessions. ‘C-x C-k’ (‘transient-reset’) - Clear the set and saved values of the active transient. + This command clears the set and saved values of the active + transient. -- User Option: transient-values-file This option names the file that is used to persist the values of @@ -365,7 +367,7 @@ File: transient.info, Node: Using History, Next: Getting Help for Suffix Comma ================= Every time the user invokes a suffix command the transient’s current -value is saved to its history. These values can be cycled through the +value is saved to its history. These values can be cycled through, the same way one can cycle through the history of commands that read user-input in the minibuffer. @@ -379,11 +381,11 @@ user-input in the minibuffer. This command switches to the next value used for the active transient. - In addition to the transient-wide history, Transient of course -supports per-infix history. When an infix reads user-input using the -minibuffer, the user can use the regular minibuffer history commands to -cycle through previously used values. Usually the same keys as those -mentioned above are bound to those commands. + In addition to the transient-wide history, infixes can have their own +history. When an infix reads user-input using the minibuffer, the user +can use the regular minibuffer history commands to cycle through +previously used values. Usually the same keys as those mentioned above +are bound to those commands. Authors of transients should arrange for different infix commands that read the same kind of value to also use the same history key (see @@ -391,6 +393,10 @@ that read the same kind of value to also use the same history key (see Both kinds of history are saved to a file when Emacs is exited. + -- User Option: transient-save-history + This option controls whether the history of transient commands is + saved when exiting Emacs. + -- User Option: transient-history-file This option names the file that is used to persist the history of transients and their infixes between Emacs sessions. @@ -521,6 +527,21 @@ window, and the key bindings are the same as for ‘scroll-up-command’ and If ARG is ‘nil’, then it scrolls near full screen. This is a wrapper around ‘scroll-down-command’ (which see). + The following commands are not available by default. If you would +like to use them for all menus, bind them in ‘transient-map’. + + -- Command: transient-copy-menu-text + This command copies the contents of the menu buffer to the kill + ring. + + -- Command: transient-toggle-docstrings + This command toggle between showing suffix descriptions in the menu + (as usual) or showing the first lines of the respective docstrings + in their place. For commands that do not have a docstring, always + display the suffix description. Because there likely isn’t enough + room to display multiple docstrings side-by-side, a single column + is used when displaying docstrings. +  File: transient.info, Node: Configuration, Prev: Other Commands, Up: Usage @@ -557,21 +578,82 @@ Also see *note Common Suffix Commands::. zero, the popup is shown after that many seconds of inactivity (using the absolute value). + -- User Option: transient-show-common-commands + This option controls whether shared suffix commands are shown + alongside the transient-specific infix and suffix commands. By + default, the shared commands are not shown to avoid overwhelming + the user with too many options. + + While a transient is active, pressing ‘C-x’ always shows the common + commands. The value of this option can be changed for the current + Emacs session by typing ‘C-x t’ while a transient is active. + + -- User Option: transient-show-during-minibuffer-read + This option controls whether the transient menu continues to be + displayed while the minibuffer is used to read user input. + + This is only relevant to commands that do not close the menu, such + as commands that set infix arguments. If a command exits the menu, + and uses the minibuffer, then the menu is always closed before the + minibuffer is entered, irrespective of the value of this option. + + When ‘nil’ (the default), hide the menu while the minibuffer is in + use. When ‘t’, keep showing the menu, but allow for the menu + window to be resized, to ensure that completion candidates can be + displayed. + + When ‘fixed’, keep showing the menu and prevent it from being + resized, which may make it impossible to display the completion + candidates. If that ever happens for you, consider using ‘t’ or an + integer, as described below. + + If the value is ‘fixed’ and the menu window uses the full height of + its frame, then the former is ignored and resizing is allowed + anyway. This is necessary because individual menus may use unusual + display actions different from what + ‘transient-display-buffer-action’ specifies (likely to display that + menu in a side-window). + + When using a third-party mode, which automatically resizes windows + (e.g., by calling ‘balance-windows’ on ‘post-command-hook’), then + ‘fixed’ (or ‘nil’) is likely a better choice than ‘t’. + + The value can also be an integer, in which case the behavior + depends on whether at least that many lines are left to display + windows other than the menu window. If that is the case, display + the menu and preserve the size of that window. Otherwise, allow + resizing the menu window if the number is positive, or hide the + menu if it is negative. + + -- User Option: transient-read-with-initial-input + This option controls whether the last history element is used as + the initial minibuffer input when reading the value of an infix + argument from the user. If ‘nil’, there is no initial input and + the first element has to be accessed the same way as the older + elements. + -- User Option: transient-enable-popup-navigation This option controls whether navigation commands are enabled in the - transient popup buffer. + transient popup buffer. If the value is ‘verbose’ (the default), + brief documentation about the command under point is additionally + show in the echo area. While a transient is active the transient popup buffer is not the current buffer, making it necessary to use dedicated commands to - act on that buffer itself. This is disabled by default. If this - option is non-‘nil’, then the following features are available: + act on that buffer itself. If this option is non-‘nil’, then the + following features are available: • ‘’ moves the cursor to the previous suffix. • ‘’ moves the cursor to the next suffix. - • ‘’ invokes the suffix the cursor is on. + • ‘M-’ invokes the suffix the cursor is on. • ‘mouse-1’ invokes the clicked on suffix. • ‘C-s’ and ‘C-r’ start isearch in the popup buffer. + By default ‘M-’ is bound to ‘transient-push-button’, instead + of ‘’, because if a transient allows the invocation of + non-suffixes, then it is likely, that you would want ‘’ to do + what it would do if no transient were active." + -- User Option: transient-display-buffer-action This option specifies the action used to display the transient popup buffer. The transient popup buffer is displayed in a window @@ -586,15 +668,13 @@ Also see *note Common Suffix Commands::. The default is: (display-buffer-in-side-window - (side . bottom) - (inhibit-same-window . t) - (window-parameters (no-other-window . t))) + (side . bottom) + (dedicated . t) + (inhibit-same-window . t)) - This displays the window at the bottom of the selected frame. - Another useful FUNCTION is ‘display-buffer-below-selected’, which - is what ‘magit-popup’ used by default. For more alternatives see - *note (elisp)Buffer Display Action Functions::, and *note - (elisp)Buffer Display Action Alists::. + This displays the window at the bottom of the selected frame. For + alternatives see *note (elisp)Buffer Display Action Functions::, + and *note (elisp)Buffer Display Action Alists::. Note that the buffer that was current before the transient buffer is shown should remain the current buffer. Many suffix commands @@ -611,6 +691,9 @@ Also see *note Common Suffix Commands::. If you change the value of this option, then you might also want to change the value of ‘transient-mode-line-format’. + This user option may be overridden if ‘:display-action’ is passed + when creating a new prefix with ‘transient-define-prefix’. + Accessibility Options --------------------- @@ -632,18 +715,21 @@ Auxiliary Options good value. If ‘line’ (the default) or a natural number, then the buffer has no - mode-line, but a line is drawn is drawn in its place. If a number - is used, that specifies the thickness of the line. On termcap - frames we cannot draw lines, so there ‘line’ and numbers are - synonyms for ‘nil’. + mode-line, but a line is drawn in its place. If a number is used, + that specifies the thickness of the line. On termcap frames we + cannot draw lines, so there ‘line’ and numbers are synonyms for + ‘nil’. The color of the line is used to indicate if non-suffixes are allowed and whether they exit the transient. The foreground color - of ‘transient-key-noop’ (if non-suffix are disallowed), + of ‘transient-key-noop’ (if non-suffixes are disallowed), ‘transient-key-stay’ (if allowed and transient stays active), or ‘transient-key-exit’ (if allowed and they exit the transient) is used to draw the line. + This user option may be overridden if ‘:mode-line-format’ is passed + when creating a new prefix with ‘transient-define-prefix’. + Otherwise this can be any mode-line format. See *note (elisp)Mode Line Format::, for details. @@ -695,17 +781,6 @@ Auxiliary Options (replace-match "(" t t key 1) key)))) - -- User Option: transient-read-with-initial-input - This option controls whether the last history element is used as - the initial minibuffer input when reading the value of an infix - argument from the user. If ‘nil’, there is no initial input and - the first element has to be accessed the same way as the older - elements. - - -- User Option: transient-hide-during-minibuffer-read - This option controls whether the transient buffer is hidden while - user input is being read in the minibuffer. - -- User Option: transient-align-variable-pitch This option controls whether columns are aligned pixel-wise in the popup buffer. @@ -754,6 +829,16 @@ These options are mainly intended for developers. suffixes that won’t be available to users without them making the same customization. +Hook Variables +-------------- + + -- Variable: transient-exit-hook + This hook is run after a transient is exited. + + -- Variable: transient-setup-buffer-hook + This hook is run when the transient buffer is being setup. That + buffer is current and empty when this hook is runs. +  File: transient.info, Node: Modifying Existing Transients, Next: Defining New Commands, Prev: Usage, Up: Top @@ -857,6 +942,8 @@ File: transient.info, Node: Defining New Commands, Next: Classes and Methods, * Binding Suffix and Infix Commands:: * Defining Suffix and Infix Commands:: * Using Infix Arguments:: +* Current Suffix Command:: +* Current Prefix Command:: * Transient State::  @@ -900,7 +987,7 @@ arguments have been set using a command such as ‘universal-argument’. Transient can be used to implement simple “command dispatchers”. The main benefit then is that the user can see all the available commands in -a popup buffer, which can be thought of as a “menus”. That is useful by +a popup buffer, which can be thought of as a “menu”. That is useful by itself because it frees the user from having to remember all the keys that are valid after a certain prefix key or command. Magit’s ‘magit-dispatch’ (on ‘C-x M-g’) command is an example of using Transient @@ -1078,9 +1165,9 @@ constructor of that class. • Likewise ‘:level’ is equivalent to LEVEL. - • Other important keywords include the ‘:if...’ keywords. These - keywords control whether the group is available in a certain - situation. + • Other important keywords include the ‘:if...’ and ‘:inapt-if...’ + keywords. These keywords control whether the group is available in + a certain situation. For example, one group of the ‘magit-rebase’ transient uses ‘:if magit-rebase-in-progress-p’, which contains the suffixes that are @@ -1335,7 +1422,7 @@ Note that an infix is a special kind of suffix. Depending on context ‘transient-define-infix’ instead.  -File: transient.info, Node: Using Infix Arguments, Next: Transient State, Prev: Defining Suffix and Infix Commands, Up: Defining New Commands +File: transient.info, Node: Using Infix Arguments, Next: Current Suffix Command, Prev: Defining Suffix and Infix Commands, Up: Defining New Commands 4.5 Using Infix Arguments ========================= @@ -1350,11 +1437,11 @@ calling the command. the arguments are reset to ‘nil’ (which causes the function to return ‘nil’ too). - Like for Emacs’ prefix arguments, it is advisable, but not mandatory, -to access the infix arguments inside the command’s ‘interactive’ form. -The preferred way of doing that is to call the ‘transient-args’ -function, which for infix arguments serves about the same purpose as -‘prefix-arg’ serves for prefix arguments. + Like for Emacs’s prefix arguments, it is advisable, but not +mandatory, to access the infix arguments inside the command’s +‘interactive’ form. The preferred way of doing that is to call the +‘transient-args’ function, which for infix arguments serves about the +same purpose as ‘prefix-arg’ serves for prefix arguments. -- Function: transient-args prefix This function returns the value of the transient prefix command @@ -1365,8 +1452,16 @@ function, which for infix arguments serves about the same purpose as current command was not invoked from PREFIX, then it returns the set, saved or default value for PREFIX. + -- Function: transient-get-value + This function returns the value of the current prefix. + + This is mostly intended for internal use, but may also be of use in + ‘transient-set-value’ and ‘transient-save-value’ methods. Unlike + ‘transient-args’, this does not include the values of suffixes + whose ‘unsavable’ slot is non-‘nil’. + -- Function: transient-arg-value arg args - This function return the value of ARG as it appears in ARGS. + This function returns the value of ARG as it appears in ARGS. For a switch a boolean is returned. For an option the value is returned as a string, using the empty string for the empty value, @@ -1378,6 +1473,51 @@ function, which for infix arguments serves about the same purpose as used if you need the objects (as opposed to just their values) and if the current command is not being invoked from PREFIX. + +File: transient.info, Node: Current Suffix Command, Next: Current Prefix Command, Prev: Using Infix Arguments, Up: Defining New Commands + +4.6 Current Suffix Command +========================== + + -- Function: transient-suffix-object command + This function returns the object associated with the current suffix + command. + + Each suffix commands is associated with an object, which holds + additional information about the suffix, such as its value (in the + case of an infix command, which is a kind of suffix command). + + This function is intended to be called by infix commands, which are + usually aliases of ‘transient--default-infix-command’, which is + defined like this: + + (defun transient--default-infix-command () + (interactive) + (let ((obj (transient-suffix-object))) + (transient-infix-set obj (transient-infix-read obj))) + (transient--show)) + + (User input is read outside of ‘interactive’ to prevent the command + from being added to ‘command-history’.) + + Such commands need to be able to access their associated object to + guide how ‘transient-infix-read’ reads the new value and to store + the read value. Other suffix commands (including non-infix + commands) may also need the object to guide their behavior. + + This function attempts to return the object associated with the + current suffix command even if the suffix command was not invoked + from a transient. (For some suffix command that is a valid thing + to do, for others it is not.) In that case ‘nil’ may be returned, + if the command was not defined using one of the macros intended to + define such commands. + + The optional argument COMMAND is intended for internal use. If you + are contemplating using it in your own code, then you should + probably use this instead: + + (get COMMAND 'transient--suffix) + -- Variable: transient-current-suffixes The suffixes of the transient from which this suffix command was invoked. This is a list of objects. Usually it is sufficient to @@ -1386,20 +1526,50 @@ function, which for infix arguments serves about the same purpose as variable instead, i.e., if you need access to information beside the value. - -- Variable: transient-current-command - The transient from which this suffix command was invoked. The - returned value is a symbol, the transient prefix command. + +File: transient.info, Node: Current Prefix Command, Next: Transient State, Prev: Current Suffix Command, Up: Defining New Commands + +4.7 Current Prefix Command +========================== + + -- Function: transient-prefix-object + This function returns the current prefix as an object. + + While a transient is being setup or refreshed (which involves + preparing its suffixes) the variable ‘transient--prefix’ can be + used to access the prefix object. Thus this is what has to be used + in suffix methods such as ‘transient-format-description’, and in + object-specific functions that are stored in suffix slots such as + ‘description’. + + When a suffix command is invoked (i.e., in its ‘interactive’ form + and function body) then the variable ‘transient-current-prefix’ has + to be used instead. + + Two distinct variables are needed, because any prefix may itself be + used as a suffix of another prefix, and such sub-prefixes have to + be able to tell themselves apart from the prefix they were invoked + from. + + Regular suffix commands, which are not prefixes, do not have to + concern themselves with this distinction, so they can use this + function instead. In the context of a plain suffix, it always + returns the value of the appropriate variable. -- Variable: transient-current-prefix The transient from which this suffix command was invoked. The - returned value is a ‘transient-prefix’ object, which holds - information associated with the transient prefix command. + value is a ‘transient-prefix’ object, which holds information + associated with the transient prefix command. - -- Variable: transient-active-prefix - This function returns the active transient object. Return ‘nil’ if - there is no active transient, if the transient buffer isn’t shown, - and while the active transient is suspended (e.g., while the - minibuffer is in use). + -- Variable: transient-current-command + The transient from which this suffix command was invoked. The + value is a symbol, the transient prefix command. + + -- Function: transient-active-prefix &optional prefixes + This function returns the active transient object. It returns + ‘nil’ if there is no active transient, if the transient buffer + isn’t shown, and while the active transient is suspended (e.g., + while the minibuffer is in use). Unlike ‘transient-current-prefix’, which is only ever non-‘nil’ in code that is run directly by a command that is invoked while a @@ -1407,14 +1577,14 @@ function, which for infix arguments serves about the same purpose as asynchronous code, such as timers and callbacks (this function’s main use-case). - If optional PREFIXES is non-‘nil’, it must be a list of prefix - command symbols, in which case the active transient object is only - returned if it matches one of the PREFIXES." + If optional PREFIXES is non-‘nil’, it must be a prefix command + symbol or a list of symbols, in which case the active transient + object is only returned if it matches one of the PREFIXES.  -File: transient.info, Node: Transient State, Prev: Using Infix Arguments, Up: Defining New Commands +File: transient.info, Node: Transient State, Prev: Current Prefix Command, Up: Defining New Commands -4.6 Transient State +4.8 Transient State =================== Invoking a transient prefix command “activates” the respective @@ -1633,13 +1803,11 @@ File: transient.info, Node: Classes and Methods, Next: FAQ, Prev: Defining Ne ********************* Transient uses classes and generic functions to make it possible to -define new types of suffix commands that are similar to existing types, -but behave differently in some aspects. It does the same for groups and -prefix commands, though at least for prefix commands that *currently* -appears to be less important. +define new types of suffix and prefix commands, which are similar to +existing types, but behave differently in some respects. Every prefix, infix and suffix command is associated with an object, -which holds information that controls certain aspects of its behavior. +which holds information, which controls certain aspects of its behavior. This happens in two ways. • Associating a command with a certain class gives the command a @@ -1648,7 +1816,7 @@ This happens in two ways. type of command it acts on. That in turn makes it possible for third-parties to add new types - without having to convince the maintainer of Transient that that + without having to convince the maintainer of Transient, that that new type is important enough to justify adding a special case to a dozen or so functions. @@ -1675,6 +1843,7 @@ This happens in two ways. * Group Methods:: * Prefix Classes:: * Suffix Classes:: +* Prefix Methods:: * Suffix Methods:: * Prefix Slots:: * Suffix Slots:: @@ -1755,7 +1924,8 @@ File: transient.info, Node: Group Methods, Next: Prefix Classes, Prev: Group Functions that are called by this function may need to operate in the buffer from which the transient was called. To do so they can - temporarily make the ‘transient--source-buffer’ the current buffer. + temporarily make the ‘transient--shadowed-buffer’ the current + buffer.  File: transient.info, Node: Prefix Classes, Next: Suffix Classes, Prev: Group Methods, Up: Classes and Methods @@ -1763,18 +1933,11 @@ File: transient.info, Node: Prefix Classes, Next: Suffix Classes, Prev: Group 5.3 Prefix Classes ================== -Currently the ‘transient-prefix’ class is being used for all prefix -commands and there is only a single generic function that can be -specialized based on the class of a prefix command. - - -- Function: transient--history-init obj - This generic function is called while setting up the transient and - is responsible for initializing the ‘history’ slot. This is the - transient-wide history; many individual infixes also have a history - of their own. - - The default (and currently only) method extracts the value from the - global variable ‘transient-history’. +Transient itself provides a single class for prefix commands, +‘transient-prefix’, but package authors may wish to define specialized +classes. Doing so makes it possible to change the behavior of the set +of prefix commands that use that class, by implementing specialized +methods for certain generic functions (see *note Prefix Methods::). A transient prefix command’s object is stored in the ‘transient--prefix’ property of the command symbol. While a transient @@ -1783,7 +1946,7 @@ is active, a clone of that object is stored in the variable to the active transient’s object should not affect later invocations.  -File: transient.info, Node: Suffix Classes, Next: Suffix Methods, Prev: Prefix Classes, Up: Classes and Methods +File: transient.info, Node: Suffix Classes, Next: Prefix Methods, Prev: Prefix Classes, Up: Classes and Methods 5.4 Suffix Classes ================== @@ -1826,20 +1989,39 @@ File: transient.info, Node: Suffix Classes, Next: Suffix Methods, Prev: Prefi • Classes used for infix commands that represent variables should derived from the abstract ‘transient-variable’ class. - • The ‘transient-information’ class is special in that suffixes that - use this class are not associated with a command and thus also not - with any key binding. Such suffixes are only used to display - arbitrary information, and that anywhere a suffix can appear. - Display-only suffix specifications take this form: + • The ‘transient-information’ and ‘transient-information*’ classes + are special in that suffixes that use these class are not + associated with a command and thus also not with any key binding. + Such suffixes are only used to display arbitrary information, and + that anywhere a suffix can appear. Display-only suffix + specifications take these form: ([LEVEL] :info DESCRIPTION [KEYWORD VALUE]...) + ([LEVEL] :info* DESCRIPTION [KEYWORD VALUE]...) - The ‘:info’ keyword argument replaces the ‘:description’ keyword - used for other suffix classes. Other keyword arguments that you - might want to set, include ‘:face’, predicate keywords (such as - ‘:if’), and ‘:format’. By default the value of ‘:format’ includes - ‘%k’, which for this class is replaced with the empty string or - spaces, if keys are being padded in the containing group. + The ‘:info’ and ‘:info*’ keyword arguments replaces the + ‘:description’ keyword used for other suffix classes. Other + keyword arguments that you might want to set, include ‘:face’, + predicate keywords (such as ‘:if’ and ‘:inapt-if’), and ‘:format’. + By default the value of ‘:format’ includes ‘%k’, which for this + class is replaced with the empty string or spaces, if keys are + being padded in the containing group. + + The only difference between these two classes is that ‘:info*’ + aligns its description with the descriptions of suffix commands, + while for ‘:info’ the description bleeds into the area where + suffixes display their key bindings. + + • The ‘transient-lisp-variable’ class can be used to show and change + the value of lisp variables. This class is not fully featured yet + and it is somewhat likely that future improvements won’t be fully + backward compatible. + + • The ‘transient-describe-target’ class is used by the command + ‘transient-describe’. + + • The ‘transient-value-preset’ class is used to implement the command + ‘transient-preset’, which activates a value preset. Magit defines additional classes, which can serve as examples for the fancy things you can do without modifying Transient. Some of these @@ -1847,9 +2029,64 @@ classes will likely get generalized and added to Transient. For now they are very much subject to change and not documented.  -File: transient.info, Node: Suffix Methods, Next: Prefix Slots, Prev: Suffix Classes, Up: Classes and Methods +File: transient.info, Node: Prefix Methods, Next: Suffix Methods, Prev: Suffix Classes, Up: Classes and Methods -5.5 Suffix Methods +5.5 Prefix Methods +================== + +To get information about the methods implementing these generic +functions use ‘describe-function’. + + -- Function: transient-init-value obj + This generic function sets the initial value of the object OBJ. + Methods exist for both prefix and suffix objects. + + The default method for prefix objects sets the value of OBJ’s + ‘value’ slot to the set, saved or default value. The value that is + set for the current session is preferred over the saved value, + which is preferred over the default value. + + The default value is determined using the generic function + ‘transient-default-value’. If you need to change how the value for + a prefix class is determined, its usually sufficient to implement a + method for that function. + + -- Function: transient-default-value obj + This generic function returns the default value of the object OBJ. + Methods exist for both prefix and suffix objects. + + The default method for prefix objects returns the value of the + ‘default-value’ slot if that is bound and not a function. If it is + a function, that is called to get the value. If the slot is + unbound, ‘nil’ is returned. + + -- Function: transient-prefix-value obj + This generic function returns the value of the prefix object OBJ. + The respective generic function for infix and suffix objects is + named ‘transient-infix-value’. + + -- Function: transient-init-scope obj + This generic function sets the scope of the object OBJ. Methods + exist for both prefix and suffix objects. + + This function is called for all prefix and suffix commands, but + unless a concrete method is implemented this falls through to the + default implementation, which is a noop. + + ‘transient-set-value’, ‘transient-save-value’, +‘transient-reset-value’, ‘transient--history-key’, +‘transient--history-push’ and ‘transient--history-init’ are other +generic functions dealing with the value of prefix objects. See their +doc-strings for more information. + + ‘transient-show-help’ is another generic function implemented for +prefix commands. The default method effectively describes the command +using ‘describe-function’. + + +File: transient.info, Node: Suffix Methods, Next: Prefix Slots, Prev: Prefix Methods, Up: Classes and Methods + +5.6 Suffix Methods ================== To get information about the methods implementing these generic @@ -1863,18 +2100,30 @@ functions use ‘describe-function’.  File: transient.info, Node: Suffix Value Methods, Next: Suffix Format Methods, Up: Suffix Methods -5.5.1 Suffix Value Methods +5.6.1 Suffix Value Methods -------------------------- -- Function: transient-init-value obj This generic function sets the initial value of the object OBJ. + Methods exist for both prefix and suffix objects. + + For ‘transient-argument’ objects this function handles setting the + value by itself. + + For other ‘transient-suffix’ objects (including ‘transient-infix’ + objects), this calls ‘transient-default-value’ and uses the value + returned by that, unless it is the special value ‘eieio--unbound’, + which indicates that there is no default value. Since that is what + the default method for ‘transient-suffix’ objects does, both of + these functions effectively are noops for these classes. - This function is called for all suffix commands, but unless a - concrete method is implemented this falls through to the default - implementation, which is a noop. In other words this usually only - does something for infix commands, but note that this is not - implemented for the abstract class ‘transient-infix’, so if your - class derives from that directly, then you must implement a method. + If you implement a class that derives from ‘transient-infix’ + directly, then you must implement a dedicated method for this + function and/or ‘transient-default-value’. + + -- Function: transient-default-value obj + This generic function returns the default value of the object OBJ. + Methods exist for both prefix and suffix objects. -- Function: transient-infix-read obj This generic function determines the new value of the infix object @@ -1913,7 +2162,8 @@ File: transient.info, Node: Suffix Value Methods, Next: Suffix Format Methods, ‘transient-suffix’. -- Function: transient-init-scope obj - This generic function sets the scope of the suffix object OBJ. + This generic function sets the scope of the object OBJ. Methods + exist for both prefix and suffix objects. The scope is actually a property of the transient prefix, not of individual suffixes. However it is possible to invoke a suffix @@ -1921,14 +2171,14 @@ File: transient.info, Node: Suffix Value Methods, Next: Suffix Format Methods, suffix expects a scope, then it has to determine that itself and store it in its ‘scope’ slot. - This function is called for all suffix commands, but unless a - concrete method is implemented this falls through to the default - implementation, which is a noop. + This function is called for all prefix and suffix commands, but + unless a concrete method is implemented, this falls through to the + default implementation, which is a noop.  File: transient.info, Node: Suffix Format Methods, Prev: Suffix Value Methods, Up: Suffix Methods -5.5.2 Suffix Format Methods +5.6.2 Suffix Format Methods --------------------------- -- Function: transient-format obj @@ -1955,6 +2205,12 @@ File: transient.info, Node: Suffix Format Methods, Prev: Suffix Value Methods, Show help for the prefix, infix or suffix command represented by OBJ. + Regardless of OBJ’s type, if its ‘show-help’ slot is non-‘nil’, + that must be a function, which takes OBJ is its only argument. It + must prepare, display and return a buffer, and select the window + used to display it. The ‘transient-show-help-window’ macro is + intended for use in such functions. + For prefixes, show the info manual, if that is specified using the ‘info-manual’ slot. Otherwise, show the manpage if that is specified using the ‘man-page’ slot. Otherwise, show the command’s @@ -1965,34 +2221,52 @@ File: transient.info, Node: Suffix Format Methods, Prev: Suffix Value Methods, For infixes, show the manpage if that is specified. Otherwise show the command’s documentation string. + -- Macro: transient-with-help-window &rest body + Evaluate BODY, send output to ‘*Help*’ buffer, and display it in a + window. Select the help window, and make the help buffer current + and return it. + + -- Function: transient-show-summary obj &optional return + This generic function shows or, if optional RETURN is non-‘nil’, + returns a brief summary about the command at point or hovered with + the mouse. + + This function is called when the mouse is moved over a command and + (if the value of ‘transient-enable-popup-navigation’ is ‘verbose’) + when the user navigates to a command using the keyboard. + + If OBJ’s ‘summary’ slot is a string, that is used. If ‘summary’ is + a function, that is called with OBJ as the only argument and the + returned string is used. If ‘summary’ is or returns something + other than a string or ‘nil’, no summary is shown. If ‘summary’ is + or returns ‘nil’, the first line of the documentation string is + used, if any. + + If RETURN is non-‘nil’, this function returns the summary instead + of showing it. This is used when a tooltip is needed. +  File: transient.info, Node: Prefix Slots, Next: Suffix Slots, Prev: Suffix Methods, Up: Classes and Methods -5.6 Prefix Slots +5.7 Prefix Slots ================ - • ‘show-help’, ‘man-page’ or ‘info-manual’ can be used to specify the - documentation for the prefix and its suffixes. The command - ‘transient-help’ uses the method ‘transient-show-help’ (which see) - to lookup and use these values. +Value and Scope +--------------- + + • ‘default-value’ The default value of the prefix. Use the keyword + argument ‘:value’ (sic) to set this slot in the definition of a + prefix. + + • ‘init-value’ A function that is responsible for setting the + object’s value. If bound, then this is called with the object as + the only argument. Usually this is not bound, in which case the + object’s primary ‘transient-init-value’ method is called instead. • ‘history-key’ If multiple prefix commands should share a single value, then this slot has to be set to the same value for all of them. You probably don’t want that. - • ‘transient-suffix’ and ‘transient-non-suffix’ play a part when - determining whether the currently active transient prefix command - remains active/transient when a suffix or arbitrary non-suffix - command is invoked. See *note 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 @@ -2006,8 +2280,65 @@ File: transient.info, Node: Prefix Slots, Next: Suffix Slots, Prev: Suffix Me • ‘scope’ For some transients it might be necessary to have a sort of secondary value, called a “scope”. See ‘transient-define-prefix’. -Internal Prefix Slots ---------------------- +Behavior +-------- + + • ‘transient-suffix’, ‘transient-non-suffix’ and + ‘transient-switch-frame’ play a part when determining whether the + currently active transient prefix command remains active/transient + when a suffix or arbitrary non-suffix command is invoked. See + *note 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. + + • ‘environment’ A function used to establish an environment while + initializing, refreshing or redisplaying a transient prefix menu. + This is useful to establish a cache, in case multiple suffixes + require the same expensive work. The provided function is called + with at least one argument, the function for which it establishes + the environment. It must ‘funcall’ that function with no + arguments. During initialization the second argument is the prefix + object being initialized. This slot is still experimental. + +Appearance +---------- + + • ‘display-action’ determines how this prefix is displayed, + overriding ‘transient-display-buffer-action’. It should have the + same type. + + • ‘mode-line-format’ is this prefix’s mode line format, overriding + ‘transient-mode-line-format’. It should have the same type. + + • ‘column-width’ is only respected inside ‘transient-columns’ groups + and allows aligning columns across separate instances of that. + + • ‘variable-pitch’ controls whether alignment is done pixel-wise to + account for use of variable-pitch characters, which is useful, + e.g., when using emoji. + +Documentation +------------- + + • ‘show-help’, ‘man-page’ or ‘info-manual’ can be used to specify the + documentation for the prefix and its suffixes. The command + ‘transient-help’ uses the function ‘transient-show-help’ (which + see) to lookup and use these values. + + • ‘suffix-description’ can be used to specify a function which + provides fallback descriptions for suffixes that lack a + description. This is intended to be temporarily used when + implementing of a new prefix command, at which time + ‘transient-command-summary-or-name’ is a useful value. + +Internal +-------- These slots are mostly intended for internal use. They should not be set in calls to ‘transient-define-prefix’. @@ -2035,10 +2366,13 @@ set in calls to ‘transient-define-prefix’. values. Unless you implement your own ‘transient-infix-read’ method you should not have to deal with these slots. + • ‘unwind-suffix’ is used internally to ensure transient state is + properly exited, even in case of an error. +  File: transient.info, Node: Suffix Slots, Next: Predicate Slots, Prev: Prefix Slots, Up: Classes and Methods -5.7 Suffix Slots +5.8 Suffix Slots ================ Here we document most of the slots that are only available for suffix @@ -2047,6 +2381,16 @@ documented in *note Predicate Slots::. Also see *note Suffix Classes::. +Slots of ‘transient-child’ +-------------------------- + +This is the abstract superclass of ‘transient-suffix’ and +‘transient-group’. This is where the shared ‘if*’ and ‘inapt-if*’ slots +(see *note Predicate Slots::) and the ‘level’ slot (see *note Enabling +and Disabling Suffixes::) are defined. + + • ‘parent’ The object for the parent group. + Slots of ‘transient-suffix’ --------------------------- @@ -2076,7 +2420,15 @@ Slots of ‘transient-suffix’ • ‘show-help’ A function used to display help for the suffix. If unspecified, the prefix controls how help is displayed for its - suffixes. + suffixes. See also function ‘transient-show-help’. + + • ‘summary’ The summary displayed in the echo area, or as a tooltip. + If this is ‘nil’, which it usually should be, the first line of the + documentation string is used instead. See ‘transient-show-summary’ + for details. + + • ‘definition’ A command, which is used if the body is omitted when + defining a command using ‘transient-define-suffix’. Slots of ‘transient-infix’ -------------------------- @@ -2170,13 +2522,16 @@ Slots of ‘transient-switches’  File: transient.info, Node: Predicate Slots, Prev: Suffix Slots, Up: Classes and Methods -5.8 Predicate Slots +5.9 Predicate Slots =================== -Suffix and group objects share some predicate slots that control whether -a group or suffix should be available depending on some state. Only one -of these slots can be used at the same time. It is undefined what -happens if you use more than one. +Suffix and group objects share two sets of predicate slots that control +whether a group or suffix should be available depending on some state. +Only one slot from each set can be used at the same time. It is +undefined which slot is honored if you use more than one. + + Predicates from the first group control whether the suffix is present +in the menu at all. • ‘if’ Enable if predicate returns non-‘nil’. • ‘if-not’ Enable if predicate returns ‘nil’. @@ -2187,6 +2542,21 @@ 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. + Predicates from the second group control whether the suffix can be +invoked. The suffix is shown in the menu regardless, but when it is +considered "inapt", then it is grayed out to indicated that it currently +cannot be invoked. + + • ‘inapt-if’ Inapt if predicate returns non-‘nil’. + • ‘inapt-if-not’ Inapt if predicate returns ‘nil’. + • ‘inapt-if-non-nil’ Inapt if variable’s value is non-‘nil’. + • ‘inapt-if-nil’ Inapt if variable’s value is ‘nil’. + • ‘inapt-if-mode’ Inapt if major-mode matches value. + • ‘inapt-if-not-mode’ Inapt if major-mode does not match value. + • ‘inapt-if-derived’ Inapt if major-mode derives from value. + • ‘inapt-if-not-derived’ Inapt 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 *note Prefix Slots::. @@ -2208,6 +2578,8 @@ A.1 Can I control how the popup buffer is displayed? ==================================================== Yes, see ‘transient-display-buffer-action’ in *note Configuration::. +You can also control how the popup buffer is displayed on a case-by-case +basis by passing ‘:display-action’ to ‘transient-define-prefix’. A.2 How can I copy text from the popup buffer? ============================================== @@ -2286,7 +2658,7 @@ potential prefix keys can be used for transient-specific commands particular is a prefix that I want to (and already do) use for Magit, and also using that for a common command would prevent me from doing so. - (Also see the next question.) + (See also the next question.) A.7 Why does ‘q’ not quit popups anymore? ========================================= @@ -2365,14 +2737,19 @@ Appendix C Command and Function Index * transient--do-suspend: Transient State. (line 161) * transient--do-suspend <1>: Transient State. (line 210) * transient--do-warn: Transient State. (line 187) -* transient--history-init: Prefix Classes. (line 10) * transient--insert-group: Group Methods. (line 19) +* transient-active-prefix: Current Prefix Command. + (line 39) * transient-append-suffix: Modifying Existing Transients. (line 51) * transient-arg-value: Using Infix Arguments. - (line 31) + (line 39) * transient-args: Using Infix Arguments. (line 22) +* transient-copy-menu-text: Other Commands. (line 25) +* transient-default-value: Prefix Methods. (line 23) +* transient-default-value <1>: Suffix Value Methods. + (line 24) * transient-define-argument: Defining Suffix and Infix Commands. (line 57) * transient-define-infix: Defining Suffix and Infix Commands. @@ -2390,24 +2767,31 @@ Appendix C Command and Function Index (line 22) * transient-get-suffix: Modifying Existing Transients. (line 73) +* transient-get-value: Using Infix Arguments. + (line 31) * transient-help: Getting Help for Suffix Commands. (line 11) * transient-history-next: Using History. (line 18) * transient-history-prev: Using History. (line 13) * transient-infix-read: Suffix Value Methods. - (line 16) + (line 28) * transient-infix-set: Suffix Value Methods. - (line 36) + (line 48) * transient-infix-value: Suffix Value Methods. - (line 39) -* transient-init-scope: Suffix Value Methods. - (line 52) -* transient-init-value: Suffix Value Methods. + (line 51) +* transient-init-scope: Prefix Methods. (line 37) +* transient-init-scope <1>: Suffix Value Methods. + (line 64) +* transient-init-value: Prefix Methods. (line 9) +* transient-init-value <1>: Suffix Value Methods. (line 6) * transient-insert-suffix: Modifying Existing Transients. (line 49) +* transient-prefix-object: Current Prefix Command. + (line 6) +* transient-prefix-value: Prefix Methods. (line 32) * transient-prompt: Suffix Value Methods. - (line 32) + (line 44) * transient-quit-all: Aborting and Resuming Transients. (line 36) * transient-quit-one: Aborting and Resuming Transients. @@ -2430,16 +2814,23 @@ Appendix C Command and Function Index * transient-setup-children: Group Methods. (line 6) * transient-show-help: Suffix Format Methods. (line 26) +* transient-show-summary: Suffix Format Methods. + (line 51) +* transient-suffix-object: Current Suffix Command. + (line 6) * transient-suffix-put: Modifying Existing Transients. (line 77) * transient-suffixes: Using Infix Arguments. - (line 38) + (line 46) * transient-suspend: Aborting and Resuming Transients. (line 41) * transient-toggle-common: Common Suffix Commands. (line 18) +* transient-toggle-docstrings: Other Commands. (line 29) * transient-toggle-level-limit: Enabling and Disabling Suffixes. (line 68) +* transient-with-help-window: Suffix Format Methods. + (line 46)  File: transient.info, Node: Variable Index, Next: Concept Index, Prev: Command and Function Index, Up: Top @@ -2450,37 +2841,39 @@ Appendix D Variable Index [index] * Menu: -* transient-active-prefix: Using Infix Arguments. - (line 61) -* transient-align-variable-pitch: Configuration. (line 185) -* transient-current-command: Using Infix Arguments. - (line 52) -* transient-current-prefix: Using Infix Arguments. - (line 56) -* transient-current-suffixes: Using Infix Arguments. - (line 44) +* transient-align-variable-pitch: Configuration. (line 239) +* transient-current-command: Current Prefix Command. + (line 35) +* transient-current-prefix: Current Prefix Command. + (line 30) +* transient-current-suffixes: Current Suffix Command. + (line 45) * transient-default-level: Enabling and Disabling Suffixes. (line 33) -* transient-detect-key-conflicts: Configuration. (line 210) -* transient-display-buffer-action: Configuration. (line 51) -* transient-enable-popup-navigation: Configuration. (line 36) -* transient-force-fixed-pitch: Configuration. (line 198) -* transient-force-single-column: Configuration. (line 93) -* transient-hide-during-minibuffer-read: Configuration. (line 181) -* transient-highlight-higher-levels: Configuration. (line 223) -* transient-highlight-mismatched-keys: Configuration. (line 135) -* transient-history-file: Using History. (line 33) -* transient-history-limit: Using History. (line 37) +* transient-detect-key-conflicts: Configuration. (line 264) +* transient-display-buffer-action: Configuration. (line 112) +* transient-enable-popup-navigation: Configuration. (line 90) +* transient-exit-hook: Configuration. (line 290) +* transient-force-fixed-pitch: Configuration. (line 252) +* transient-force-single-column: Configuration. (line 155) +* transient-highlight-higher-levels: Configuration. (line 277) +* transient-highlight-mismatched-keys: Configuration. (line 200) +* transient-history-file: Using History. (line 37) +* transient-history-limit: Using History. (line 41) * transient-levels-file: Enabling and Disabling Suffixes. (line 38) -* transient-mode-line-format: Configuration. (line 102) -* transient-read-with-initial-input: Configuration. (line 174) -* transient-semantic-coloring: Configuration. (line 126) +* transient-mode-line-format: Configuration. (line 164) +* transient-read-with-initial-input: Configuration. (line 83) +* transient-save-history: Using History. (line 33) +* transient-semantic-coloring: Configuration. (line 191) +* transient-setup-buffer-hook: Configuration. (line 293) * transient-show-common-commands: Common Suffix Commands. (line 23) +* transient-show-common-commands <1>: Configuration. (line 36) +* transient-show-during-minibuffer-read: Configuration. (line 46) * transient-show-popup: Configuration. (line 15) -* transient-substitute-key-function: Configuration. (line 153) -* transient-values-file: Saving Values. (line 31) +* transient-substitute-key-function: Configuration. (line 218) +* transient-values-file: Saving Values. (line 32)  File: transient.info, Node: Concept Index, Next: GNU General Public License, Prev: Variable Index, Up: Top @@ -3247,68 +3640,77 @@ please read .  Tag Table: Node: Top763 -Node: Introduction2976 -Ref: Some things that Transient can do3504 -Ref: Complexity in CLI programs3857 -Ref: Using Transient for composing interactive commands4458 -Node: Usage6700 -Node: Invoking Transients7068 -Node: Aborting and Resuming Transients8147 -Node: Common Suffix Commands10768 -Node: Saving Values12604 -Ref: Saving Values-Footnote-113975 -Node: Using History14168 -Node: Getting Help for Suffix Commands15742 -Node: Enabling and Disabling Suffixes17120 -Node: Other Commands20408 -Node: Configuration21384 -Ref: Essential Options21664 -Ref: Accessibility Options25325 -Ref: Auxiliary Options25648 -Ref: Developer Options30611 -Node: Modifying Existing Transients31859 -Node: Defining New Commands36051 -Node: Technical Introduction36414 -Node: Defining Transients42115 -Node: Binding Suffix and Infix Commands44582 -Node: Group Specifications45440 -Node: Suffix Specifications51968 -Node: Defining Suffix and Infix Commands56181 -Node: Using Infix Arguments59229 -Node: Transient State62853 -Ref: Pre-commands for Infixes67668 -Ref: Pre-commands for Suffixes68188 -Ref: Pre-commands for Non-Suffixes70642 -Ref: Special Pre-Commands71778 -Node: Classes and Methods72286 -Node: Group Classes74470 -Node: Group Methods76397 -Node: Prefix Classes77650 -Node: Suffix Classes78741 -Node: Suffix Methods81828 -Node: Suffix Value Methods82149 -Node: Suffix Format Methods84907 -Node: Prefix Slots86386 -Ref: Internal Prefix Slots88521 -Node: Suffix Slots89778 -Ref: Slots of transient-suffix90146 -Ref: Slots of transient-infix91283 -Ref: Slots of transient-variable94579 -Ref: Slots of transient-switches94681 -Node: Predicate Slots95044 -Node: FAQ96479 -Ref: Can I control how the popup buffer is displayed?96608 -Ref: How can I copy text from the popup buffer?96789 -Ref: How can I autoload prefix and suffix commands?97283 -Ref: How does Transient compare to prefix keys and universal arguments?97757 -Ref: How does Transient compare to Magit-Popup and Hydra?98000 -Ref: Why did some of the key bindings change?98194 -Ref: Why does q not quit popups anymore?100547 -Node: Keystroke Index101650 -Node: Command and Function Index103515 -Node: Variable Index110107 -Node: Concept Index112517 -Node: GNU General Public License115253 +Node: Introduction3049 +Ref: Some things that Transient can do3577 +Ref: Complexity in CLI programs3930 +Ref: Using Transient for composing interactive commands4531 +Node: Usage6773 +Node: Invoking Transients7141 +Node: Aborting and Resuming Transients8310 +Node: Common Suffix Commands10931 +Node: Saving Values12638 +Ref: Saving Values-Footnote-114042 +Node: Using History14235 +Node: Getting Help for Suffix Commands15941 +Node: Enabling and Disabling Suffixes17319 +Node: Other Commands20607 +Node: Configuration22284 +Ref: Essential Options22564 +Ref: Accessibility Options29394 +Ref: Auxiliary Options29717 +Ref: Developer Options34295 +Ref: Hook Variables35543 +Node: Modifying Existing Transients35830 +Node: Defining New Commands40022 +Node: Technical Introduction40439 +Node: Defining Transients46139 +Node: Binding Suffix and Infix Commands48606 +Node: Group Specifications49464 +Node: Suffix Specifications56015 +Node: Defining Suffix and Infix Commands60228 +Node: Using Infix Arguments63276 +Node: Current Suffix Command65669 +Node: Current Prefix Command68029 +Node: Transient State70585 +Ref: Pre-commands for Infixes75401 +Ref: Pre-commands for Suffixes75921 +Ref: Pre-commands for Non-Suffixes78375 +Ref: Special Pre-Commands79511 +Node: Classes and Methods80019 +Node: Group Classes82106 +Node: Group Methods84033 +Node: Prefix Classes85293 +Node: Suffix Classes86138 +Node: Prefix Methods90118 +Node: Suffix Methods92511 +Node: Suffix Value Methods92832 +Node: Suffix Format Methods96181 +Node: Prefix Slots99183 +Ref: Value and Scope99333 +Ref: Behavior100812 +Ref: Appearance102153 +Ref: Documentation102812 +Ref: Internal103432 +Node: Suffix Slots104787 +Ref: Slots of transient-child105155 +Ref: Slots of transient-suffix105530 +Ref: Slots of transient-infix107103 +Ref: Slots of transient-variable110399 +Ref: Slots of transient-switches110501 +Node: Predicate Slots110864 +Node: FAQ113209 +Ref: Can I control how the popup buffer is displayed?113338 +Ref: How can I copy text from the popup buffer?113665 +Ref: How can I autoload prefix and suffix commands?114159 +Ref: How does Transient compare to prefix keys and universal arguments?114633 +Ref: How does Transient compare to Magit-Popup and Hydra?114876 +Ref: Why did some of the key bindings change?115070 +Ref: Why does q not quit popups anymore?117423 +Node: Keystroke Index118526 +Node: Command and Function Index120391 +Node: Variable Index128309 +Node: Concept Index130877 +Node: GNU General Public License133613  End Tag Table diff --git a/elpa/transient-readme.txt b/elpa/transient-readme.txt deleted file mode 100644 index 674b25f7..00000000 --- a/elpa/transient-readme.txt +++ /dev/null @@ -1,21 +0,0 @@ -Taking inspiration from prefix keys and prefix arguments, Transient -implements a similar abstraction involving a prefix command, infix -arguments and suffix commands. We could call this abstraction a -"transient command", but because it always involves at least two -commands (a prefix and a suffix) we prefer to call it just a -"transient". - -When the user calls a transient prefix command, then a transient -(temporary) keymap is activated, which binds the transient's infix -and suffix commands, and functions that control the transient state -are added to `pre-command-hook' and `post-command-hook'. The -available suffix and infix commands and their state are shown in -the echo area until the transient is exited by invoking a suffix -command. - -Calling an infix command causes its value to be changed, possibly -by reading a new value in the minibuffer. - -Calling a suffix command usually causes the transient to be exited -but suffix commands can also be configured to not exit the -transient state. -- 2.47.3