Skip to content

Commit 59688b3

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 a636a1f commit 59688b3

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
@@ -3636,41 +3636,35 @@ symbol."
36363636
"Apply a gptel preset to the buffer depending on the prompt.
36373637
36383638
If the user prompt begins with @foo, the preset foo is applied."
3639-
(text-property-search-backward 'gptel nil t)
3640-
(when (looking-at
3641-
(concat "[\n[:blank:]]*"
3642-
(and-let* ((prefix (gptel-prompt-prefix-string))
3643-
((not (string-empty-p prefix))))
3644-
(concat "\\(?:" (regexp-quote prefix) "\\)?"))))
3645-
(goto-char (match-end 0)))
3646-
(while-let (((looking-at "[[:blank:]\n]*@\\([^[:blank:]]+\\)\\s-+"))
3647-
(name (match-string 1))
3648-
(preset (or (gptel-get-preset (intern-soft name))
3649-
(gptel-get-preset name))))
3650-
(delete-region (match-beginning 0) (match-end 0))
3651-
(gptel--apply-preset (cons name preset)
3652-
(lambda (sym val)
3653-
(set (make-local-variable sym) val)))
3654-
(message "Sending request with preset %s applied!"
3655-
(propertize name 'face 'mode-line-emphasis))))
3639+
(when gptel--known-presets
3640+
(text-property-search-backward 'gptel nil t)
3641+
(while (re-search-forward "@\\([^[:blank:]]+\\)\\_>" nil t)
3642+
;; The following convoluted check is because re-search is much faster if
3643+
;; the search pattern begins with a non-whitespace char.
3644+
(when (or (= (match-beginning 0) (point-min))
3645+
(memq (char-syntax (char-before (match-beginning 0))) '(32 62)))
3646+
(when-let* ((name (match-string 1))
3647+
(preset (or (gptel-get-preset (intern-soft name))
3648+
(gptel-get-preset name))))
3649+
(delete-region (match-beginning 0) (match-end 0))
3650+
(gptel--apply-preset (cons name preset)
3651+
(lambda (sym val)
3652+
(set (make-local-variable sym) val))))))))
3653+
3654+
;; ;; Alternative approach with string search
3655+
;; (search-forward "@" nil t)
3656+
;; (if (and (memq (char-syntax (char-before (1- (point)))) '(32 62))
3657+
;; (looking-at "\\([^[:blank:]]+?\\)[[:punct:]]?\\s-+"))
3658+
;; do-stuff)
36563659

36573660
(defun gptel--fontify-preset-keyword (end)
36583661
"Font-lock function for preset indicators in chat buffers.
36593662
36603663
Return preset fontification info for text up to END."
3661-
(when (re-search-forward "\\(?:^\\|[[:blank:]]+\\)\\(@\\([^[:blank:]\n]+\\)\\)"
3662-
end t)
3663-
(= (match-beginning 1)
3664-
(save-excursion
3665-
(text-property-search-backward 'gptel nil t)
3666-
(save-match-data
3667-
(if (looking-at
3668-
(concat "[\n[:blank:]]*"
3669-
(and-let* ((prefix (gptel-prompt-prefix-string))
3670-
((not (string-empty-p prefix))))
3671-
(concat "\\(?:" (regexp-quote prefix) "\\)?"
3672-
"[\n[:blank:]]*"))))
3673-
(match-end 0) (point)))))))
3664+
(and (re-search-forward "@\\([^[:blank:]]+\\)\\_>" end t)
3665+
(or (= (match-beginning 0) (point-min))
3666+
(memq (char-syntax (char-before (match-beginning 0))) '(32 62)))
3667+
(not (plist-get (text-properties-at (match-beginning 1)) 'gptel))))
36743668

36753669
(defun gptel-preset-capf ()
36763670
"Completion at point for gptel presets in `gptel-mode'.
@@ -3694,9 +3688,11 @@ Add this to `completion-at-point-functions'."
36943688
36953689
Intended to be added to `gptel-mode-hook'."
36963690
(let ((keyword '((gptel--fontify-preset-keyword
3697-
1 (when-let* ((comps (all-completions (match-string 2)
3691+
;; subexp 0 here is not required, we retain it to make it
3692+
;; easy to swtich to more complex patterns in the future
3693+
0 (when-let* ((comps (all-completions (match-string 1)
36983694
gptel--known-presets))
3699-
((member (match-string 2) comps)))
3695+
((member (match-string 1) comps)))
37003696
'(:box -1 :inherit secondary-selection))
37013697
prepend))))
37023698
(cond

0 commit comments

Comments
 (0)