branch: elpa/gptel
commit 26b6a7be1fb959a78ac2c7c57c5371ff83ce09ea
Author: Karthik Chikmagalur <karthikchikmaga...@gmail.com>
Commit: Karthik Chikmagalur <karthikchikmaga...@gmail.com>

    gptel-transient: Implement preset switching (#542)
    
    * gptel-transient.el (gptel--preset, transient-infix-set,
    transient-format-value, gptel-menu, gptel--infix-preset):
    Implement preset-switching via `gptel-menu'.  Presets need to be
    available for this option to show up in the menu.
    
    TODO: This involved creating a singleton class (gptel--preset)
    derived from transient-option -- it would be good to extend this
    to an umbrella for gptel's options/arguments in `gptel-menu'.
---
 gptel-transient.el | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/gptel-transient.el b/gptel-transient.el
index 8cf6a72b21..b579f6fdde 100644
--- a/gptel-transient.el
+++ b/gptel-transient.el
@@ -461,6 +461,24 @@ Their own value is ignored")
         (propertize display-if-true
                     'face (if value 'transient-value 
'transient-inactive-value))))))
 
+;; TODO(presets): Extend to a general gptel--option class.
+(defclass gptel--preset (transient-option)
+  ((set-value :initarg :set-value :initform nil))
+  "Singleton class for displaying and setting gptel presets.")
+
+(cl-defmethod transient-infix-set ((obj gptel--preset) value)
+  "Call an instance-specific setter for side-effects."
+  (funcall (oref obj set-value) value)
+  (oset obj value value))
+
+(cl-defmethod transient-format-value ((obj gptel--preset))
+  (with-slots (value) obj
+    (if gptel--known-presets            ;FIXME: Make this generic?
+        (format "(%s%s)" (propertize "@" 'face 'transient-key)
+                (or (and value (propertize value 'face 'transient-value))
+                    (propertize "preset" 'face 'transient-inactive-value)))
+      "")))
+
 (defclass gptel--scope (gptel--switches)
   ((display-if-true :initarg :display-if-true :initform "buffer")
    (display-if-false :initarg :display-if-false :initform "global"))
@@ -593,7 +611,9 @@ Also format its value in the Transient menu."
      (lambda () (interactive) (gptel--handle-tool-use gptel--fsm-last))
      :if (lambda () (and gptel--fsm-last
                     (eq (gptel-fsm-state gptel--fsm-last) 'TOOL))))]]
-  [["Request Parameters"
+  [[(gptel--infix-preset
+     :description "Request Parameters" :face 'transient-heading
+     :format "%d %v")
     (gptel--infix-variable-scope)
     (gptel--infix-provider)
     (gptel--infix-max-tokens)
@@ -867,6 +887,42 @@ value of `gptel-use-context', set from here."
               (cdr (assoc destination choices)))))
 
 ;; ** Infixes for model parameters
+(transient-define-infix gptel--infix-preset ()
+  "Select and apply a gptel preset.
+
+Presets are collections of gptel options intended to be applied
+together, defined via `gptel-make-preset'.  Using this command and they
+can be applied globally, buffer-locally or for the next request only."
+  :always-read t
+  :argument "@"
+  :format "  %k %d (%v)"
+  :key "@"
+  :description "Preset"
+  :class 'gptel--preset
+  :prompt "Apply preset: "
+  :set-value #'(lambda (name)
+                 (when name
+                  (gptel--apply-preset
+                   (or (assoc name gptel--known-presets)
+                       (assoc (intern-soft name) gptel--known-presets))
+                   (lambda (sym val) (gptel--set-with-scope
+                                 sym val gptel--set-buffer-locally)))
+                  (message "Applied gptel preset %s"
+                   (propertize name 'face 'transient-value)))
+                 (transient-setup)
+                 name)
+  :reader
+  #'(lambda (prompt initial history)
+      (let ((completion-extra-properties
+             `(:annotation-function
+               ,(lambda (choice)
+                  (when-let* ((desc (plist-get
+                                     (cdr (assoc choice gptel--known-presets))
+                                     :description)))
+                   (concat (propertize " " 'display '(space :align-to 40))
+                    desc))))))
+       (completing-read
+        prompt gptel--known-presets nil t initial history))))
 
 (transient-define-infix gptel--infix-variable-scope ()
   "Set gptel's model parameters and system message in this buffer or globally."

Reply via email to