branch: externals/transient
commit c9aa876b4cc679b19c736acc5951f6e640bcbbf2
Author: Jonas Bernoulli <[email protected]>
Commit: Jonas Bernoulli <[email protected]>

    Generate command's docstring based on class's docstring slot
    
    Iff no docstring is explicitly specified for the command and the
    class's `docstring' is set.
    
    This likely still needs some refinement, so leave it undocumented for
    now.  Meanwhile, see the `magit-section-jumper' class for an example.
---
 lisp/transient.el | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/lisp/transient.el b/lisp/transient.el
index 2fcc4b7ecb..7b1ea530bb 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -794,7 +794,8 @@ If `transient-save-history' is nil, then do nothing."
 ;;;; Prefix
 
 (defclass transient-prefix ()
-  ((prototype   :initarg :prototype)
+  ((docstring   :allocation :class :initform nil)
+   (prototype   :initarg :prototype)
    (command     :initarg :command)
    (level       :initarg :level)
    (init-value  :initarg :init-value)
@@ -928,6 +929,7 @@ predicate slots or more than one `inapt-if*' slots are 
non-nil."
 
 (defclass transient-suffix (transient-child)
   ((definition  :allocation :class    :initform nil)
+   (docstring   :allocation :class    :initform nil)
    (key         :initarg :key)
    (command     :initarg :command)
    (transient   :initarg :transient)
@@ -1300,21 +1302,39 @@ commands are aliases for."
           (delq int declare))
         (unless (cdr declare)
           (setq declare nil)))
+      (when (eq (car-safe class) 'quote)
+        (setq class (cadr class)))
+      (setq keys (nreverse keys))
+      (when (and (not docstr) class)
+        (setq docstr (transient--generate-docstring class keys)))
       (cond
        ((not args))
        (nobody
         (error "%s: No function body allowed" form))
        ((not (eq (car-safe (nth (if declare 1 0) args)) 'interactive))
         (error "%s: Interactive form missing" form)))
-      (list (if (eq (car-safe class) 'quote)
-                (cadr class)
-              class)
-            (nreverse keys)
+      (list class
+            keys
             (nreverse suffixes)
             docstr
             (if declare (cons declare args) args)
             interactive-only))))
 
+(eval-and-compile ;transient--generate-docstring
+  (defun transient--generate-docstring (class args)
+    (and-let* ((class (cl--find-class class))
+               (docstr (oref-default class docstring)))
+      (if (functionp docstr)
+          (funcall docstr args)
+        (replace-regexp-in-string
+         "\\({:[^}]+}\\)"
+         (lambda (s)
+           (let ((v (plist-get args (intern (substring s 1 -1)))))
+             (when (eq (car-safe v) 'quote)
+               (setq v (cadr v)))
+             (format "%s" v)))
+         docstr t t 1)))))
+
 (defun transient--parse-child (prefix spec)
   (cl-typecase spec
     (null    (error "Invalid transient--parse-child spec: %s" spec))

Reply via email to