Skip to content

Commit 31c9ee3

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 db1a610 commit 31c9ee3

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

36863689
(defun gptel--fontify-preset-keyword (end)
36873690
"Font-lock function for preset indicators in chat buffers.
36883691
36893692
Return preset fontification info for text up to END."
3690-
(when (re-search-forward "\\(?:^\\|[[:blank:]]+\\)\\(@\\([^[:blank:]\n]+\\)\\)"
3691-
end t)
3692-
(= (match-beginning 1)
3693-
(save-excursion
3694-
(text-property-search-backward 'gptel nil t)
3695-
(save-match-data
3696-
(if (looking-at
3697-
(concat "[\n[:blank:]]*"
3698-
(and-let* ((prefix (gptel-prompt-prefix-string))
3699-
((not (string-empty-p prefix))))
3700-
(concat "\\(?:" (regexp-quote prefix) "\\)?"
3701-
"[\n[:blank:]]*"))))
3702-
(match-end 0) (point)))))))
3693+
(and (re-search-forward "@\\([^[:blank:]]+\\)\\_>" end t)
3694+
(or (= (match-beginning 0) (point-min))
3695+
(memq (char-syntax (char-before (match-beginning 0))) '(32 62)))
3696+
(not (plist-get (text-properties-at (match-beginning 1)) 'gptel))))
37033697

37043698
(defun gptel-preset-capf ()
37053699
"Completion at point for gptel presets in `gptel-mode'.
@@ -3723,9 +3717,11 @@ Add this to `completion-at-point-functions'."
37233717
37243718
Intended to be added to `gptel-mode-hook'."
37253719
(let ((keyword '((gptel--fontify-preset-keyword
3726-
1 (when-let* ((comps (all-completions (match-string 2)
3720+
;; subexp 0 here is not required, we retain it to make it
3721+
;; easy to swtich to more complex patterns in the future
3722+
0 (when-let* ((comps (all-completions (match-string 1)
37273723
gptel--known-presets))
3728-
((member (match-string 2) comps)))
3724+
((member (match-string 1) comps)))
37293725
'(:box -1 :inherit secondary-selection))
37303726
prepend))))
37313727
(cond

0 commit comments

Comments
 (0)