1
0
Fork 0

Improve the placeholder handling in prompts

This commit is contained in:
Bram Schoenmakers 2024-03-22 23:07:11 +01:00
parent 086b6b30f6
commit 2b9ab2fa0a
Signed by: bram
GPG key ID: 0CCD19DFDC63258F
2 changed files with 36 additions and 8 deletions

View file

@ -152,12 +152,32 @@ https://www.example.com"
(it "makes exactly one API call"
(kagi-fastgpt-prompt "foo")
(expect #'kagi--call-api :to-have-been-called-times 1))
(it "replaces all occurrences of %s when it appears in the prompt"
(it "replaces all occurrences of %s with the user input or region when it appears in the prompt"
(spy-on #'kagi--fastgpt)
(spy-on #'completing-read :and-return-value "foo %s %s bar")
(spy-on #'completing-read :and-return-value "foo %s%s bar")
(spy-on #'kagi--get-text-for-prompt :and-return-value "region")
(call-interactively #'kagi-fastgpt-prompt)
(kagi-test--expect-arg #'kagi--fastgpt 0 :to-equal "foo region region bar")))
(kagi-test--expect-arg #'kagi--fastgpt 0 :to-equal "foo regionregion bar"))
(it "retrieves the user input once when %s appears multiple times in the prompt"
(spy-on #'kagi--fastgpt)
(spy-on #'completing-read :and-return-value "%s%s")
(spy-on #'kagi--get-text-for-prompt :and-return-value "")
(call-interactively #'kagi-fastgpt-prompt)
(expect #'kagi--get-text-for-prompt :to-have-been-called-times 1))
(it "replaces all occurrences of %% with % when it appears in the prompt"
(spy-on #'kagi--fastgpt)
(spy-on #'completing-read :and-return-value "foo%%s")
(spy-on #'kagi--get-text-for-prompt)
(call-interactively #'kagi-fastgpt-prompt)
(kagi-test--expect-arg #'kagi--fastgpt 0 :to-equal "foo%s")
(expect #'kagi--get-text-for-prompt :not :to-have-been-called))
(it "does not replace an invalid placeholder %b"
(spy-on #'kagi--fastgpt)
(spy-on #'completing-read :and-return-value "foo%bar")
(spy-on #'kagi--get-text-for-prompt)
(call-interactively #'kagi-fastgpt-prompt)
(kagi-test--expect-arg #'kagi--fastgpt 0 :to-equal "foo%bar")
(expect #'kagi--get-text-for-prompt :not :to-have-been-called)))
(describe "kagi-translate"
(before-each
(spy-on #'kagi-fastgpt-prompt))

18
kagi.el
View file

@ -423,7 +423,8 @@ the text manually."
When PROMPT contains %s, it will be replaced with the region (if
active), the buffer content of the selected buffer or a manually
entered prompt. %s remains unprocessed when `kagi-fastgpt-prompt'
is called non-interactively (when INTERACTIVE-P is nil).
is called non-interactively (when INTERACTIVE-P is nil). %%
becomes % and any other placeholder is left as-is.
If INSERT is non-nil, the response is inserted at point (if the
buffer is writable).
@ -434,11 +435,18 @@ buffer.
If INTERACTIVE-P is nil, the result is returned as a
string (suitable for invocations from Emacs Lisp)."
(interactive (list (let* ((prompt-name (completing-read "fastgpt> " kagi-fastgpt-prompts))
(interactive (list (let* ((user-text)
(prompt-name (completing-read "fastgpt> " kagi-fastgpt-prompts))
(prompt-template (alist-get prompt-name kagi-fastgpt-prompts prompt-name nil #'string=)))
(if (string-match "%s" prompt-template)
(replace-match (kagi--get-text-for-prompt) t t prompt-template)
prompt-template))
(replace-regexp-in-string (rx (seq "%" anychar))
(lambda (match)
(pcase match
("%%" "%")
;; call (kagi--get-text-for-prompt) only once
;; when %s appears multiple times
("%s" (or user-text (setq user-text (kagi--get-text-for-prompt))))
(_ match)))
prompt-template t t))
current-prefix-arg
t))
(let* ((result (kagi--fastgpt prompt))