Skip to content

Commit c0dbe1a

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 cd04da0 commit c0dbe1a

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
@@ -3658,41 +3658,35 @@ symbol."
36583658
"Apply a gptel preset to the buffer depending on the prompt.
36593659
36603660
If the user prompt begins with @foo, the preset foo is applied."
3661-
(text-property-search-backward 'gptel nil t)
3662-
(when (looking-at
3663-
(concat "[\n[:blank:]]*"
3664-
(and-let* ((prefix (gptel-prompt-prefix-string))
3665-
((not (string-empty-p prefix))))
3666-
(concat "\\(?:" (regexp-quote prefix) "\\)?"))))
3667-
(goto-char (match-end 0)))
3668-
(while-let (((looking-at "[[:blank:]\n]*@\\([^[:blank:]]+\\)\\s-+"))
3669-
(name (match-string 1))
3670-
(preset (or (gptel-get-preset (intern-soft name))
3671-
(gptel-get-preset name))))
3672-
(delete-region (match-beginning 0) (match-end 0))
3673-
(gptel--apply-preset (cons name preset)
3674-
(lambda (sym val)
3675-
(set (make-local-variable sym) val)))
3676-
(message "Sending request with preset %s applied!"
3677-
(propertize name 'face 'mode-line-emphasis))))
3661+
(when gptel--known-presets
3662+
(text-property-search-backward 'gptel nil t)
3663+
(while (re-search-forward "@\\([^[:blank:]]+\\)\\_>" nil t)
3664+
;; The following convoluted check is because re-search is much faster if
3665+
;; the search pattern begins with a non-whitespace char.
3666+
(when (or (= (match-beginning 0) (point-min))
3667+
(memq (char-syntax (char-before (match-beginning 0))) '(32 62)))
3668+
(when-let* ((name (match-string 1))
3669+
(preset (or (gptel-get-preset (intern-soft name))
3670+
(gptel-get-preset name))))
3671+
(delete-region (match-beginning 0) (match-end 0))
3672+
(gptel--apply-preset (cons name preset)
3673+
(lambda (sym val)
3674+
(set (make-local-variable sym) val))))))))
3675+
3676+
;; ;; Alternative approach with string search
3677+
;; (search-forward "@" nil t)
3678+
;; (if (and (memq (char-syntax (char-before (1- (point)))) '(32 62))
3679+
;; (looking-at "\\([^[:blank:]]+?\\)[[:punct:]]?\\s-+"))
3680+
;; do-stuff)
36783681

36793682
(defun gptel--fontify-preset-keyword (end)
36803683
"Font-lock function for preset indicators in chat buffers.
36813684
36823685
Return preset fontification info for text up to END."
3683-
(when (re-search-forward "\\(?:^\\|[[:blank:]]+\\)\\(@\\([^[:blank:]\n]+\\)\\)"
3684-
end t)
3685-
(= (match-beginning 1)
3686-
(save-excursion
3687-
(text-property-search-backward 'gptel nil t)
3688-
(save-match-data
3689-
(if (looking-at
3690-
(concat "[\n[:blank:]]*"
3691-
(and-let* ((prefix (gptel-prompt-prefix-string))
3692-
((not (string-empty-p prefix))))
3693-
(concat "\\(?:" (regexp-quote prefix) "\\)?"
3694-
"[\n[:blank:]]*"))))
3695-
(match-end 0) (point)))))))
3686+
(and (re-search-forward "@\\([^[:blank:]]+\\)\\_>" end t)
3687+
(or (= (match-beginning 0) (point-min))
3688+
(memq (char-syntax (char-before (match-beginning 0))) '(32 62)))
3689+
(not (plist-get (text-properties-at (match-beginning 1)) 'gptel))))
36963690

36973691
(defun gptel-preset-capf ()
36983692
"Completion at point for gptel presets in `gptel-mode'.
@@ -3716,9 +3710,11 @@ Add this to `completion-at-point-functions'."
37163710
37173711
Intended to be added to `gptel-mode-hook'."
37183712
(let ((keyword '((gptel--fontify-preset-keyword
3719-
1 (when-let* ((comps (all-completions (match-string 2)
3713+
;; subexp 0 here is not required, we retain it to make it
3714+
;; easy to swtich to more complex patterns in the future
3715+
0 (when-let* ((comps (all-completions (match-string 1)
37203716
gptel--known-presets))
3721-
((member (match-string 2) comps)))
3717+
((member (match-string 1) comps)))
37223718
'(:box -1 :inherit secondary-selection))
37233719
prepend))))
37243720
(cond

0 commit comments

Comments
 (0)