From f76ca2645bf9d116ac2b9ede349290438164db09 Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Wed, 24 Dec 2025 14:28:35 +0100 Subject: [PATCH] update transient --- .../dir | 0 .../gpl.info | 0 .../transient-autoloads.el | 0 .../transient-pkg.el | 13 +- .../transient.el | 1105 ++++++++++------- .../transient.info | 312 +++-- 6 files changed, 845 insertions(+), 585 deletions(-) rename elpa/{transient-20250520.1040 => transient-20251215.2209}/dir (100%) rename elpa/{transient-20250520.1040 => transient-20251215.2209}/gpl.info (100%) rename elpa/{transient-20250520.1040 => transient-20251215.2209}/transient-autoloads.el (100%) rename elpa/{transient-20250520.1040 => transient-20251215.2209}/transient-pkg.el (58%) rename elpa/{transient-20250520.1040 => transient-20251215.2209}/transient.el (87%) rename elpa/{transient-20250520.1040 => transient-20251215.2209}/transient.info (95%) diff --git a/elpa/transient-20250520.1040/dir b/elpa/transient-20251215.2209/dir similarity index 100% rename from elpa/transient-20250520.1040/dir rename to elpa/transient-20251215.2209/dir diff --git a/elpa/transient-20250520.1040/gpl.info b/elpa/transient-20251215.2209/gpl.info similarity index 100% rename from elpa/transient-20250520.1040/gpl.info rename to elpa/transient-20251215.2209/gpl.info diff --git a/elpa/transient-20250520.1040/transient-autoloads.el b/elpa/transient-20251215.2209/transient-autoloads.el similarity index 100% rename from elpa/transient-20250520.1040/transient-autoloads.el rename to elpa/transient-20251215.2209/transient-autoloads.el diff --git a/elpa/transient-20250520.1040/transient-pkg.el b/elpa/transient-20251215.2209/transient-pkg.el similarity index 58% rename from elpa/transient-20250520.1040/transient-pkg.el rename to elpa/transient-20251215.2209/transient-pkg.el index 97b5054d..eb6ae2df 100644 --- a/elpa/transient-20250520.1040/transient-pkg.el +++ b/elpa/transient-20251215.2209/transient-pkg.el @@ -1,12 +1,13 @@ ;; -*- no-byte-compile: t; lexical-binding: nil -*- -(define-package "transient" "20250520.1040" +(define-package "transient" "20251215.2209" "Transient commands." - '((emacs "26.1") - (compat "30.1.0.0") - (seq "2.24")) + '((emacs "28.1") + (compat "30.1") + (cond-let "0.2") + (seq "2.24")) :url "https://github.com/magit/transient" - :commit "cb6550d5b111b7815feec97b236ecb051de70dbe" - :revdesc "cb6550d5b111" + :commit "066b985b19afbcc8f2f344cebb8d2f4c626b1bdc" + :revdesc "066b985b19af" :keywords '("extensions") :authors '(("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) :maintainers '(("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev"))) diff --git a/elpa/transient-20250520.1040/transient.el b/elpa/transient-20251215.2209/transient.el similarity index 87% rename from elpa/transient-20250520.1040/transient.el rename to elpa/transient-20251215.2209/transient.el index 721867ad..9e08a370 100644 --- a/elpa/transient-20250520.1040/transient.el +++ b/elpa/transient-20251215.2209/transient.el @@ -6,9 +6,13 @@ ;; Homepage: https://github.com/magit/transient ;; Keywords: extensions -;; Package-Version: 20250520.1040 -;; Package-Revision: cb6550d5b111 -;; Package-Requires: ((emacs "26.1") (compat "30.1.0.0") (seq "2.24")) +;; Package-Version: 20251215.2209 +;; Package-Revision: 066b985b19af +;; Package-Requires: ( +;; (emacs "28.1") +;; (compat "30.1") +;; (cond-let "0.2") +;; (seq "2.24")) ;; SPDX-License-Identifier: GPL-3.0-or-later @@ -35,10 +39,11 @@ ;;; Code: -(defconst transient-version "0.8.8") +(defconst transient-version "0.11.0") (require 'cl-lib) (require 'compat) +(require 'cond-let) (require 'eieio) (require 'edmacro) (require 'format-spec) @@ -82,10 +87,6 @@ similar defect.") :emergency)) (eval-when-compile (require 'subr-x)) -(eval-and-compile - (unless (boundp 'eieio--unbound) ; New name since Emacs 28.1. - (defvaralias 'eieio--unbound 'eieio-unbound nil))) - (declare-function info "info" (&optional file-or-node buffer)) (declare-function Man-find-section "man" (section)) (declare-function Man-next-section "man" (n)) @@ -94,17 +95,18 @@ 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 - 'transient-show-during-minibuffer-read "0.8.0") +(static-if (< emacs-major-version 30) + (progn + (defun internal--build-binding@backport-e680827e814 (fn binding prev-var) + "Backport not warning about `_' not being left unused. +Backport fix for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=69108, +from Emacs commit e680827e814e155cf79175d87ff7c6ee3a08b69a." + (let ((binding (funcall fn binding prev-var))) + (if (eq (car binding) '_) + (cons (make-symbol "s") (cdr binding)) + binding))) + (advice-add 'internal--build-binding :around + #'internal--build-binding@backport-e680827e814))) (defvar transient-common-command-prefix) @@ -132,9 +134,10 @@ TYPE is a type descriptor as accepted by `cl-typep', which see." (defcustom transient-show-popup t "Whether and when to show transient's menu in a buffer. -\\ -- If t, then show the buffer as soon as a transient prefix command - is invoked. + +\\\ +- If t (the default), then show the buffer as soon as a transient + prefix command is invoked. - If nil, then do not show the buffer unless the user explicitly requests it, by pressing \\[transient-show] or a prefix key. @@ -156,8 +159,8 @@ TYPE is a type descriptor as accepted by `cl-typep', which see." (defcustom transient-enable-popup-navigation 'verbose "Whether navigation commands are enabled in the menu buffer. -If the value is `verbose', additionally show brief documentation -about the command under point in the echo area. +If the value is `verbose' (the default), additionally show brief +documentation about the command under point in the echo area. While a transient is active transient's menu buffer is not the current buffer, making it necessary to use dedicated commands to @@ -246,6 +249,7 @@ want to change the value of `transient-mode-line-format'." (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." @@ -367,12 +371,15 @@ This command is not bound by default, see its docstring for instructions." (defcustom transient-highlight-mismatched-keys nil "Whether to highlight keys that do not match their argument. -This only affects infix arguments that represent command-line -arguments. When this option is non-nil, then the key binding -for infix argument are highlighted when only a long argument -\(e.g., \"--verbose\") is specified but no shorthand (e.g., \"-v\"). -In the rare case that a short-hand is specified but does not -match the key binding, then it is highlighted differently. +This is mostly intended for authors of transient menus and disabled by +default. + +This only affects infix arguments that represent command-line arguments. +When this option is non-nil, then the key binding for infix argument are +highlighted when only a long argument \(e.g., \"--verbose\") is specified +but no shorthand (e.g., \"-v\"). In the rare case that a short-hand is +specified but does not match the key binding, then it is highlighted +differently. The highlighting is done using `transient-mismatched-key' and `transient-nonstandard-key'." @@ -577,6 +584,11 @@ give you as many additional suffixes as you hoped.)" "Face used for inactive arguments." :group 'transient-faces) +(defface transient-inapt-argument '((t :inherit shadow :weight bold)) + "Face used for inapt arguments with a (currently ignored) value. +Depending on the type this is used for the argument and/or value." + :group 'transient-faces) + (defface transient-value '((t :inherit font-lock-string-face :weight bold)) "Face used for values." :group 'transient-faces) @@ -610,10 +622,9 @@ See info node `(transient)Enabling and Disabling Suffixes'." :group 'transient-faces) (defface transient-higher-level - `((t :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1) - :color ,(let ((color (face-attribute 'shadow :foreground t t))) - (or (and (not (eq color 'unspecified)) color) - "grey60"))))) + (let* ((color (face-attribute 'shadow :foreground t t)) + (color (if (eq color 'unspecified) "grey60" color))) + `((t :box (:line-width (-1 . -1) :color ,color)))) "Face optionally used to highlight suffixes on higher levels. See also option `transient-highlight-higher-levels'." :group 'transient-faces) @@ -694,15 +705,13 @@ character used to separate possible values from each other." :group 'transient-faces) (defface transient-nonstandard-key - `((t :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1) - :color "cyan"))) + `((t :box (:line-width (-1 . -1) :color "cyan"))) "Face optionally used to highlight keys conflicting with short-argument. 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"))) + `((t :box (:line-width (-1 . -1) :color "magenta"))) "Face optionally used to highlight keys without a short-argument. See also option `transient-highlight-mismatched-keys'." :group 'transient-faces) @@ -716,15 +725,16 @@ See also option `transient-highlight-mismatched-keys'." (insert-file-contents file) (read (current-buffer)))))) -(defun transient--pp-to-file (list file) - (make-directory (file-name-directory file) t) - (setq list (cl-sort (copy-sequence list) #'string< :key #'car)) - (with-temp-file file - (let ((print-level nil) - (print-length nil) - (pp-default-function 'pp-28) - (fill-column 999)) - (pp list (current-buffer))))) +(defun transient--pp-to-file (value file) + (when (or value (file-exists-p file)) + (make-directory (file-name-directory file) t) + (setq value (cl-sort (copy-sequence value) #'string< :key #'car)) + (with-temp-file file + (let ((print-level nil) + (print-length nil) + (pp-default-function 'pp-28) + (fill-column 999)) + (pp value (current-buffer)))))) (defvar transient-values (transient--read-file-contents transient-values-file) @@ -791,6 +801,7 @@ 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) + (remember-value :initarg :remember-value :initform nil) (environment :initarg :environment :initform nil) (incompatible :initarg :incompatible :initform nil) (suffix-description :initarg :suffix-description) @@ -820,6 +831,8 @@ the prototype is stored in the clone's `prototype' slot.") :initarg :level :initform nil :documentation "Enable if level of prefix is equal or greater.") + (inactive + :initform nil) (if :initarg :if :initform nil @@ -1256,7 +1269,7 @@ commands are aliases for." (setq class v) (push k keys) (push v keys)))) - (while-let + (while-let* ((arg (car args)) (arg (cond ;; Inline group definition. @@ -1296,8 +1309,8 @@ commands are aliases for." (cl-typecase spec (null (error "Invalid transient--parse-child spec: %s" spec)) (symbol (list `',spec)) - (vector (and-let* ((c (transient--parse-group prefix spec))) (list c))) - (list (and-let* ((c (transient--parse-suffix prefix spec))) (list c))) + (vector (and$ (transient--parse-group prefix spec) (list $))) + (list (and$ (transient--parse-suffix prefix spec) (list $))) (string (list spec)) (t (error "Invalid transient--parse-child spec: %s" spec)))) @@ -1351,9 +1364,10 @@ commands are aliases for." (guard (commandp (cadr spec)))) (use :description (macroexp-quote (pop spec))))) (pcase (car spec) - ((or :info :info*)) + ((or :info :info* :cons)) ((and (cl-type keyword) invalid) - (error "Need command, argument, `:info' or `:info*'; got `%s'" invalid)) + (error "Need command, argument, `:info', `:info*' or `:cons'; got `%s'" + invalid)) ((cl-type symbol) (use :command (macroexp-quote (pop spec)))) ;; During macro-expansion this is expected to be a `lambda' @@ -1408,6 +1422,15 @@ commands are aliases for." (use :description val)) (:info* (setq class 'transient-information*) (use :description val)) + (:cons + (setq class 'transient-cons-option) + (use :command + (let ((sym (intern (format "transient:%s:%s" prefix val)))) + `(prog1 ',sym + (put ',sym 'interactive-only t) + (put ',sym 'completion-predicate #'transient--suffix-only) + (defalias ',sym #'transient--default-infix-command)))) + (use :argument val)) ((guard (eq (car-safe val) '\,)) (use key (cadr val))) ((guard (or (symbolp val) @@ -1417,12 +1440,13 @@ commands are aliases for." (_ (use key val))))) (when spec (error "Need keyword, got %S" (car spec))) - (if-let ((key (plist-get args :key))) - (when (string-match "\\`\\({p}\\)" key) - (use :key - (replace-match transient-common-command-prefix t t key 1))) - (when-let ((shortarg (plist-get args :shortarg))) - (use :key shortarg)))) + (cond-let + ([key (plist-get args :key)] + (when (string-match "\\`\\({p}\\)" key) + (use :key + (replace-match transient-common-command-prefix t t key 1)))) + ([shortarg (plist-get args :shortarg)] + (use :key shortarg)))) (list 'cons (macroexp-quote (or class 'transient-suffix)) (cons 'list args)))) @@ -1447,8 +1471,7 @@ See also `transient-command-completion-not-suffix-only-p'. Only use this alias as the value of the `completion-predicate' symbol property.") -(when (and (boundp 'read-extended-command-predicate) ; since Emacs 28.1 - (not read-extended-command-predicate)) +(unless read-extended-command-predicate (setq read-extended-command-predicate #'transient-command-completion-not-suffix-only-p)) @@ -1456,50 +1479,50 @@ symbol property.") (put prefix 'transient--layout (vector 2 nil layout))) (defun transient--get-layout (prefix) - (if-let* - ((layout - (or (get prefix 'transient--layout) - ;; Migrate unparsed legacy group definition. - (condition-case-unless-debug err - (and-let* ((value (symbol-value prefix))) - (transient--set-layout - prefix - (if (and (listp value) - (or (listp (car value)) - (vectorp (car value)))) - (transient-parse-suffixes prefix value) - (list (transient-parse-suffix prefix value))))) - (error - (message "Not a legacy group definition: %s: %S" prefix err) - nil))))) - (if (vectorp layout) - (let ((version (aref layout 0))) - (if (= version 2) - layout - (error "Unsupported layout version %s for %s" version prefix))) - ;; Upgrade from version 1. - (cl-labels - ((upgrade (spec) - (cond - ((vectorp spec) - (pcase-let ((`[,level ,class ,args ,children] spec)) - (when level - (setq args (plist-put args :level level))) - (vector class args (mapcar #'upgrade children)))) - ((and (listp spec) - (length= spec 3) - (or (null (car spec)) - (natnump (car spec))) - (symbolp (cadr spec))) - (pcase-let ((`(,level ,class ,args) spec)) - (when level - (setq args (plist-put args :level level))) - (cons class args))) - ((listp spec) - (mapcar #'upgrade spec)) - (t spec)))) - (transient--set-layout prefix (upgrade layout)))) - (error "Not a transient prefix command or group definition: %s" prefix))) + (cond-let + [[layout (or (get prefix 'transient--layout) + ;; Migrate unparsed legacy group definition. + (condition-case-unless-debug err + (and-let* ((value (symbol-value prefix))) + (transient--set-layout + prefix + (if (and (listp value) + (or (listp (car value)) + (vectorp (car value)))) + (transient-parse-suffixes prefix value) + (list (transient-parse-suffix prefix value))))) + (error + (message "Not a legacy group definition: %s: %S" prefix err) + nil)))]] + ((not layout) + (error "Not a transient prefix command or group definition: %s" prefix)) + ((vectorp layout) + (let ((version (aref layout 0))) + (if (= version 2) + layout + (error "Unsupported layout version %s for %s" version prefix)))) + (t + ;; Upgrade from version 1. + (transient--set-layout + prefix + (named-let upgrade ((spec layout)) + (cond ((vectorp spec) + (pcase-let ((`[,level ,class ,args ,children] spec)) + (when level + (setq args (plist-put args :level level))) + (vector class args (mapcar #'upgrade children)))) + ((and (listp spec) + (length= spec 3) + (or (null (car spec)) + (natnump (car spec))) + (symbolp (cadr spec))) + (pcase-let ((`(,level ,class ,args) spec)) + (when level + (setq args (plist-put args :level level))) + (cons class args))) + ((listp spec) + (mapcar #'upgrade spec)) + (t spec))))))) (defun transient--get-children (prefix) (aref (transient--get-layout prefix) 2)) @@ -1510,9 +1533,8 @@ PREFIX is a prefix command symbol or object. SUFFIX is a suffix command or a group specification (of the same forms as expected by `transient-define-prefix'). Intended for use in a group's `:setup-children' function." - (if (cl-typep prefix 'transient-prefix) - (setq prefix (oref prefix command)) - (transient--get-layout prefix)) ; validate + (when (cl-typep prefix 'transient-prefix) + (setq prefix (oref prefix command))) (eval (car (transient--parse-child prefix suffix)) t)) (defun transient-parse-suffixes (prefix suffixes) @@ -1521,9 +1543,8 @@ PREFIX is a prefix command symbol or object. SUFFIXES is a list of suffix command or a group specification (of the same forms as expected by `transient-define-prefix'). Intended for use in a group's `:setup-children' function." - (if (cl-typep prefix 'transient-prefix) - (setq prefix (oref prefix command)) - (transient--get-layout prefix)) ; validate + (when (cl-typep prefix 'transient-prefix) + (setq prefix (oref prefix command))) (mapcar (apply-partially #'transient-parse-suffix prefix) suffixes)) ;;; Edit @@ -1548,9 +1569,9 @@ Intended for use in a group's `:setup-children' function." suffix prefix loc "suffixes and groups cannot be siblings")) (t - (when-let* (((not (eq keep-other 'always))) + (when-let* ((_(not (eq keep-other 'always))) (bindingp (listp suf)) - (key (transient--spec-key suf)) + (key (transient--suffix-key suf)) (conflict (car (transient--locate-child prefix key))) (conflictp (and (not (and (eq action 'replace) @@ -1562,7 +1583,9 @@ Intended for use in a group's `:setup-children' function." :command))) (equal (transient--suffix-predicate suf) (transient--suffix-predicate conflict))))) - (transient-remove-suffix prefix key)) + (transient-remove-suffix prefix key) + (let ((eg (transient--locate-child prefix loc))) + (setq elt (car eg) group (cadr eg)))) (let ((mem (memq elt (aref group 2)))) (pcase-exhaustive action ('insert (setcdr mem (cons elt (cdr mem))) @@ -1677,45 +1700,44 @@ See info node `(transient)Modifying Existing Transients'." (setq group (transient--get-layout group))) (when (vectorp loc) (setq loc (append loc nil))) - (if (listp loc) - (and-let* ((match (transient--nth (pop loc) (aref group 2)))) - (if loc - (transient--locate-child - match (cond ((or (stringp (car loc)) - (symbolp (car loc))) - (car loc)) - ((symbolp match) - (vconcat (cons 0 loc))) - ((vconcat loc)))) - (list match group))) - (seq-some (lambda (child) - (transient--match-child group loc child)) - (aref group 2)))) + (cond-let + ((atom loc) + (seq-some (lambda (child) + (transient--match-child group loc child)) + (aref group 2))) + ([match (transient--nth (pop loc) (aref group 2))] + (cond (loc (transient--locate-child + match (cond ((or (stringp (car loc)) + (symbolp (car loc))) + (car loc)) + ((symbolp match) + (vconcat (cons 0 loc))) + ((vconcat loc))))) + ((list match group)))))) (defun transient--match-child (group loc child) (cl-etypecase child (string nil) - (symbol (if (symbolp loc) - (and (eq child loc) - (list child group)) - (and-let* ((include (transient--get-layout child))) - (transient--locate-child include loc)))) + (symbol (cond-let + ((symbolp loc) + (and (eq child loc) + (list child group))) + ([include (transient--get-layout child)] + (transient--locate-child include loc)))) (vector (seq-some (lambda (subgroup) (transient--locate-child subgroup loc)) (aref group 2))) - (list (let* ((props (transient--suffix-props child)) - (cmd (plist-get props :command))) - (and (if (symbolp loc) - (eq cmd loc) - (equal (kbd (or (plist-get props :key) - (transient--command-key cmd))) - (kbd loc))) - (list child group)))))) + (list (and (if (symbolp loc) + (eq (plist-get (transient--suffix-props child) :command) + loc) + (equal (kbd (transient--suffix-key child)) + (kbd loc))) + (list child group))))) (defun transient--nth (n list) (nth (if (< n 0) (- (length list) (abs n)) n) list)) -(defun transient--spec-key (spec) +(defun transient--suffix-key (spec) (let ((props (transient--suffix-props spec))) (or (plist-get props :key) (transient--command-key @@ -1852,6 +1874,10 @@ This is bound while the suffixes are drawn in the transient buffer.") mwheel-scroll scroll-bar-toolkit-scroll)) +(defvar transient--quit-commands + '(transient-quit-one + transient-quit-all)) + ;;; Identities (defun transient-active-prefix (&optional prefixes) @@ -1943,47 +1969,46 @@ probably use this instead: (get COMMAND \\='transient--suffix)" (when command (cl-check-type command command)) - (cond - (transient--pending-suffix) - (transient--current-suffix) - ((or transient--prefix - transient-current-prefix) - (let ((suffixes - (cl-remove-if-not - (lambda (obj) - (eq (oref obj command) - (or command - (if (eq this-command 'transient-set-level) - ;; This is how it can look up for which - ;; command it is setting the level. - this-original-command - this-command)))) - (or transient--suffixes - transient-current-suffixes)))) - (cond - ((length= suffixes 1) - (car suffixes)) - ((cl-find-if (lambda (obj) - (equal (listify-key-sequence (kbd (oref obj key))) - (listify-key-sequence (this-command-keys)))) - suffixes)) - ;; COMMAND is only provided if `this-command' is meaningless, in - ;; which case `this-command-keys' is also meaningless, making it - ;; impossible to disambiguate bindings for the same command. - (command (car suffixes)) - ;; If COMMAND is nil, then failure to disambiguate likely means - ;; that there is a bug somewhere. - ((length> suffixes 1) - (error "BUG: Cannot unambiguously determine suffix object")) - ;; It is legimate to use this function as a predicate of sorts. - ;; `transient--pre-command' and `transient-help' are examples. - (t nil)))) - ((and-let* ((obj (transient--suffix-prototype (or command this-command))) - (obj (clone obj))) - (progn - (transient-init-scope obj) - (transient-init-value obj) - obj))))) + (cond-let* + (transient--pending-suffix) + (transient--current-suffix) + ((or transient--prefix + transient-current-prefix) + (let ((suffixes + (cl-remove-if-not + (lambda (obj) + (eq (oref obj command) + (or command + (if (eq this-command 'transient-set-level) + ;; This is how it can look up for which + ;; command it is setting the level. + this-original-command + this-command)))) + (or transient--suffixes + transient-current-suffixes)))) + (cond + ((length= suffixes 1) + (car suffixes)) + ((cl-find-if (lambda (obj) + (equal (listify-key-sequence (kbd (oref obj key))) + (listify-key-sequence (this-command-keys)))) + suffixes)) + ;; COMMAND is only provided if `this-command' is meaningless, in + ;; which case `this-command-keys' is also meaningless, making it + ;; impossible to disambiguate bindings for the same command. + (command (car suffixes)) + ;; If COMMAND is nil, then failure to disambiguate likely means + ;; that there is a bug somewhere. + ((length> suffixes 1) + (error "BUG: Cannot unambiguously determine suffix object")) + ;; It is legimate to use this function as a predicate of sorts. + ;; `transient--pre-command' and `transient-help' are examples. + (t nil)))) + ([obj (transient--suffix-prototype (or command this-command))] + [obj (clone obj)] + (transient-init-scope obj) + (transient-init-value obj) + obj))) (defun transient--suffix-prototype (command) (or (get command 'transient--suffix) @@ -2016,25 +2041,22 @@ to `transient-predicate-map'." "" #'transient-scroll-up "" #'transient-scroll-down) -(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) - ;; Next two have additional bindings 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. +(defvar-keymap transient-map + :doc "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'. See also `transient-base-map'.") +to `transient-predicate-map'. See also `transient-base-map'." + :parent transient-base-map + "C-u" #'universal-argument + "C--" #'negative-argument + "C-t" #'transient-show + "?" #'transient-help + "C-h" #'transient-help + "C-x 5 5" #'other-frame-prefix + "C-x 4 4" #'other-window-prefix + ;; These have additional bindings in transient-common-commands. + "C-M-p" #'transient-history-prev + "C-M-n" #'transient-history-next) (defvar-keymap transient-edit-map :doc "Keymap that is active while a transient in is in \"edit mode\"." @@ -2246,17 +2268,19 @@ of the corresponding object." (cond ((not alt) (define-key map kbd cmd)) ((eq alt cmd)) - ((transient--inapt-suffix-p obj)) - ((and-let* ((obj (transient-suffix-object alt))) - (transient--inapt-suffix-p obj)) + ((oref obj inactive)) + ((oref obj inapt)) + ((and-let* ((alt (transient-suffix-object alt))) + (or (oref alt inactive) + (oref alt inapt))) (define-key map kbd cmd)) (transient-detect-key-conflicts (error "Cannot bind %S to %s and also %s" (string-trim key) cmd alt)) ((define-key map kbd cmd)))))) - (when-let ((b (keymap-lookup map "-"))) (keymap-set map "" b)) - (when-let ((b (keymap-lookup map "="))) (keymap-set map "" b)) - (when-let ((b (keymap-lookup map "+"))) (keymap-set map "" b)) + (when-let* ((b (keymap-lookup map "-"))) (keymap-set map "" b)) + (when-let* ((b (keymap-lookup map "="))) (keymap-set map "" b)) + (when-let* ((b (keymap-lookup map "+"))) (keymap-set map "" b)) (when transient-enable-popup-navigation ;; `transient--make-redisplay-map' maps only over bindings that are ;; directly in the base keymap, so that cannot be a composed keymap. @@ -2267,10 +2291,10 @@ of the corresponding object." map)) (defun transient--make-predicate-map () - (let* ((default (transient--resolve-pre-command - (oref transient--prefix transient-suffix))) - (return (and transient--stack (oref transient--prefix return))) - (map (make-sparse-keymap))) + (let ((default (transient--resolve-pre-command + (oref transient--prefix transient-suffix))) + (return (and transient--stack (oref transient--prefix return))) + (map (make-sparse-keymap))) (set-keymap-parent map transient-predicate-map) (when (or (and (slot-boundp transient--prefix 'transient-switch-frame) (transient--resolve-pre-command @@ -2286,6 +2310,7 @@ of the corresponding object." ((cl-typep obj 'transient-infix) 'infix) (t 'suffix))) (pre (cond + ((oref obj inactive) nil) ((oref obj inapt) #'transient--do-warn-inapt) ((slot-boundp obj 'transient) (pcase (list kind @@ -2422,7 +2447,7 @@ value. Otherwise return CHILDREN as is.") ;; 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)))) + (oset transient--prefix value (transient--get-extended-value)))) (transient--init-objects name layout params) (transient--init-keymaps)) @@ -2436,9 +2461,14 @@ 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 (and (not transient--refreshp) layout) - (transient--init-suffixes name))) - (setq transient--suffixes (transient--flatten-suffixes transient--layout))) + (cond ((and (not transient--refreshp) layout) + (setq transient--layout layout) + (setq transient--suffixes (transient--flatten-suffixes layout))) + (t + (setq transient--suffixes nil) + (setq transient--layout (transient--init-suffixes name)) + (setq transient--suffixes (nreverse transient--suffixes)))) + (slot-makeunbound transient--prefix 'value)) (defun transient--init-prefix (name &optional params) (let ((obj (let ((proto (get name 'transient--prefix))) @@ -2460,35 +2490,33 @@ value. Otherwise return CHILDREN as is.") (transient--get-children 'transient-common-commands)))))) (defun transient--flatten-suffixes (layout) - (cl-labels ((s (def) - (cond - ((stringp def) nil) - ((cl-typep def 'transient-information) nil) - ((listp def) (mapcan #'s def)) - ((cl-typep def 'transient-group) - (mapcan #'s (oref def suffixes))) - ((cl-typep def 'transient-suffix) - (list def))))) - (mapcan #'s layout))) + (named-let flatten ((def layout)) + (cond ((stringp def) nil) + ((cl-typep def 'transient-information) nil) + ((listp def) (mapcan #'flatten def)) + ((cl-typep def 'transient-group) + (mapcan #'flatten (oref def suffixes))) + ((cl-typep def 'transient-suffix) + (list def))))) (defun transient--init-child (levels spec parent) (cl-etypecase spec (symbol (mapcan (lambda (c) (transient--init-child levels c parent)) (transient--get-children spec))) - (vector (transient--init-group levels spec parent)) - (list (transient--init-suffix levels spec parent)) - (string (list spec)))) + (vector (transient--init-group levels spec parent)) + (list (transient--init-suffix levels spec parent)) + (string (list spec)))) (defun transient--init-group (levels spec parent) (pcase-let* ((`[,class ,args ,children] spec) (level (or (plist-get args :level) transient--default-child-level))) - (and-let* (((transient--use-level-p level)) + (and-let* ((_(transient--use-level-p level)) (obj (apply class :parent parent :level level args)) - ((transient--use-suffix-p obj)) - ((prog1 t - (when (transient--inapt-suffix-p obj) - (oset obj inapt t)))) + (_(transient--use-suffix-p obj)) + (_(prog1 t + (when (transient--inapt-suffix-p obj) + (oset obj inapt t)))) (suffixes (mapcan (lambda (c) (transient--init-child levels c obj)) (transient-setup-children obj children)))) (progn @@ -2496,44 +2524,50 @@ value. Otherwise return CHILDREN as is.") (list obj))))) (defun transient--init-suffix (levels spec parent) - (pcase-let* ((`(,class . ,args) spec) - (cmd (plist-get args :command)) - (_ (transient--load-command-if-autoload cmd)) - (key (plist-get args :key)) - (key (and key (kbd key))) - (proto (and cmd (transient--suffix-prototype cmd))) - (level (or (alist-get (cons cmd key) levels nil nil #'equal) - (alist-get cmd levels) - (plist-get args :level) - (and proto (oref proto level)) - transient--default-child-level))) - (when (transient--use-level-p level) - (let ((obj (if (child-of-class-p class 'transient-information) - (apply class :parent parent :level level args) + (let* ((class (car spec)) + (args (cdr spec)) + (cmd (plist-get args :command)) + (_ (transient--load-command-if-autoload cmd)) + (key (plist-get args :key)) + (key (and key (kbd key))) + (proto (and cmd (transient--suffix-prototype cmd))) + (level (or (alist-get (cons cmd key) levels nil nil #'equal) + (alist-get cmd levels) + (plist-get args :level) + (and proto (oref proto level)) + transient--default-child-level)) + (args (plist-put (copy-sequence args) :level level)) + (obj (if (child-of-class-p class 'transient-information) + (apply class :parent parent args) (unless (and cmd (symbolp cmd)) (error "BUG: Non-symbolic suffix command: %s" cmd)) (if proto - (apply #'clone proto :parent parent :level level args) - (apply class :command cmd :parent parent :level level - args))))) - (cond ((not cmd)) - ((commandp cmd)) - ((or (cl-typep obj 'transient-switch) - (cl-typep obj 'transient-option)) - ;; As a temporary special case, if the package was compiled - ;; with an older version of Transient, then we must define - ;; "anonymous" switch and option commands here. - (defalias cmd #'transient--default-infix-command)) - ((transient--use-suffix-p obj) - (error "Suffix command %s is not defined or autoloaded" cmd))) - (unless (cl-typep obj 'transient-information) - (transient--init-suffix-key obj)) - (when (transient--use-suffix-p obj) - (if (transient--inapt-suffix-p obj) - (oset obj inapt t) - (transient-init-scope obj) - (transient-init-value obj)) - (list obj)))))) + (apply #'clone proto :parent parent args) + (apply class :command cmd :parent parent args)))) + (active (and (transient--use-level-p level) + (transient--use-suffix-p obj))) + (inapt (and active (transient--inapt-suffix-p obj))) + (active (and active (not inapt)))) + (cond (inapt + (oset obj inapt t)) + ((not active) + (oset obj inactive t))) + (cond ((not cmd)) + ((commandp cmd)) + ((or (cl-typep obj 'transient-switch) + (cl-typep obj 'transient-option)) + ;; As a temporary special case, if the package was compiled + ;; with an older version of Transient, then we must define + ;; "anonymous" switch and option commands here. + (defalias cmd #'transient--default-infix-command)) + (active + (error "Suffix command %s is not defined or autoloaded" cmd))) + (cond ((not (cl-typep obj 'transient-information)) + (transient--init-suffix-key obj) + (transient-init-scope obj) + (transient-init-value obj) + (push obj transient--suffixes))) + (list obj))) (cl-defmethod transient--init-suffix-key ((obj transient-suffix)) (unless (slot-boundp obj 'key) @@ -2542,8 +2576,10 @@ 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) - (when-let* (((not (slot-boundp obj 'shortarg))) - (shortarg (transient--derive-shortarg (oref obj argument)))) + (when-let* ((_(not (slot-boundp obj 'shortarg))) + (argument (oref obj argument)) + (_(stringp argument)) + (shortarg (transient--derive-shortarg argument))) (oset obj shortarg shortarg)) (unless (slot-boundp obj 'key) (if (slot-boundp obj 'shortarg) @@ -2571,8 +2607,8 @@ value. Otherwise return CHILDREN as is.") t))) (defun transient--inapt-suffix-p (obj) - (or (and-let* ((parent (oref obj parent))) - (oref parent inapt)) + (or (and$ (oref obj parent) + (oref $ inapt)) (let ((transient--shadowed-buffer (current-buffer)) (transient--pending-suffix obj)) (transient--do-suffix-p @@ -2613,8 +2649,8 @@ value. Otherwise return CHILDREN as is.") (defun transient--suffix-predicate (spec) (let ((props (transient--suffix-props spec))) (seq-some (lambda (prop) - (and-let* ((pred (plist-get props prop))) - (list prop pred))) + (and$ (plist-get props prop) + (list prop $))) '( :if :if-not :if-nil :if-non-nil :if-mode :if-not-mode @@ -2625,9 +2661,9 @@ value. Otherwise return CHILDREN as is.") :inapt-if-derived :inapt-if-not-derived)))) (defun transient--load-command-if-autoload (cmd) - (when-let* (((symbolp cmd)) + (when-let* ((_(symbolp cmd)) (fn (symbol-function cmd)) - ((autoloadp fn))) + (_(autoloadp fn))) (transient--debug " autoload %s" cmd) (autoload-do-load fn))) @@ -2640,6 +2676,7 @@ value. Otherwise return CHILDREN as is.") (add-hook 'pre-command-hook #'transient--pre-command 99) (add-hook 'post-command-hook #'transient--post-command) (advice-add 'recursive-edit :around #'transient--recursive-edit) + (transient--quit-kludge 'enable) (when transient--exitp ;; This prefix command was invoked as the suffix of another. ;; Prevent `transient--post-command' from removing the hooks @@ -2671,8 +2708,7 @@ value. Otherwise return CHILDREN as is.") ((memq this-command '(transient-update transient-quit-seq)) (transient--pop-keymap 'transient--redisplay-map)) ((and transient--helpp - (not (memq this-command '(transient-quit-one - transient-quit-all)))) + (not (memq this-command transient--quit-commands))) (cond ((transient-help) (transient--do-suspend) @@ -2682,9 +2718,8 @@ value. Otherwise return CHILDREN as is.") (setq this-command 'transient-undefined)))) ((and transient--editp (transient-suffix-object) - (not (memq this-command '(transient-quit-one - transient-quit-all - transient-help)))) + (not (memq this-command + (cons 'transient-help transient--quit-commands)))) (setq this-command 'transient-set-level) (transient--wrap-command)) (t @@ -2692,6 +2727,7 @@ value. Otherwise return CHILDREN as is.") (let ((exitp (eq (transient--call-pre-command) transient--exit))) (transient--wrap-command) (when exitp + (transient--maybe-set-value 'exit) (transient--pre-exit))))))) (defun transient--pre-exit () @@ -2722,7 +2758,8 @@ value. Otherwise return CHILDREN as is.") (setq transient-current-prefix transient--prefix) (setq transient-current-command (oref transient--prefix command)) (setq transient-current-suffixes transient--suffixes) - (transient--history-push transient--prefix)) + (unless (transient--maybe-set-value 'export) + (transient--history-push transient--prefix))) (defun transient--suspend-override (&optional nohide) (transient--debug 'suspend-override) @@ -2750,10 +2787,8 @@ value. Otherwise return CHILDREN as is.") (defun transient--resume-override (&optional _ignore) (transient--debug 'resume-override) - (cond ((and transient--showp (not (window-live-p transient--window))) - (transient--show)) - ((window-live-p transient--window) - (transient--fit-window-to-buffer transient--window))) + (when (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) @@ -2987,6 +3022,7 @@ value. Otherwise return CHILDREN as is.") (setq transient--current-suffix nil)) (cond (resume (transient--stack-pop)) ((not replace) + (transient--quit-kludge 'disable) (run-hooks 'transient-post-exit-hook))))) (defun transient--stack-push () @@ -2994,7 +3030,7 @@ value. Otherwise return CHILDREN as is.") (push (list (oref transient--prefix command) transient--layout transient--editp - :value (transient-get-value) + :value (transient--get-extended-value) :return (oref transient--prefix return) :scope (oref transient--prefix scope)) transient--stack)) @@ -3066,15 +3102,38 @@ value. Otherwise return CHILDREN as is.") (defun transient--emergency-exit (&optional id) "Exit the current transient command after an error occurred. When no transient is active (i.e., when `transient--prefix' is -nil) then do nothing. Optional ID is a keyword identifying the -exit." +nil) then only reset `inhibit-quit'. Optional ID is a keyword +identifying the exit." (transient--debug 'emergency-exit id) + (transient--quit-kludge 'disable) (when transient--prefix (setq transient--stack nil) (setq transient--exitp t) (transient--pre-exit) (transient--post-exit this-command))) +(defun transient--quit-kludge (action) + (static-if (boundp 'redisplay-can-quit) ;Emacs 31 + action + (pcase-exhaustive action + ('enable + (add-function + :around command-error-function + (let (unreadp) + (lambda (orig data context fn) + (cond ((not (eq (car data) 'quit)) + (funcall orig data context fn) + (setq unreadp nil)) + (unreadp + (remove-function command-error-function "inhibit-quit") + (funcall orig data context fn)) + (t + (push ?\C-g unread-command-events) + (setq unreadp t))))) + '((name . "inhibit-quit")))) + ('disable + (remove-function command-error-function "inhibit-quit"))))) + ;;; Pre-Commands (defun transient--call-pre-command () @@ -3367,21 +3426,22 @@ transient is active." ;;;; Help -(defun transient-help (&optional interactive) +(defun transient-help (&optional interactivep) "Show help for the active transient or one of its suffixes. \n(fn)" (interactive (list t)) - (if interactive - (setq transient--helpp t) + (cond + (interactivep + (setq transient--helpp t)) + ((lookup-key transient--transient-map + (this-single-command-raw-keys)) + (setq transient--helpp nil) (with-demoted-errors "transient-help: %S" - (when (lookup-key transient--transient-map - (this-single-command-raw-keys)) - (setq transient--helpp nil) - (transient--display-help #'transient-show-help - (if (eq this-original-command 'transient-help) - transient--prefix - (or (transient-suffix-object) - this-original-command))))))) + (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. @@ -3448,19 +3508,16 @@ For example: (transient-undefined)))) (transient-define-suffix transient-toggle-level-limit () - "Toggle whether to temporarily displayed suffixes on all levels." + "Toggle whether to temporarily display suffixes on all levels." :description (lambda () (cond - ((= transient-default-level transient--max-level) - "Always displaying all levels") (transient--all-levels-p (format "Hide suffix %s" (propertize (format "levels > %s" (oref (transient-prefix-object) level)) 'face 'transient-higher-level))) ("Show all suffix levels"))) - :inapt-if (lambda () (= transient-default-level transient--max-level)) :transient t (interactive) (setq transient--all-levels-p (not transient--all-levels-p)) @@ -3571,14 +3628,15 @@ such as when suggesting a new feature or reporting an issue." :description "Echo arguments" :key "x" (interactive (list (transient-args transient-current-command))) - (message "%s: %s" - (key-description (this-command-keys)) - (mapconcat (lambda (arg) - (propertize (if (string-match-p " " arg) - (format "%S" arg) - arg) - 'face 'transient-argument)) - arguments " "))) + (if (seq-every-p #'stringp arguments) + (message "%s: %s" (key-description (this-command-keys)) + (mapconcat (lambda (arg) + (propertize (if (string-match-p " " arg) + (format "%S" arg) + arg) + 'face 'transient-argument)) + arguments " ")) + (message "%s: %S" (key-description (this-command-keys)) arguments))) ;;; Value ;;;; Init @@ -3861,21 +3919,21 @@ command-line option) or \": \". Finally fall through to using \"(BUG: no prompt): \" as the prompt." - (if-let ((prompt (oref obj prompt))) - (let ((prompt (if (functionp prompt) - (funcall prompt obj) - prompt))) - (if (stringp prompt) - prompt - "(BUG: no prompt): ")) - (or (and-let* ((arg (and (slot-boundp obj 'argument) (oref obj argument)))) - (if (and (stringp arg) (string-suffix-p "=" arg)) - arg - (concat arg ": "))) - (and-let* ((var (and (slot-boundp obj 'variable) (oref obj variable)))) - (and (stringp var) - (concat var ": "))) - "(BUG: no prompt): "))) + (cond-let + ([prompt (oref obj prompt)] + (let ((prompt (if (functionp prompt) + (funcall prompt obj) + prompt))) + (if (stringp prompt) + prompt + "[BUG: invalid prompt]: "))) + ([name (or (and (slot-boundp obj 'argument) (oref obj argument)) + (and (slot-boundp obj 'variable) (oref obj variable)))] + (if (and (stringp name) + (string-suffix-p "=" name)) + name + (format "%s: " name))) + ("[BUG: no prompt]: "))) ;;;; Set @@ -3888,7 +3946,7 @@ prompt." (cl-defmethod transient-infix-set :after ((obj transient-argument) value) "Unset incompatible infix arguments." - (when-let* ((value) + (when-let* ((_ value) (val (transient-infix-value obj)) (arg (if (slot-boundp obj 'argument) (oref obj argument) @@ -3902,15 +3960,15 @@ prompt." (and (not (equal val arg)) (mapcan (apply-partially filter val) spec))))) (dolist (obj transient--suffixes) - (when-let* (((cl-typep obj 'transient-argument)) + (when-let* ((_(cl-typep obj 'transient-argument)) (val (transient-infix-value obj)) (arg (if (slot-boundp obj 'argument) (oref obj argument) (oref obj argument-format))) - ((if (equal val arg) - (member arg incomp) - (or (member val incomp) - (member arg incomp))))) + (_(if (equal val arg) + (member arg incomp) + (or (member val incomp) + (member arg incomp))))) (transient-infix-set obj nil))))) (defun transient-prefix-set (value) @@ -3925,8 +3983,27 @@ Only intended for use by `transient-set'. See also `transient-prefix-set'.") (cl-defmethod transient-set-value ((obj transient-prefix)) - (oset (oref obj prototype) value (transient-get-value)) - (transient--history-push obj)) + (let ((value (transient--get-savable-value))) + (oset (oref obj prototype) value value) + (transient--history-push obj value))) + +(defun transient--maybe-set-value (event) + "Maybe set the value, subject to EVENT and the `remember-value' slot." + (let* ((event (if (and (eq event 'exit) + (memq this-command transient--quit-commands)) + 'quit + event)) + (spec (oref transient--prefix remember-value)) + (spec (cond ((listp spec) spec) + ((memq spec '(export exit quit)) + (list spec)) + ((boundp spec) + (symbol-value spec))))) + (and (memq event spec) + (prog1 t + (if (memq 'save spec) + (transient-save-value transient--prefix) + (transient-set-value transient--prefix)))))) ;;;; Save @@ -3934,11 +4011,11 @@ See also `transient-prefix-set'.") "Save the value of the transient prefix OBJ.") (cl-defmethod transient-save-value ((obj transient-prefix)) - (let ((value (transient-get-value))) + (let ((value (transient--get-savable-value))) (oset (oref obj prototype) value value) (setf (alist-get (oref obj command) transient-values) value) - (transient-save-values)) - (transient--history-push obj)) + (transient-save-values) + (transient--history-push obj value))) ;;;; Reset @@ -3950,8 +4027,8 @@ See also `transient-prefix-set'.") (oset obj value value) (oset (oref obj prototype) value value) (setf (alist-get (oref obj command) transient-values nil 'remove) nil) - (transient-save-values)) - (transient--history-push obj) + (transient-save-values) + (transient--history-push obj value)) (mapc #'transient-init-value transient--suffixes)) ;;;; Get @@ -3968,29 +4045,55 @@ 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." +returned value. + +This function is intended to be used by suffix commands, whether they +are invoked from a menu or not. It is not intended to be used when +setting up a menu and its suffixes, in which case `transient-get-value' +should be used." (when (listp prefix) (setq prefix (car (or (memq transient-current-command prefix) prefix)))) (if-let ((obj (get prefix 'transient--prefix))) + ;; This OBJ is only used for dispatch purposes; see below. (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'.") + "Return a list of the values of the suffixes of the specified prefix. + +OBJ is a prototype object and is only used to select the appropriate +method of this generic function. Transient itself only provides one +such method, which should be suitable for most prefixes. + +This function is only intended to be used by `transient-args'. It is +not defined as an internal function because third-party packages may +define their own methods. That does not mean that it would be a good +idea to call it for any other purpose.") (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 + "Return a list of the values of the suffixes of the specified prefix. + +OBJ is a prototype object. This method does not return the value of +that object. Instead it extracts the name of the respective command +from the object and uses that to collect the current values from the +suffixes of the prefix from which the current command was invoked. +If the current command was not invoked from the identified prefix, +then this method returns the set, save or default value, as described +for `transient-args'. + +This method uses `transient-suffixes' (which see) to determine the +suffix objects and then extracts the value(s) from those objects." + (mapcan (lambda (obj) + (and (not (oref obj inactive)) + (not (oref obj inapt)) + (transient--get-wrapped-value obj))) (transient-suffixes (oref obj command)))) (defun transient-suffixes (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." +they can be returned. That does not cause the menu to be displayed." (if (eq transient-current-command prefix) transient-current-suffixes (let ((transient--prefix (transient--init-prefix prefix))) @@ -3998,16 +4101,38 @@ they can be returned. Doing so doesn't have any side-effects." (transient--init-suffixes prefix))))) (defun transient-get-value () - "Return the value of the current prefix. + "Return the value of the extant 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." +This function is intended to be used when setting up a menu and its +suffixes. It is not intended to be used when a suffix command is +invoked, whether from a menu or not, in which case `transient-args' +should be used." (transient--with-emergency-exit :get-value (mapcan (lambda (obj) - (and (or (not (slot-exists-p obj 'unsavable)) - (not (oref obj unsavable))) + (and (not (oref obj inactive)) + (not (oref obj inapt)) + (transient--get-wrapped-value obj))) + transient--suffixes))) + +(defun transient--get-extended-value () + "Return the extended value of the extant prefix. + +Unlike `transient-get-value' also include the values of inactive and +inapt arguments. This function is mainly intended for internal use. +It is used to preserve the full value when a menu is being refreshed, +including the presently ineffective parts." + (transient--with-emergency-exit :get-value + (mapcan #'transient--get-wrapped-value transient--suffixes))) + +(defun transient--get-savable-value () + "Return the value of the extant prefix, excluding unsavable parts. + +This function is only intended for internal use. It is used to save +the value." + (transient--with-emergency-exit :get-savable-value + (mapcan (lambda (obj) + (and (not (and (slot-exists-p obj 'unsavable) + (oref obj unsavable))) (transient--get-wrapped-value obj))) (or transient--suffixes transient-current-suffixes)))) @@ -4015,7 +4140,7 @@ in `transient-set-value' and `transient-save-value' methods. Unlike "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 +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." @@ -4082,28 +4207,29 @@ a string, using the empty string for the empty value, or nil if 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) - (re (format "\\`%s\\(?:=\\(.+\\)\\)?\\'" - (substring arg 0 -1)))) - (cl-find-if (lambda (a) - (and (stringp a) - (string-match re a))) - args)))) - (or (match-string 1 match) ""))) - (and (member arg args) t))) + (save-match-data + (cond-let + ((member arg args) t) + ([_(string-suffix-p "=" arg)] + [match (let ((case-fold-search nil) + (re (format "\\`%s\\(?:=\\(.+\\)\\)?\\'" + (substring arg 0 -1)))) + (cl-find-if (lambda (a) + (and (stringp a) + (string-match re a))) + args))] + (match-string 1 match))))) ;;; Return (defun transient-init-return (obj) - (when-let* ((transient--stack) + (when-let* ((_ transient--stack) (command (oref obj command)) (suffix-obj (transient-suffix-object command)) - ((memq (if (slot-boundp suffix-obj 'transient) - (oref suffix-obj transient) - (oref transient-current-prefix transient-suffix)) - (list t 'recurse #'transient--do-recurse)))) + (_(memq (if (slot-boundp suffix-obj 'transient) + (oref suffix-obj transient) + (oref transient-current-prefix transient-suffix)) + (list t 'recurse #'transient--do-recurse)))) (oset obj return t))) ;;; Scope @@ -4162,21 +4288,23 @@ be non-nil. If either is non-nil, try the following in order: class definition or using its `transient-init-scope' method. If no prefix matches, return nil." - (if (or prefixes classes) - (let ((prefixes (ensure-list prefixes)) - (type (if (symbolp classes) classes (cons 'or classes)))) - (if-let ((obj (cl-flet ((match (obj) - (and obj - (or (memq (oref obj command) prefixes) - (cl-typep obj type)) - obj))) - (or (match transient-current-prefix) - (match transient--prefix))))) - (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)))) + (cond-let + ((or prefixes classes) + (let* ((prefixes (ensure-list prefixes)) + (type (if (symbolp classes) classes (cons 'or classes))) + (match (lambda (obj) + (and obj + (or (memq (oref obj command) prefixes) + (cl-typep obj type)) + obj)))) + (cond-let + ([obj (or (funcall match transient-current-prefix) + (funcall match transient--prefix))] + (oref obj scope)) + ((get (car prefixes) 'transient--prefix) + (oref (transient--init-prefix (car prefixes)) scope))))) + ([obj (transient-prefix-object)] + (oref obj scope)))) ;;; History @@ -4189,14 +4317,15 @@ 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'.") +(cl-defgeneric transient--history-push (obj value) + "Push VALUE to OBJ's entry in `transient-history'.") -(cl-defmethod transient--history-push ((obj transient-prefix)) +(cl-defmethod transient--history-push + ((obj transient-prefix) + &optional (value (transient--get-savable-value))) (let ((key (transient--history-key obj))) (setf (alist-get key transient-history) - (let ((args (transient-get-value))) - (cons args (delete args (alist-get key transient-history))))))) + (cons value (delete value (alist-get key transient-history)))))) (cl-defgeneric transient--history-init (obj) "Initialize OBJ's `history' slot. @@ -4205,8 +4334,8 @@ have a history of their own.") (cl-defmethod transient--history-init ((obj transient-prefix)) "Initialize OBJ's `history' slot from the variable `transient-history'." - (let ((val (oref obj value))) - (oset obj history + (oset obj history + (let ((val (transient--get-extended-value))) (cons val (delete val (alist-get (transient--history-key obj) transient-history)))))) @@ -4384,8 +4513,7 @@ have a history of their own.") (height (cond ((not window-system) nil) ((natnump format) format) ((eq format 'line) 1))) - (face `(,@(and (>= emacs-major-version 27) '(:extend t)) - :background ,(transient--prefix-color)))) + (face `(:background ,(transient--prefix-color) :extend t))) (concat (propertize "__" 'face face 'display `(space :height (,height))) (propertize "\n" 'face face 'line-height t)))) @@ -4412,6 +4540,12 @@ have a history of their own.") (when groups (insert ?\n))))) +(defun transient--active-suffixes (group) + (seq-remove (lambda (suffix) + (and (cl-typep suffix 'transient-suffix) + (oref suffix inactive))) + (oref group suffixes))) + (defvar transient--max-group-level 1) (cl-defgeneric transient--insert-group (group) @@ -4430,7 +4564,7 @@ have a history of their own.") (cl-defmethod transient--insert-group ((group transient-row)) (transient--maybe-pad-keys group) - (dolist (suffix (oref group suffixes)) + (dolist (suffix (transient--active-suffixes group)) (insert (transient-with-shadowed-buffer (transient-format suffix))) (insert " ")) (insert ?\n)) @@ -4438,7 +4572,7 @@ have a history of their own.") (cl-defmethod transient--insert-group ((group transient-column) &optional skip-empty) (transient--maybe-pad-keys group) - (dolist (suffix (oref group suffixes)) + (dolist (suffix (transient--active-suffixes group)) (let ((str (transient-with-shadowed-buffer (transient-format suffix)))) (unless (and (not skip-empty) (equal str "")) (insert str) @@ -4457,7 +4591,8 @@ have a history of their own.") `(,@(and-let* ((desc (transient-format-description column))) (list desc)) ,@(let ((transient--pending-group column)) - (mapcar #'transient-format (oref column suffixes)))))) + (mapcar #'transient-format + (transient--active-suffixes column)))))) (oref group suffixes))) (stops (transient--column-stops columns))) (dolist (row (apply #'transient--mapn #'list columns)) @@ -4609,7 +4744,7 @@ and its value is returned to the caller." (cl-defmethod transient-format-description ((obj transient-value-preset)) (pcase-let* (((eieio description key set) obj) - ((eieio value) transient--prefix) + (value (transient--get-extended-value)) (active (seq-set-equal-p set value))) (format "%s %s" @@ -4645,15 +4780,15 @@ apply the face `transient-unreachable' to the complete string." (and (slot-boundp transient--prefix 'suffix-description) (funcall (oref transient--prefix suffix-description) obj))))) - (when-let* ((transient--docsp) - ((slot-boundp obj 'command)) + (when-let* ((_ transient--docsp) + (_(slot-boundp obj 'command)) (cmd (oref obj command)) - ((not (memq 'transient--default-infix-command - (function-alias-p cmd)))) + (_(not (memq 'transient--default-infix-command + (function-alias-p cmd)))) (docstr (ignore-errors (documentation cmd))) (docstr (string-trim (substring docstr 0 (string-match "\\.?\n" docstr)))) - ((not (equal docstr "")))) + (_(not (equal docstr "")))) (setq desc (format-spec transient-show-docstring-format `((?c . ,desc) (?s . ,docstr))))) @@ -4661,9 +4796,9 @@ apply the face `transient-unreachable' to the complete string." (when-let ((face (transient--get-face obj 'face))) (setq desc (transient--add-face desc face t))) (setq desc (propertize "(BUG: no description)" 'face 'error))) - (when (if transient--all-levels-p - (> (oref obj level) transient--default-prefix-level) - (and transient-highlight-higher-levels + (when (cond (transient--all-levels-p + (> (oref obj level) transient--default-prefix-level)) + (transient-highlight-higher-levels (> (max (oref obj level) transient--max-group-level) transient--default-prefix-level))) (setq desc (transient--add-face desc 'transient-higher-level))) @@ -4681,28 +4816,33 @@ apply the face `transient-unreachable' to the complete string." (cl-defmethod transient-format-value ((obj transient-suffix)) (propertize (oref obj argument) 'face (if (oref obj value) - 'transient-argument + (if (oref obj inapt) + 'transient-inapt-argument + 'transient-argument) 'transient-inactive-argument))) (cl-defmethod transient-format-value ((obj transient-option)) - (let ((argument (oref obj argument))) + (let ((argument (prin1-to-string (oref obj argument) t))) (if-let ((value (oref obj value))) - (pcase-exhaustive (oref obj multi-value) - ('nil - (concat (propertize argument 'face 'transient-argument) - (propertize value 'face 'transient-value))) - ((or 't 'rest) - (concat (propertize (if (string-suffix-p " " argument) - argument - (concat argument " ")) - 'face 'transient-argument) - (propertize (mapconcat #'prin1-to-string value " ") - 'face 'transient-value))) - ('repeat - (mapconcat (lambda (value) - (concat (propertize argument 'face 'transient-argument) - (propertize value 'face 'transient-value))) - value " "))) + (let* ((inapt (oref obj inapt)) + (aface (if inapt 'transient-inapt-argument 'transient-argument)) + (vface (if inapt 'transient-inapt-argument 'transient-value))) + (pcase-exhaustive (oref obj multi-value) + ('nil + (concat (propertize argument 'face aface) + (propertize value 'face vface))) + ((or 't 'rest) + (concat (propertize (if (string-suffix-p " " argument) + argument + (concat argument " ")) + 'face aface) + (propertize (mapconcat #'prin1-to-string value " ") + 'face vface))) + ('repeat + (mapconcat (lambda (value) + (concat (propertize argument 'face aface) + (propertize value 'face vface))) + value " ")))) (propertize argument 'face 'transient-inactive-argument)))) (cl-defmethod transient-format-value ((obj transient-switches)) @@ -4717,29 +4857,30 @@ apply the face `transient-unreachable' to the complete string." (lambda (choice) (propertize choice 'face (if (equal (format argument-format choice) value) - 'transient-value + (if (oref obj inapt) + 'transient-inapt-argument + 'transient-value) 'transient-inactive-value))) choices (propertize "|" 'face 'transient-delimiter)))))) (cl-defmethod transient--get-description ((obj transient-child)) - (and-let* ((desc (oref obj description))) - (if (functionp desc) - (if (= (car (transient--func-arity desc)) 1) - (funcall desc obj) - (funcall desc)) - desc))) + (cond-let* [[desc (oref obj description)]] + ((functionp desc) + (condition-case nil + (funcall desc obj) + (wrong-number-of-arguments (funcall desc)))) + (desc))) (cl-defmethod transient--get-face ((obj transient-suffix) slot) - (and-let* (((slot-boundp obj slot)) - (face (slot-value obj slot))) - (if (and (not (facep face)) - (functionp face)) - (let ((transient--pending-suffix obj)) - (if (= (car (transient--func-arity face)) 1) - (funcall face obj) - (funcall face))) - face))) + (cond-let* ((not (slot-boundp obj slot)) nil) + [[face (slot-value obj slot)]] + ((facep face) face) + ((functionp face) + (let ((transient--pending-suffix obj)) + (condition-case nil + (funcall face obj) + (wrong-number-of-arguments (funcall face))))))) (defun transient--add-face (string face &optional append beg end) (let ((str (copy-sequence string))) @@ -4842,28 +4983,28 @@ if non-nil, else show the `man-page' if non-nil, else use Also used to dispatch showing documentation for the current prefix. If the suffix is a sub-prefix, then also call the prefix method." - (cond - ((eq this-command 'transient-help) - (transient-show-help transient--prefix)) - ((let ((prefix (get (oref obj command) - 'transient--prefix))) - (and prefix (not (eq (oref transient--prefix command) this-command)) - (prog1 t (transient-show-help prefix))))) - ((if-let ((show-help (oref obj show-help))) - (funcall show-help obj) - (transient--describe-function this-command))))) + (cond-let + ((eq this-command 'transient-help) + (transient-show-help transient--prefix)) + ([prefix (get (oref obj command) 'transient--prefix)] + [_(not (eq (oref transient--prefix command) this-command))] + (transient-show-help prefix)) + ([show-help (oref obj show-help)] + (funcall show-help obj)) + ((transient--describe-function this-command)))) (cl-defmethod transient-show-help ((obj transient-infix)) "Call `show-help' if non-nil, else show the `man-page' if non-nil, else use `describe-function'. When showing the manpage, then try to jump to the correct location." - (if-let ((show-help (oref obj show-help))) - (funcall show-help obj) - (if-let ((man-page (oref transient--prefix man-page)) - (argument (and (slot-boundp obj 'argument) - (oref obj argument)))) - (transient--show-manpage man-page argument) - (transient--describe-function this-command)))) + (cond-let + ([show-help (oref obj show-help)] + (funcall show-help obj)) + ([man-page (oref transient--prefix man-page)] + [argument (and (slot-boundp obj 'argument) + (oref obj argument))] + (transient--show-manpage man-page argument)) + ((transient--describe-function this-command)))) ;; `cl-generic-generalizers' doesn't support `command' et al. (cl-defmethod transient-show-help (cmd) @@ -5028,11 +5169,11 @@ This is used when a tooltip is needed.") (summary) ((documentation command) (car (split-string (documentation command) "\n"))))) - ((stringp doc)) - ((not (equal doc - (car (split-string (documentation - 'transient--default-infix-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 @@ -5091,7 +5232,9 @@ See `forward-button' for information about N." (when (re-search-forward (concat "^" (regexp-quote command)) nil t) (goto-char (match-beginning 0)))) (command - (cl-flet ((found () (eq (button-get (button-at (point)) 'command) command))) + (cl-flet ((found () + (and$ (button-at (point)) + (eq (button-get $ 'command) command)))) (while (and (ignore-errors (forward-button 1)) (not (found)))) (unless (found) @@ -5112,6 +5255,7 @@ See `forward-button' for information about N." (defvar-keymap transient--isearch-mode-map :parent isearch-mode-map + "" #'transient-isearch-exit " " #'transient-isearch-exit " " #'transient-isearch-cancel " " #'transient-isearch-abort) @@ -5221,7 +5365,7 @@ that binding back, then call this function in your init file like so: Individual transients may already bind \\`q' to something else and such a binding would shadow the quit binding. If that is the case then \\`Q' is bound to whatever \\`q' would have been bound -to by setting `transient-substitute-key-function' to a function +to, by setting `transient-substitute-key-function' to a function that does that. Of course \\`Q' may already be bound to something else, so that function binds \\`M-q' to that command instead. Of course \\`M-q' may already be bound to something else, but @@ -5243,9 +5387,6 @@ we stop there." (face-remap-reset-base 'default) (face-remap-add-relative 'default 'fixed-pitch)) -(defun transient--func-arity (fn) - (func-arity (advice--cd*r (if (symbolp fn) (symbol-function fn) fn)))) - (defun transient--seq-reductions-from (function sequence initial-value) (let ((acc (list initial-value))) (seq-doseq (elt sequence) @@ -5315,9 +5456,39 @@ as stand-in for elements of exhausted lists." (defun transient-lisp-variable--reader (prompt initial-input _history) (read--expression prompt initial-input)) +;;;; `transient-cons-option' + +(defclass transient-cons-option (transient-option) + ((format :initform " %k %d: %v")) + "[Experimental] Class used for unencoded key-value pairs.") + +(cl-defmethod transient-infix-value ((obj transient-cons-option)) + "Return ARGUMENT and VALUE as a cons-cell or nil if the latter is nil." + (and$ (oref obj value) + (cons (oref obj argument) $))) + +(cl-defmethod transient-format-description ((obj transient-cons-option)) + (or (oref obj description) + (let ((description (prin1-to-string (oref obj argument) t))) + (if (string-prefix-p ":" description) + (substring description 1) + description)))) + +(cl-defmethod transient-format-value ((obj transient-cons-option)) + (let ((value (oref obj value))) + (propertize (prin1-to-string value t) 'face + (if value 'transient-value 'transient-inactive-value)))) + ;;; _ (provide 'transient) ;; Local Variables: +;; read-symbol-shorthands: ( +;; ("and$" . "cond-let--and$") +;; ("and-let" . "cond-let--and-let") +;; ("if-let" . "cond-let--if-let") +;; ("when$" . "cond-let--when$") +;; ("when-let" . "cond-let--when-let") +;; ("while-let" . "cond-let--while-let")) ;; indent-tabs-mode: nil ;; checkdoc-symbol-words: ("command-line" "edit-mode" "help-mode") ;; End: diff --git a/elpa/transient-20250520.1040/transient.info b/elpa/transient-20251215.2209/transient.info similarity index 95% rename from elpa/transient-20250520.1040/transient.info rename to elpa/transient-20251215.2209/transient.info index 3d3c4c7b..a06ce052 100644 --- a/elpa/transient-20250520.1040/transient.info +++ b/elpa/transient-20251215.2209/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.8.8. +This manual is for Transient version 0.11.0. Copyright (C) 2018–2025 Free Software Foundation, Inc. @@ -806,6 +806,9 @@ Auxiliary Options not match the respective command-line argument should be highlighted. For other infix commands this option has no effect. + This is mostly indended for autors of transient menus and disabled + by default. + When this option is non-‘nil’, the key binding for an infix argument is highlighted when only a long argument (e.g., ‘--verbose’) is specified but no shorthand (e.g., ‘-v’). In the @@ -962,13 +965,13 @@ after the infix argument that is bound to ‘-3’ in ‘magit-patch-apply’. These functions operate on the information stored in the ‘transient--layout’ property of the PREFIX symbol. Elements in that -tree are not objects but have the form ‘(CLASS PLIST) for suffixes’ and -[CLASS PLIST CHILDREN] for groups. At the root of the tree is an -element [N nil CHILDREN], where N is the version of the layout format, -currently and hopefully for a long time 2. While that element looks -like a group vector, that element does not count when identifying a -group using a coordinate vector, i.e., [0] is its first child, not the -root element itself. +tree are not objects but have the form ‘(CLASS PLIST)’ for suffixes and +‘[CLASS PLIST CHILDREN]’ for groups. At the root of the tree is an +element ‘[N nil CHILDREN]’, where ‘N’ is the version of the layout +format, currently and hopefully for a long time 2. While that element +looks like a group vector, that element does not count when identifying +a group using a coordinate vector, i.e., ‘[0]’ is its first child, not +the root element itself. -- Function: transient-insert-suffix prefix loc suffix &optional keep-other @@ -1577,13 +1580,26 @@ same purpose as ‘prefix-arg’ serves for prefix arguments. current command was not invoked from PREFIX, then it returns 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. + + This function is intended to be used by suffix commands, whether + they are invoked from a menu or not. It is not intended to be used + when setting up a menu and its suffixes, in which case + ‘transient-get-value’ should be used. + -- Function: transient-get-value - This function returns the value of the current prefix. + This function returns the value of the erant 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’. + This function is intended to be used when setting up a menu and its + suffixes. It is not intended to be used when a suffix command is + invoked, whether from a menu or not, in which case ‘transient-args’ + should be used. In other words, use this, e.g., in a suffixes + ‘:if*’ or ‘:inapt-if*’ predicate and ‘:description’ function, but + never in its ‘interactive’ form or function body. -- Function: transient-arg-value arg args This function returns the value of ARG as it appears in ARGS. @@ -1612,18 +1628,18 @@ its value can be accessed using ‘transient-args’. This function returns the scope of the active or current transient prefix command. - If optional PREFIXES and CLASSES are both nil, return the scope of - the prefix currently being setup, making this variation useful, + If optional PREFIXES and CLASSES are both ‘nil’, return the scope + of the prefix currently being setup, making this variation 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. - If PREFIXES is non-nil, it must be a prefix command or a list of - such commands. If CLASSES is non-nil, it must be a prefix class or - a list of such classes. When this function is called from the body - or the ‘interactive’ form of a suffix command, PREFIXES and/or - CLASSES should be non-nil. If either is non-nil, try the following - in order: + If PREFIXES is non-‘nil’, it must be a prefix command or a list of + such commands. If CLASSES is non-‘nil’, it must be a prefix class + or a list of such classes. When this function is called from the + body or the ‘interactive’ form of a suffix command, PREFIXES and/or + CLASSES should be non-‘nil’. If either is non-‘nil’, try the + following in order: • If the current suffix command was invoked from a prefix, which appears in PREFIXES, return the scope of that prefix. @@ -1643,7 +1659,7 @@ its value can be accessed using ‘transient-args’. respective class definition or using its ‘transient-init-scope’ method. - If no prefix matches, return nil. + If no prefix matches, return ‘nil’.  File: transient.info, Node: Current Suffix Command, Next: Current Prefix Command, Prev: Using Prefix Scope, Up: Defining New Commands @@ -2161,8 +2177,8 @@ File: transient.info, Node: Suffix Classes, Next: Prefix Methods, Prev: Prefi that anywhere a suffix can appear. Display-only suffix specifications take these form: - ([LEVEL] :info DESCRIPTION [KEYWORD VALUE]...) - ([LEVEL] :info* DESCRIPTION [KEYWORD VALUE]...) + (:info DESCRIPTION [KEYWORD VALUE]...) + (:info* DESCRIPTION [KEYWORD VALUE]...) The ‘:info’ and ‘:info*’ keyword arguments replaces the ‘:description’ keyword used for other suffix classes. Other @@ -2182,6 +2198,23 @@ File: transient.info, Node: Suffix Classes, Next: Prefix Methods, Prev: Prefi and it is somewhat likely that future improvements won’t be fully backward compatible. + • The ‘transient-cons-option’ class is intended for situations where + ‘transient-args’ should return an alist, instead of a list of + strings (arguments). Such suffixes can be specified in prefix + definitions like so: + + (:cons OPTION :key KEY [KEYWORD VALUE]...) + + OPTION may be something other than a string, likely a keyword or + some other symbol, it is used as the ‘car’ of the cons-cell. When + using such an inline definition ‘:key’ has to be specified. In + most cases ‘:reader’ should also be specified. When defining such + a suffix separately, the "alist key" has to be specified using the + ‘:variable’ keyword argument. + + This class is still experimental 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’. @@ -2227,6 +2260,21 @@ functions use ‘describe-function’. -- Function: transient-prefix-value obj This generic function returns the value of the prefix object OBJ. + + OBJ is a prototype object and is only used to select the + appropriate method of this generic function. This function does + not return the value of that object. Instead it extracts the name + of the respective command from the object and uses that to collect + the current values from the suffixes of the prefix from which the + current command was invoked. If the current command was not + invoked from the identified prefix, then this method returns the + set, save or default value, as described for ‘transient-args’. + + This function is only intended to be used by ‘transient-args’. It + is not defined as an internal function because third-party packages + may define their own methods. That does not mean that it would be + a good idea to call it for any other purpose. + The respective generic function for infix and suffix objects is named ‘transient-infix-value’. @@ -2421,6 +2469,40 @@ Value and Scope value, then this slot has to be set to the same value for all of them. You probably don’t want that. + • ‘remember-value’ When a suffix command is invoked, which can + consume the prefix’s value (which depends on the suffix slot + ‘transient’ and the prefix slots ‘transient-suffix’ and + ‘transient-non-suffix’), then the value is automatically pushed to + the prefix’s value history. + + This slot allows additionally setting or even saving the value, so + that it becomes the initial value when the menu is invoked again. + + Beside ‘nil’, the value can be one of these symbols: + + • ‘export’ Set the value when it is exported. That is the time + when the value would ordinarily just be pushed to the history + stack. + + • ‘exit’ Set the value when the menu is exited, except when that + is done using a command whose sole purpose is to quit the + menu. + + • ‘quit’ Set the value when the menu is quit, using a command + whose sole purpose is to do so. + + The value can also be a list of one or more of these symbols and + optionally also the symbol ‘save’. + + • ‘save’ Instead of merely setting the value, save it, so that + it will be used in future Emacs sessions. At least one other + symbol has to be used together with this. + + The value can also be a (quoted) variable, whose value is a list of + symbols as described above. Ideally an option should be used, + since not all users will find the automatic saving of the value + desirable. + • ‘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 @@ -2597,7 +2679,7 @@ Slots of ‘transient-suffix’ The following two slots are experimental. They can also be set for a group, in which case they apply to all suffixes in that group, except -for suffixes that set the same slot to a non-nil value. +for suffixes that set the same slot to a non-‘nil’ value. • ‘advice’ A function used to advise the command. The advise is called using ‘(apply advice command args)’, i.e., it behaves like @@ -2605,9 +2687,9 @@ for suffixes that set the same slot to a non-nil value. • ‘advice*’ A function used to advise the command. Unlike ‘advice’, this advises not only the command body but also its ‘interactive’ - spec. If both slots are non-nil, ‘advice’ is used for the body and - ‘advice*’ is used for the ‘interactive’ form. When advising the - ‘interactive’ spec, called using ‘(funcall advice + spec. If both slots are non-‘nil’, ‘advice’ is used for the body + and ‘advice*’ is used for the ‘interactive’ form. When advising + the ‘interactive’ spec, called using ‘(funcall advice #'advice-eval-interactive-spec spec)’. Slots of ‘transient-infix’ @@ -2773,6 +2855,12 @@ transient menu, you will be able to yank it in another buffer. "" #'transient--do-stay) + Copying the region while not seeing the region is a bit fiddly, so a +dedicated command, ‘transient-copy-menu-text’, was added. You have to +add a binding for this command in ‘transient-map’. + + (keymap-set transient-map "C-c C-w" #'transient-copy-menu-text) + A.3 How can I autoload prefix and suffix commands? ================================================== @@ -2880,7 +2968,7 @@ Appendix C Command and Function Index * transient-append-suffix: Modifying Existing Transients. (line 63) * transient-arg-value: Using Infix Arguments. - (line 39) + (line 52) * transient-args: Using Infix Arguments. (line 22) * transient-copy-menu-text: Other Commands. (line 25) @@ -2901,7 +2989,7 @@ Appendix C Command and Function Index * transient-get-suffix: Modifying Existing Transients. (line 88) * transient-get-value: Using Infix Arguments. - (line 31) + (line 42) * transient-help: Getting Help for Suffix Commands. (line 11) * transient-history-next: Using History. (line 22) @@ -2909,7 +2997,7 @@ Appendix C Command and Function Index * transient-infix-read: Suffix Methods. (line 34) * transient-infix-set: Suffix Methods. (line 54) * transient-infix-value: Suffix Methods. (line 57) -* transient-init-scope: Prefix Methods. (line 37) +* transient-init-scope: Prefix Methods. (line 52) * transient-init-scope <1>: Suffix Methods. (line 70) * transient-init-value: Prefix Methods. (line 9) * transient-init-value <1>: Suffix Methods. (line 12) @@ -2951,7 +3039,7 @@ Appendix C Command and Function Index * transient-suffix-put: Modifying Existing Transients. (line 92) * transient-suffixes: Using Infix Arguments. - (line 46) + (line 59) * transient-suspend: Aborting and Resuming Transients. (line 41) * transient-toggle-common: Common Suffix Commands. @@ -2970,7 +3058,7 @@ Appendix D Variable Index [index] * Menu: -* transient-align-variable-pitch: Configuration. (line 235) +* transient-align-variable-pitch: Configuration. (line 238) * transient-common-command-prefix: Common Suffix Commands. (line 23) * transient-current-command: Current Prefix Command. @@ -2981,30 +3069,30 @@ Appendix D Variable Index (line 45) * transient-default-level: Enabling and Disabling Suffixes. (line 33) -* transient-detect-key-conflicts: Configuration. (line 260) +* transient-detect-key-conflicts: Configuration. (line 263) * transient-display-buffer-action: Configuration. (line 103) * transient-enable-popup-navigation: Configuration. (line 81) -* transient-error-on-insert-failure: Configuration. (line 273) -* transient-exit-hook: Configuration. (line 292) -* transient-force-fixed-pitch: Configuration. (line 248) +* transient-error-on-insert-failure: Configuration. (line 276) +* transient-exit-hook: Configuration. (line 295) +* transient-force-fixed-pitch: Configuration. (line 251) * transient-force-single-column: Configuration. (line 151) -* transient-highlight-higher-levels: Configuration. (line 279) +* transient-highlight-higher-levels: Configuration. (line 282) * transient-highlight-mismatched-keys: Configuration. (line 196) * transient-history-file: Using History. (line 41) * transient-history-limit: Using History. (line 45) * transient-levels-file: Enabling and Disabling Suffixes. (line 38) * transient-mode-line-format: Configuration. (line 160) -* transient-post-exit-hook: Configuration. (line 296) +* transient-post-exit-hook: Configuration. (line 299) * transient-read-with-initial-input: Configuration. (line 74) * transient-save-history: Using History. (line 37) * transient-semantic-coloring: Configuration. (line 187) -* transient-setup-buffer-hook: Configuration. (line 300) +* transient-setup-buffer-hook: Configuration. (line 303) * transient-show-common-commands: Common Suffix Commands. (line 11) * transient-show-during-minibuffer-read: Configuration. (line 37) * transient-show-popup: Configuration. (line 16) -* transient-substitute-key-function: Configuration. (line 214) +* transient-substitute-key-function: Configuration. (line 217) * transient-values-file: Saving Values. (line 36)  @@ -3773,77 +3861,77 @@ please read .  Tag Table: Node: Top763 -Node: Introduction2915 -Ref: Some things that Transient can do3443 -Ref: Complexity in CLI programs3796 -Ref: Using Transient for composing interactive commands4397 -Node: Usage6639 -Node: Invoking Transients7007 -Node: Aborting and Resuming Transients8199 -Node: Common Suffix Commands10819 -Node: Saving Values13762 -Ref: Saving Values-Footnote-115336 -Node: Using History15529 -Node: Getting Help for Suffix Commands17405 -Node: Enabling and Disabling Suffixes18783 -Node: Other Commands24149 -Node: Configuration25833 -Ref: Essential Options26113 -Ref: Accessibility Options32655 -Ref: Auxiliary Options32978 -Ref: Developer Options37542 -Ref: Hook Variables39069 -Node: Modifying Existing Transients39597 -Node: Defining New Commands45454 -Node: Technical Introduction45894 -Node: Defining Transients51603 -Node: Binding Suffix and Infix Commands54956 -Ref: Group Specifications55753 -Ref: Suffix Specifications62566 -Node: Defining Suffix and Infix Commands67480 -Node: Using Infix Arguments70528 -Node: Using Prefix Scope72917 -Node: Current Suffix Command74923 -Node: Current Prefix Command77280 -Node: Transient State79836 -Ref: Pre-commands for Infixes84187 -Ref: Pre-commands for Suffixes84707 -Ref: Pre-commands for Non-Suffixes87160 -Ref: Special Pre-Commands88296 -Node: Classes and Methods88804 -Node: Group Classes90891 -Node: Group Methods92818 -Node: Prefix Classes94077 -Node: Suffix Classes94922 -Node: Prefix Methods98902 -Node: Suffix Methods101295 -Ref: Suffix Value Methods101555 -Ref: Suffix Format Methods104800 -Node: Prefix Slots107698 -Ref: Value and Scope107848 -Ref: Behavior109327 -Ref: Appearance110668 -Ref: Documentation111354 -Ref: Internal111974 -Node: Suffix Slots113329 -Ref: Slots of transient-child113697 -Ref: Slots of transient-suffix114155 -Ref: Slots of transient-infix117008 -Ref: Slots of transient-variable120304 -Ref: Slots of transient-switches120406 -Node: Predicate Slots120769 -Node: FAQ123114 -Ref: Can I control how the menu buffer is displayed?123243 -Ref: How can I copy text from the menu buffer?123567 -Ref: How can I autoload prefix and suffix commands?124057 -Ref: How does Transient compare to prefix keys and universal arguments?124531 -Ref: How does Transient compare to Magit-Popup and Hydra?124774 -Ref: Why does q not quit popups anymore?124968 -Node: Keystroke Index126071 -Node: Command and Function Index127936 -Node: Variable Index135403 -Node: Concept Index138182 -Node: GNU General Public License141006 +Node: Introduction2916 +Ref: Some things that Transient can do3444 +Ref: Complexity in CLI programs3797 +Ref: Using Transient for composing interactive commands4398 +Node: Usage6640 +Node: Invoking Transients7008 +Node: Aborting and Resuming Transients8200 +Node: Common Suffix Commands10820 +Node: Saving Values13763 +Ref: Saving Values-Footnote-115337 +Node: Using History15530 +Node: Getting Help for Suffix Commands17406 +Node: Enabling and Disabling Suffixes18784 +Node: Other Commands24150 +Node: Configuration25834 +Ref: Essential Options26114 +Ref: Accessibility Options32656 +Ref: Auxiliary Options32979 +Ref: Developer Options37633 +Ref: Hook Variables39160 +Node: Modifying Existing Transients39688 +Node: Defining New Commands45569 +Node: Technical Introduction46009 +Node: Defining Transients51718 +Node: Binding Suffix and Infix Commands55071 +Ref: Group Specifications55868 +Ref: Suffix Specifications62681 +Node: Defining Suffix and Infix Commands67595 +Node: Using Infix Arguments70643 +Node: Using Prefix Scope73674 +Node: Current Suffix Command75716 +Node: Current Prefix Command78073 +Node: Transient State80629 +Ref: Pre-commands for Infixes84980 +Ref: Pre-commands for Suffixes85500 +Ref: Pre-commands for Non-Suffixes87953 +Ref: Special Pre-Commands89089 +Node: Classes and Methods89597 +Node: Group Classes91684 +Node: Group Methods93611 +Node: Prefix Classes94870 +Node: Suffix Classes95715 +Node: Prefix Methods100513 +Node: Suffix Methods103736 +Ref: Suffix Value Methods103996 +Ref: Suffix Format Methods107241 +Node: Prefix Slots110139 +Ref: Value and Scope110289 +Ref: Behavior113291 +Ref: Appearance114632 +Ref: Documentation115318 +Ref: Internal115938 +Node: Suffix Slots117293 +Ref: Slots of transient-child117661 +Ref: Slots of transient-suffix118119 +Ref: Slots of transient-infix120984 +Ref: Slots of transient-variable124280 +Ref: Slots of transient-switches124382 +Node: Predicate Slots124745 +Node: FAQ127090 +Ref: Can I control how the menu buffer is displayed?127219 +Ref: How can I copy text from the menu buffer?127543 +Ref: How can I autoload prefix and suffix commands?128306 +Ref: How does Transient compare to prefix keys and universal arguments?128780 +Ref: How does Transient compare to Magit-Popup and Hydra?129023 +Ref: Why does q not quit popups anymore?129217 +Node: Keystroke Index130320 +Node: Command and Function Index132185 +Node: Variable Index139652 +Node: Concept Index142431 +Node: GNU General Public License145255  End Tag Table -- 2.47.3