Skip to content

Commit 2472faa

Browse files
committed
gptel: Match presets anywhere in the user prompt
Catch strings of the form `@preset-name` anywhere in the user prompt and apply the preset in the transform/augment step. This change is experimental, and will be reverted if there are unexpected consequences or performance problems. This change is to make it easy to specify an on-the-fly preset when the user prompt structure is slightly off. Two examples: 1. When the user prompt is structured as ** Some heading *Prompt*: @preset-name ... where the heading is used for structural purposes. Technically the user prompt begins at the heading, but it's clear from context that the user intends to apply preset-name to the message. 2. When the preset specification naturally comes at the end. <long chunk of text> What do you make of the above, @explainer? This also promotes a more conversational preset usage style. * gptel.el (gptel--transform-apply-preset): Scan the entire user prompt for `@preset-name` mentions and apply presets as they are found. (gptel--fontify-preset-keyword): Fontify all `@preset-name` mentions in the user prompt. (gptel--prettify-preset): Adjust for new fontification keyword.
1 parent 72b0f38 commit 2472faa

File tree

1 file changed

+28
-32
lines changed

1 file changed

+28
-32
lines changed

gptel.el

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3627,41 +3627,35 @@ symbol."
36273627
"Apply a gptel preset to the buffer depending on the prompt.
36283628
36293629
If the user prompt begins with @foo, the preset foo is applied."
3630-
(text-property-search-backward 'gptel nil t)
3631-
(when (looking-at
3632-
(concat "[\n[:blank:]]*"
3633-
(and-let* ((prefix (gptel-prompt-prefix-string))
3634-
((not (string-empty-p prefix))))
3635-
(concat "\\(?:" (regexp-quote prefix) "\\)?"))))
3636-
(goto-char (match-end 0)))
3637-
(while-let (((looking-at "[[:blank:]\n]*@\\([^[:blank:]]+\\)\\s-+"))
3638-
(name (match-string 1))
3639-
(preset (or (gptel-get-preset (intern-soft name))
3640-
(gptel-get-preset name))))
3641-
(delete-region (match-beginning 0) (match-end 0))
3642-
(gptel--apply-preset (cons name preset)
3643-
(lambda (sym val)
3644-
(set (make-local-variable sym) val)))
3645-
(message "Sending request with preset %s applied!"
3646-
(propertize name 'face 'mode-line-emphasis))))
3630+
(when gptel--known-presets
3631+
(text-property-search-backward 'gptel nil t)
3632+
(while (re-search-forward "@\\([^[:blank:]]+\\)\\_>" nil t)
3633+
;; The following convoluted check is because re-search is much faster if
3634+
;; the search pattern begins with a non-whitespace char.
3635+
(when (or (= (match-beginning 0) (point-min))
3636+
(memq (char-syntax (char-before (match-beginning 0))) '(32 62)))
3637+
(when-let* ((name (match-string 1))
3638+
(preset (or (gptel-get-preset (intern-soft name))
3639+
(gptel-get-preset name))))
3640+
(delete-region (match-beginning 0) (match-end 0))
3641+
(gptel--apply-preset (cons name preset)
3642+
(lambda (sym val)
3643+
(set (make-local-variable sym) val))))))))
3644+
3645+
;; ;; Alternative approach with string search
3646+
;; (search-forward "@" nil t)
3647+
;; (if (and (memq (char-syntax (char-before (1- (point)))) '(32 62))
3648+
;; (looking-at "\\([^[:blank:]]+?\\)[[:punct:]]?\\s-+"))
3649+
;; do-stuff)
36473650

36483651
(defun gptel--fontify-preset-keyword (end)
36493652
"Font-lock function for preset indicators in chat buffers.
36503653
36513654
Return preset fontification info for text up to END."
3652-
(when (re-search-forward "\\(?:^\\|[[:blank:]]+\\)\\(@\\([^[:blank:]\n]+\\)\\)"
3653-
end t)
3654-
(= (match-beginning 1)
3655-
(save-excursion
3656-
(text-property-search-backward 'gptel nil t)
3657-
(save-match-data
3658-
(if (looking-at
3659-
(concat "[\n[:blank:]]*"
3660-
(and-let* ((prefix (gptel-prompt-prefix-string))
3661-
((not (string-empty-p prefix))))
3662-
(concat "\\(?:" (regexp-quote prefix) "\\)?"
3663-
"[\n[:blank:]]*"))))
3664-
(match-end 0) (point)))))))
3655+
(and (re-search-forward "@\\([^[:blank:]]+\\)\\_>" nil t)
3656+
(or (= (match-beginning 0) (point-min))
3657+
(memq (char-syntax (char-before (match-beginning 0))) '(32 62)))
3658+
(not (plist-get (text-properties-at (match-beginning 1)) 'gptel))))
36653659

36663660
(defun gptel-preset-capf ()
36673661
"Completion at point for gptel presets in `gptel-mode'.
@@ -3685,9 +3679,11 @@ Add this to `completion-at-point-functions'."
36853679
36863680
Intended to be added to `gptel-mode-hook'."
36873681
(let ((keyword '((gptel--fontify-preset-keyword
3688-
1 (when-let* ((comps (all-completions (match-string 2)
3682+
;; subexp 0 here is not required, we retain it to make it
3683+
;; easy to swtich to more complex patterns in the future
3684+
0 (when-let* ((comps (all-completions (match-string 1)
36893685
gptel--known-presets))
3690-
((member (match-string 2) comps)))
3686+
((member (match-string 1) comps)))
36913687
'(:box -1 :inherit secondary-selection))
36923688
prepend))))
36933689
(cond

0 commit comments

Comments
 (0)