update packages
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
;;; transient.el --- Transient commands -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2018-2021 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
|
||||
;; Homepage: https://github.com/magit/transient
|
||||
;; Package-Requires: ((emacs "25.1"))
|
||||
;; Package-Version: 0
|
||||
;; Keywords: bindings
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
@@ -56,6 +57,14 @@
|
||||
(eval-when-compile
|
||||
(require 'subr-x))
|
||||
|
||||
(and (require 'async-bytecomp nil t)
|
||||
(let ((pkgs (bound-and-true-p async-bytecomp-allowed-packages)))
|
||||
(if (consp pkgs)
|
||||
(cl-intersection '(all magit transient) pkgs)
|
||||
(memq pkgs '(all t))))
|
||||
(fboundp 'async-bytecomp-package-mode)
|
||||
(async-bytecomp-package-mode 1))
|
||||
|
||||
(declare-function info 'info)
|
||||
(declare-function Man-find-section 'man)
|
||||
(declare-function Man-next-section 'man)
|
||||
@@ -81,6 +90,19 @@
|
||||
(define-obsolete-variable-alias 'post-transient-hook
|
||||
'transient-exit-hook "Transient 0.3.0")
|
||||
|
||||
(defmacro transient--with-emergency-exit (&rest body)
|
||||
(declare (indent defun))
|
||||
`(condition-case err
|
||||
(let ((debugger #'transient--exit-and-debug))
|
||||
,(macroexp-progn body))
|
||||
((debug error)
|
||||
(transient--emergency-exit)
|
||||
(signal (car err) (cdr err)))))
|
||||
|
||||
(defun transient--exit-and-debug (&rest args)
|
||||
(transient--emergency-exit)
|
||||
(apply #'debug args))
|
||||
|
||||
;;; Options
|
||||
|
||||
(defgroup transient nil
|
||||
@@ -269,7 +291,7 @@ used."
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom transient-force-fixed-pitch nil
|
||||
"Whether to force used of monospaced font in popup buffer.
|
||||
"Whether to force use of monospaced font in the popup buffer.
|
||||
|
||||
Even if you use a proportional font for the `default' face,
|
||||
you might still want to use a monospaced font in transient's
|
||||
@@ -466,13 +488,13 @@ These faces are only used if `transient-semantic-coloring'
|
||||
(insert-file-contents file)
|
||||
(read (current-buffer))))))
|
||||
|
||||
(defun transient--pp-to-file (object file)
|
||||
(defun transient--pp-to-file (list file)
|
||||
(make-directory (file-name-directory file) t)
|
||||
(setq object (cl-sort object #'string< :key #'car))
|
||||
(setq list (cl-sort (copy-sequence list) #'string< :key #'car))
|
||||
(with-temp-file file
|
||||
(let ((print-level nil)
|
||||
(print-length nil))
|
||||
(pp object (current-buffer)))))
|
||||
(pp list (current-buffer)))))
|
||||
|
||||
(defvar transient-values
|
||||
(transient--read-file-contents transient-values-file)
|
||||
@@ -525,6 +547,7 @@ If `transient-save-history' is nil, then do nothing."
|
||||
(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)
|
||||
(history :initarg :history :initform nil)
|
||||
@@ -534,7 +557,8 @@ If `transient-save-history' is nil, then do nothing."
|
||||
(info-manual :initarg :info-manual :initform nil)
|
||||
(transient-suffix :initarg :transient-suffix :initform nil)
|
||||
(transient-non-suffix :initarg :transient-non-suffix :initform nil)
|
||||
(incompatible :initarg :incompatible :initform nil))
|
||||
(incompatible :initarg :incompatible :initform nil)
|
||||
(suffix-description :initarg :suffix-description :initform nil))
|
||||
"Transient prefix command.
|
||||
|
||||
Each transient prefix command consists of a command, which is
|
||||
@@ -636,7 +660,10 @@ slot is non-nil."
|
||||
(argument :initarg :argument)
|
||||
(shortarg :initarg :shortarg)
|
||||
(value :initform nil)
|
||||
(init-value :initarg :init-value)
|
||||
(unsavable :initarg :unsavable :initform nil)
|
||||
(multi-value :initarg :multi-value :initform nil)
|
||||
(always-read :initarg :always-read :initform nil)
|
||||
(allow-empty :initarg :allow-empty :initform nil)
|
||||
(history-key :initarg :history-key :initform nil)
|
||||
(reader :initarg :reader :initform nil)
|
||||
@@ -675,9 +702,11 @@ They become the value of this this argument.")
|
||||
;;;; Group
|
||||
|
||||
(defclass transient-group (transient-child)
|
||||
((suffixes :initarg :suffixes :initform nil)
|
||||
(hide :initarg :hide :initform nil)
|
||||
(description :initarg :description :initform nil))
|
||||
((suffixes :initarg :suffixes :initform nil)
|
||||
(hide :initarg :hide :initform nil)
|
||||
(description :initarg :description :initform nil)
|
||||
(setup-children :initarg :setup-children)
|
||||
(pad-keys :initarg :pad-keys))
|
||||
"Abstract superclass of all group classes."
|
||||
:abstract t)
|
||||
|
||||
@@ -869,7 +898,9 @@ example, sets a variable use `transient-define-infix' instead.
|
||||
(setq class v)
|
||||
(push k keys)
|
||||
(push v keys))))
|
||||
(while (vectorp (car args))
|
||||
(while (let ((arg (car args)))
|
||||
(or (vectorp arg)
|
||||
(and arg (symbolp arg))))
|
||||
(push (pop args) suffixes))
|
||||
(list (if (eq (car-safe class) 'quote)
|
||||
(cadr class)
|
||||
@@ -881,6 +912,12 @@ example, sets a variable use `transient-define-infix' instead.
|
||||
|
||||
(defun transient--parse-child (prefix spec)
|
||||
(cl-etypecase spec
|
||||
(symbol (let ((value (symbol-value spec)))
|
||||
(if (and (listp value)
|
||||
(or (listp (car value))
|
||||
(vectorp (car value))))
|
||||
(cl-mapcan (lambda (s) (transient--parse-child prefix s)) value)
|
||||
(transient--parse-child prefix value))))
|
||||
(vector (when-let ((c (transient--parse-group prefix spec))) (list c)))
|
||||
(list (when-let ((c (transient--parse-suffix prefix spec))) (list c)))
|
||||
(string (list spec))))
|
||||
@@ -929,6 +966,15 @@ example, sets a variable use `transient-define-infix' instead.
|
||||
(error "Need command, got %S" car))
|
||||
((symbolp car)
|
||||
(setq args (plist-put args :command pop)))
|
||||
((and (commandp car)
|
||||
(not (stringp car)))
|
||||
(let ((cmd pop)
|
||||
(sym (intern (format "transient:%s:%s"
|
||||
prefix
|
||||
(or (plist-get args :description)
|
||||
(plist-get args :key))))))
|
||||
(defalias sym cmd)
|
||||
(setq args (plist-put args :command sym))))
|
||||
((or (stringp car)
|
||||
(and car (listp car)))
|
||||
(let ((arg pop))
|
||||
@@ -950,8 +996,7 @@ example, sets a variable use `transient-define-infix' instead.
|
||||
((not (string-suffix-p "=" arg))
|
||||
(setq class 'transient-switch))
|
||||
(t
|
||||
(setq class 'transient-option)
|
||||
(setq args (plist-put args :reader 'read-string))))))
|
||||
(setq class 'transient-option)))))
|
||||
(t
|
||||
(error "Needed command or argument, got %S" car)))
|
||||
(while (keywordp car)
|
||||
@@ -1013,10 +1058,22 @@ example, sets a variable use `transient-define-infix' instead.
|
||||
(t
|
||||
(when (and (listp suffix)
|
||||
(listp elt))
|
||||
;; Both suffixes are key bindings; not heading strings.
|
||||
(let ((key (transient--spec-key suf)))
|
||||
(if (equal (transient--kbd key)
|
||||
(transient--kbd (transient--spec-key elt)))
|
||||
(setq action 'replace)
|
||||
;; We must keep `mem' until after we have inserted
|
||||
;; behind it, which `transient-remove-suffix' does
|
||||
;; not allow us to do.
|
||||
(let ((spred (transient--suffix-predicate suf))
|
||||
(epred (transient--suffix-predicate elt)))
|
||||
;; If both suffixes have a predicate and they
|
||||
;; are not identical, then the probability is
|
||||
;; high that we want to keep both.
|
||||
(when (or (not spred)
|
||||
(not epred)
|
||||
(equal spred epred))
|
||||
(setq action 'replace)))
|
||||
(transient-remove-suffix prefix key))))
|
||||
(cl-ecase action
|
||||
(insert (setcdr mem (cons elt (cdr mem)))
|
||||
@@ -1277,11 +1334,13 @@ probably use this instead:
|
||||
(get COMMAND 'transient--suffix)"
|
||||
(when command
|
||||
(cl-check-type command command))
|
||||
(if transient--prefix
|
||||
(if (or transient--prefix
|
||||
transient-current-prefix)
|
||||
(cl-find-if (lambda (obj)
|
||||
(eq (transient--suffix-command obj)
|
||||
(or command this-original-command)))
|
||||
transient--suffixes)
|
||||
(or transient--suffixes
|
||||
transient-current-suffixes))
|
||||
(when-let ((obj (get (or command this-command) 'transient--suffix))
|
||||
(obj (clone obj)))
|
||||
(transient-init-scope obj)
|
||||
@@ -1329,7 +1388,7 @@ then just return it. Otherwise return the symbol whose
|
||||
(define-key map (kbd "C-q") 'transient-quit-all)
|
||||
(define-key map (kbd "C-z") 'transient-suspend)
|
||||
(define-key map (kbd "C-v") 'transient-scroll-up)
|
||||
(define-key map (kbd "M-v") 'transient-scroll-down)
|
||||
(define-key map (kbd "C-M-v") 'transient-scroll-down)
|
||||
(define-key map [next] 'transient-scroll-up)
|
||||
(define-key map [prior] 'transient-scroll-down)
|
||||
map)
|
||||
@@ -1353,8 +1412,9 @@ edited using the same functions as used for transients.")
|
||||
(define-key map (kbd "C-t") 'transient-show)
|
||||
(define-key map (kbd "?") 'transient-help)
|
||||
(define-key map (kbd "C-h") 'transient-help)
|
||||
(define-key map (kbd "M-p") 'transient-history-prev)
|
||||
(define-key map (kbd "M-n") 'transient-history-next)
|
||||
;; Also bound to "C-x p" and "C-x n" in transient-common-commands.
|
||||
(define-key map (kbd "C-M-p") 'transient-history-prev)
|
||||
(define-key map (kbd "C-M-n") 'transient-history-next)
|
||||
map)
|
||||
"Top-level keymap used by all transients.")
|
||||
|
||||
@@ -1387,8 +1447,8 @@ edited using the same functions as used for transients.")
|
||||
["Value commands"
|
||||
("C-x s " "Set" transient-set)
|
||||
("C-x C-s" "Save" transient-save)
|
||||
("M-p " "Previous value" transient-history-prev)
|
||||
("M-n " "Next value" transient-history-next)]
|
||||
("C-x p " "Previous value" transient-history-prev)
|
||||
("C-x n " "Next value" transient-history-next)]
|
||||
["Sticky commands"
|
||||
;; Like `transient-sticky-map' except that
|
||||
;; "C-g" has to be bound to a different command.
|
||||
@@ -1490,7 +1550,6 @@ of the corresponding object.")
|
||||
(when-let ((conflict (and transient-detect-key-conflicts
|
||||
(transient--lookup-key map kbd))))
|
||||
(unless (eq cmd conflict)
|
||||
(transient--emergency-exit)
|
||||
(error "Cannot bind %S to %s and also %s"
|
||||
(string-trim key)
|
||||
cmd conflict)))
|
||||
@@ -1571,58 +1630,76 @@ be nil and PARAMS may be (but usually is not) used to set e.g. the
|
||||
This function is also called internally in which case LAYOUT and
|
||||
EDIT may be non-nil."
|
||||
(transient--debug 'setup)
|
||||
(cond
|
||||
((not name)
|
||||
;; Switching between regular and edit mode.
|
||||
(transient--pop-keymap 'transient--transient-map)
|
||||
(transient--pop-keymap 'transient--redisplay-map)
|
||||
(setq name (oref transient--prefix command))
|
||||
(setq params (list :scope (oref transient--prefix scope))))
|
||||
((not (or layout ; resuming parent/suspended prefix
|
||||
transient-current-command)) ; entering child prefix
|
||||
(transient--stack-zap)) ; replace suspended prefix, if any
|
||||
(edit
|
||||
;; Returning from help to edit.
|
||||
(setq transient--editp t)))
|
||||
(transient--init-objects name layout params)
|
||||
(transient--history-init transient--prefix)
|
||||
(setq transient--predicate-map (transient--make-predicate-map))
|
||||
(setq transient--transient-map (transient--make-transient-map))
|
||||
(setq transient--redisplay-map (transient--make-redisplay-map))
|
||||
(setq transient--original-window (selected-window))
|
||||
(setq transient--original-buffer (current-buffer))
|
||||
(transient--redisplay)
|
||||
(transient--init-transient)
|
||||
(transient--suspend-which-key-mode))
|
||||
(when (and (>= (minibuffer-depth) 1) transient--prefix)
|
||||
(error "Cannot invoke %s while minibuffer is active %s"
|
||||
this-command "on behalf of another prefix command"))
|
||||
(transient--with-emergency-exit
|
||||
(cond
|
||||
((not name)
|
||||
;; Switching between regular and edit mode.
|
||||
(transient--pop-keymap 'transient--transient-map)
|
||||
(transient--pop-keymap 'transient--redisplay-map)
|
||||
(setq name (oref transient--prefix command))
|
||||
(setq params (list :scope (oref transient--prefix scope))))
|
||||
((not (or layout ; resuming parent/suspended prefix
|
||||
transient-current-command)) ; entering child prefix
|
||||
(transient--stack-zap)) ; replace suspended prefix, if any
|
||||
(edit
|
||||
;; Returning from help to edit.
|
||||
(setq transient--editp t)))
|
||||
(transient--init-objects name layout params)
|
||||
(transient--history-init transient--prefix)
|
||||
(setq transient--predicate-map (transient--make-predicate-map))
|
||||
(setq transient--transient-map (transient--make-transient-map))
|
||||
(setq transient--redisplay-map (transient--make-redisplay-map))
|
||||
(setq transient--original-window (selected-window))
|
||||
(setq transient--original-buffer (current-buffer))
|
||||
(transient--redisplay)
|
||||
(transient--init-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."
|
||||
(if (slot-boundp group 'setup-children)
|
||||
(funcall (oref group setup-children) children)
|
||||
children))
|
||||
|
||||
(defun transient--init-objects (name layout params)
|
||||
(setq transient--prefix
|
||||
(let ((proto (get name 'transient--prefix)))
|
||||
(apply #'clone proto
|
||||
:prototype proto
|
||||
:level (or (alist-get
|
||||
t (alist-get name transient-levels))
|
||||
transient-default-level)
|
||||
params)))
|
||||
(transient-init-value transient--prefix)
|
||||
(setq transient--layout
|
||||
(or layout
|
||||
(let ((levels (alist-get name transient-levels)))
|
||||
(cl-mapcan (lambda (c) (transient--init-child levels c))
|
||||
(append (get name 'transient--layout)
|
||||
(and (not transient--editp)
|
||||
(get 'transient-common-commands
|
||||
'transient--layout)))))))
|
||||
(setq transient--suffixes
|
||||
(cl-labels ((s (def)
|
||||
(cond
|
||||
((stringp def) nil)
|
||||
((listp def) (cl-mapcan #'s def))
|
||||
((transient-group--eieio-childp def)
|
||||
(cl-mapcan #'s (oref def suffixes)))
|
||||
((transient-suffix--eieio-childp def)
|
||||
(list def)))))
|
||||
(cl-mapcan #'s transient--layout))))
|
||||
(setq transient--prefix (transient--init-prefix name params))
|
||||
(setq transient--layout (or layout (transient--init-suffixes name)))
|
||||
(setq transient--suffixes (transient--flatten-suffixes transient--layout)))
|
||||
|
||||
(defun transient--init-prefix (name &optional params)
|
||||
(let ((obj (let ((proto (get name 'transient--prefix)))
|
||||
(apply #'clone proto
|
||||
:prototype proto
|
||||
:level (or (alist-get t (alist-get name transient-levels))
|
||||
transient-default-level)
|
||||
params))))
|
||||
(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))
|
||||
(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)
|
||||
((listp def) (cl-mapcan #'s def))
|
||||
((transient-group--eieio-childp def)
|
||||
(cl-mapcan #'s (oref def suffixes)))
|
||||
((transient-suffix--eieio-childp def)
|
||||
(list def)))))
|
||||
(cl-mapcan #'s layout)))
|
||||
|
||||
(defun transient--init-child (levels spec)
|
||||
(cl-etypecase spec
|
||||
@@ -1637,7 +1714,7 @@ EDIT may be non-nil."
|
||||
(when (transient--use-suffix-p obj)
|
||||
(when-let ((suffixes
|
||||
(cl-mapcan (lambda (c) (transient--init-child levels c))
|
||||
children)))
|
||||
(transient-setup-children obj children))))
|
||||
(oset obj suffixes suffixes)
|
||||
(list obj)))))))
|
||||
|
||||
@@ -1732,6 +1809,20 @@ EDIT may be non-nil."
|
||||
(apply #'derived-mode-p if-not-derived))))
|
||||
(t default)))
|
||||
|
||||
(defun transient--suffix-predicate (spec)
|
||||
(let ((plist (nth 2 spec)))
|
||||
(seq-some (lambda (prop)
|
||||
(when-let ((pred (plist-get plist prop)))
|
||||
(list prop pred)))
|
||||
'( :if :if-not
|
||||
:if-nil :if-non-nil
|
||||
:if-mode :if-not-mode
|
||||
:if-derived :if-not-derived
|
||||
:inapt-if :inapt-if-not
|
||||
:inapt-if-nil :inapt-if-non-nil
|
||||
:inapt-if-mode :inapt-if-not-mode
|
||||
:inapt-if-derived :inapt-if-not-derived))))
|
||||
|
||||
;;; Flow-Control
|
||||
|
||||
(defun transient--init-transient ()
|
||||
@@ -1949,29 +2040,15 @@ EDIT may be non-nil."
|
||||
|
||||
(defun transient--emergency-exit ()
|
||||
"Exit the current transient command after an error occurred.
|
||||
|
||||
Beside being used with `condition-case', this function also has
|
||||
to be a member of `debugger-mode-hook', else the debugger would
|
||||
be unusable and exiting it by pressing \"q\" would fail because
|
||||
the transient command would still be active and that key would
|
||||
either be unbound or do something else.
|
||||
|
||||
When no transient is active (i.e. when `transient--prefix') is
|
||||
nil, then do nothing."
|
||||
(transient--debug 'emergency-exit)
|
||||
(when transient--prefix
|
||||
(setq transient--stack nil)
|
||||
(setq transient--exitp t)
|
||||
(transient--pre-exit)
|
||||
(transient--post-command)))
|
||||
|
||||
(add-hook 'debugger-mode-hook 'transient--emergency-exit)
|
||||
|
||||
(defmacro transient--with-emergency-exit (&rest body)
|
||||
(declare (indent defun))
|
||||
`(condition-case nil
|
||||
,(macroexp-progn body)
|
||||
(error (transient--emergency-exit))))
|
||||
|
||||
;;; Pre-Commands
|
||||
|
||||
(defun transient--do-stay ()
|
||||
@@ -2275,6 +2352,20 @@ abstract `transient-infix' class must implement this function.
|
||||
Non-infix suffix commands usually don't have a value."
|
||||
nil)
|
||||
|
||||
(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 objects 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 objects 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))
|
||||
(if (slot-boundp obj 'value)
|
||||
(oref obj value)
|
||||
@@ -2356,9 +2447,10 @@ limited number of possible values should you replace this with a
|
||||
simple method that does not handle history. (E.g. for a command
|
||||
line switch the only possible values are \"use it\" and \"don't use
|
||||
it\", in which case it is pointless to preserve history.)"
|
||||
(with-slots (value multi-value allow-empty choices) obj
|
||||
(with-slots (value multi-value always-read allow-empty choices) obj
|
||||
(if (and value
|
||||
(not multi-value)
|
||||
(not always-read)
|
||||
transient--prefix)
|
||||
(oset obj value nil)
|
||||
(let* ((overriding-terminal-local-map nil)
|
||||
@@ -2391,7 +2483,8 @@ it\", in which case it is pointless to preserve history.)"
|
||||
((and (equal value "\"\"") allow-empty)
|
||||
(setq value "")))
|
||||
(when value
|
||||
(when (bound-and-true-p ivy-mode)
|
||||
(when (and (bound-and-true-p ivy-mode)
|
||||
(stringp (car transient--history)))
|
||||
(set-text-properties 0 (length (car transient--history)) nil
|
||||
(car transient--history)))
|
||||
(setf (alist-get history-key transient-history)
|
||||
@@ -2506,10 +2599,7 @@ prompt."
|
||||
"Set the value of infix object OBJ to value.")
|
||||
|
||||
(cl-defmethod transient-infix-set ((obj transient-infix) value)
|
||||
"Set the value of infix object OBJ to value.
|
||||
|
||||
This implementation should be suitable for almost all infix
|
||||
commands."
|
||||
"Set the value of infix object OBJ to value."
|
||||
(oset obj value value))
|
||||
|
||||
(cl-defmethod transient-infix-set :around ((obj transient-argument) value)
|
||||
@@ -2552,16 +2642,22 @@ 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."
|
||||
(delq nil (mapcar 'transient-infix-value (transient-suffixes prefix))))
|
||||
|
||||
(defun transient-suffixes (prefix)
|
||||
"Return the suffix objects of the transient prefix command PREFIX."
|
||||
(if (eq transient-current-command prefix)
|
||||
(delq nil (mapcar 'transient-infix-value transient-current-suffixes))
|
||||
(let ((transient--prefix nil)
|
||||
(transient--layout nil)
|
||||
(transient--suffixes nil))
|
||||
(transient--init-objects prefix nil nil)
|
||||
(delq nil (mapcar 'transient-infix-value transient--suffixes)))))
|
||||
transient-current-suffixes
|
||||
(let ((transient--prefix (transient--init-prefix prefix)))
|
||||
(transient--flatten-suffixes
|
||||
(transient--init-suffixes prefix)))))
|
||||
|
||||
(defun transient-get-value ()
|
||||
(delq nil (mapcar 'transient-infix-value transient-current-suffixes)))
|
||||
(delq nil (mapcar (lambda (obj)
|
||||
(and (or (not (slot-exists-p obj 'unsavable))
|
||||
(not (oref obj unsavable)))
|
||||
(transient-infix-value obj)))
|
||||
transient-current-suffixes)))
|
||||
|
||||
(cl-defgeneric transient-infix-value (obj)
|
||||
"Return the value of the suffix object OBJ.
|
||||
@@ -2610,7 +2706,7 @@ contribute to the value of the transient."
|
||||
nil)
|
||||
|
||||
(cl-defmethod transient-infix-value ((obj transient-files))
|
||||
"Return (concat ARGUMENT VALUE) or nil.
|
||||
"Return (cons ARGUMENT VALUE) or nil.
|
||||
|
||||
ARGUMENT and VALUE are the values of the respective slots of OBJ.
|
||||
If VALUE is nil, then return nil. VALUE may be the empty string,
|
||||
@@ -2618,6 +2714,25 @@ which is not the same as nil."
|
||||
(when-let ((value (oref obj value)))
|
||||
(cons (oref obj argument) value)))
|
||||
|
||||
;;;; Utilities
|
||||
|
||||
(defun transient-arg-value (arg args)
|
||||
"Return the value of ARG as it appears in ARGS.
|
||||
|
||||
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."
|
||||
(if (string-match-p "=\\'" arg)
|
||||
(save-match-data
|
||||
(when-let ((match (let ((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)))
|
||||
|
||||
;;; History
|
||||
|
||||
(cl-defgeneric transient--history-key (obj)
|
||||
@@ -2751,12 +2866,14 @@ have a history of their own.")
|
||||
(insert desc ?\n)))
|
||||
|
||||
(cl-defmethod transient--insert-group ((group transient-row))
|
||||
(transient--maybe-pad-keys group)
|
||||
(dolist (suffix (oref group suffixes))
|
||||
(insert (transient-format suffix))
|
||||
(insert " "))
|
||||
(insert ?\n))
|
||||
|
||||
(cl-defmethod transient--insert-group ((group transient-column))
|
||||
(transient--maybe-pad-keys group)
|
||||
(dolist (suffix (oref group suffixes))
|
||||
(let ((str (transient-format suffix)))
|
||||
(insert str)
|
||||
@@ -2767,6 +2884,7 @@ have a history of their own.")
|
||||
(let* ((columns
|
||||
(mapcar
|
||||
(lambda (column)
|
||||
(transient--maybe-pad-keys column group)
|
||||
(let ((rows (mapcar 'transient-format (oref column suffixes))))
|
||||
(when-let ((desc (transient-format-description column)))
|
||||
(push desc rows))
|
||||
@@ -2789,9 +2907,11 @@ have a history of their own.")
|
||||
(let* ((subgroups (oref group suffixes))
|
||||
(n (length subgroups)))
|
||||
(dotimes (s n)
|
||||
(transient--insert-group (nth s subgroups))
|
||||
(when (< s (1- n))
|
||||
(insert ?\n)))))
|
||||
(let ((subgroup (nth s subgroups)))
|
||||
(transient--maybe-pad-keys subgroup group)
|
||||
(transient--insert-group subgroup)
|
||||
(when (< s (1- n))
|
||||
(insert ?\n))))))
|
||||
|
||||
(cl-defgeneric transient-format (obj)
|
||||
"Format and return OBJ for display.
|
||||
@@ -2946,6 +3066,9 @@ 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))
|
||||
(propertize "(BUG: no description)" 'face 'error))))
|
||||
(if (transient--key-unreachable-p obj)
|
||||
(propertize desc 'face 'transient-unreachable)
|
||||
@@ -3009,6 +3132,34 @@ If the OBJ's `key' is currently unreachable, then apply the face
|
||||
(let ((val (lookup-key keymap key)))
|
||||
(and val (not (integerp val)) val)))
|
||||
|
||||
(defun transient--maybe-pad-keys (group &optional parent)
|
||||
(when-let ((pad (if (slot-boundp group 'pad-keys)
|
||||
(oref group pad-keys)
|
||||
(and parent
|
||||
(slot-boundp parent 'pad-keys)
|
||||
(oref parent pad-keys)))))
|
||||
(let ((width (apply #'max
|
||||
(cons (if (integerp pad) pad 0)
|
||||
(mapcar (lambda (suffix)
|
||||
(length (oref suffix key)))
|
||||
(oref group suffixes))))))
|
||||
(dolist (suffix (oref group suffixes))
|
||||
(oset suffix key
|
||||
(truncate-string-to-width (oref suffix key) width nil ?\s))))))
|
||||
|
||||
(defun transient-command-summary-or-name (obj)
|
||||
"Return the summary or name of the command represented by OBJ.
|
||||
|
||||
If the command has a doc-string, then return the first line of
|
||||
that, else its name.
|
||||
|
||||
Intended to be temporarily used as the `:suffix-description' of
|
||||
a prefix command, while porting a regular keymap to a transient."
|
||||
(let ((command (transient--suffix-symbol (oref obj command))))
|
||||
(if-let ((doc (documentation command)))
|
||||
(propertize (car (split-string doc "\n")) 'face 'font-lock-doc-face)
|
||||
(propertize (symbol-name command) 'face 'font-lock-function-name-face))))
|
||||
|
||||
;;; Help
|
||||
|
||||
(cl-defgeneric transient-show-help (obj)
|
||||
@@ -3381,6 +3532,18 @@ we stop there."
|
||||
(push (funcall function (car acc) elt) acc))
|
||||
(nreverse acc)))
|
||||
|
||||
(defun transient-plist-to-alist (plist)
|
||||
(let (alist)
|
||||
(while plist
|
||||
(push (cons (let* ((symbol (pop plist))
|
||||
(name (symbol-name symbol)))
|
||||
(if (eq (aref name 0) ?:)
|
||||
(intern (substring name 1))
|
||||
symbol))
|
||||
(pop plist))
|
||||
alist))
|
||||
(nreverse alist)))
|
||||
|
||||
;;; Font-Lock
|
||||
|
||||
(defconst transient-font-lock-keywords
|
||||
@@ -3398,6 +3561,37 @@ we stop there."
|
||||
|
||||
(font-lock-add-keywords 'emacs-lisp-mode transient-font-lock-keywords)
|
||||
|
||||
;;; Auxiliary Classes
|
||||
;;;; `transient-lisp-variable'
|
||||
|
||||
(defclass transient-lisp-variable (transient-variable)
|
||||
((reader :initform transient-lisp-variable--reader)
|
||||
(always-read :initform t)
|
||||
(set-value :initarg :set-value :initform set))
|
||||
"[Experimental] Class used for Lisp variables.")
|
||||
|
||||
(cl-defmethod transient-init-value ((obj transient-lisp-variable))
|
||||
(oset obj value (symbol-value (oref obj variable))))
|
||||
|
||||
(cl-defmethod transient-infix-set ((obj transient-lisp-variable) value)
|
||||
(funcall (oref obj set-value)
|
||||
(oref obj variable)
|
||||
(oset obj value value)))
|
||||
|
||||
(cl-defmethod transient-format-description ((obj transient-lisp-variable))
|
||||
(or (oref obj description)
|
||||
(symbol-name (oref obj variable))))
|
||||
|
||||
(cl-defmethod transient-format-value ((obj transient-lisp-variable))
|
||||
(propertize (prin1-to-string (oref obj value))
|
||||
'face 'transient-value))
|
||||
|
||||
(cl-defmethod transient-prompt ((obj transient-lisp-variable))
|
||||
(format "Set %s: " (oref obj variable)))
|
||||
|
||||
(defun transient-lisp-variable--reader (prompt initial-input _history)
|
||||
(read--expression prompt initial-input))
|
||||
|
||||
;;; _
|
||||
(provide 'transient)
|
||||
;; Local Variables:
|
||||
|
||||
Reference in New Issue
Block a user