branch: elpa/gptel
commit 2d61709896369bd8e32323bb5a6a192b64d6f5e8
Author: Karthik Chikmagalur <[email protected]>
Commit: Karthik Chikmagalur <[email protected]>
gptel-org: Add link validation to Org mode gptel buffers
A commonly reported complaint about gptel-mode is that it's
difficult to see why a link will or will not be sent when
`gptel-track-media' is turned on. This commit adds some of the
functionality required to annotate a link to be sent via `jit-lock'.
Org mode links are being worked on first, with support for
Markdown coming in the future.
* gptel-org.el (gptel-org--link-regex): Regex covering recognized
Org link syntax, extracted from a function into a constant.
(gptel--parse-media-links): Use this regex.
(gptel-org--annotate-links): New function to annotate links that will
be sent. Not yet hooked up to jit-lock.
---
gptel-org.el | 49 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 45 insertions(+), 4 deletions(-)
diff --git a/gptel-org.el b/gptel-org.el
index f9a6b17c768..7caae2a9eb8 100644
--- a/gptel-org.el
+++ b/gptel-org.el
@@ -166,6 +166,10 @@ adding elements to this list can significantly slow down
:group 'gptel
:type '(repeat symbol))
+(defconst gptel-org--link-regex
+ (concat "\\(?:" org-link-bracket-re "\\|" org-link-angle-re "\\)")
+ "Link regex for gptel-mode in Org mode.")
+
;;; Setting context and creating queries
(defun gptel-org--get-topic-start ()
@@ -355,12 +359,10 @@ Return a list of the form
(:text \"More text\"))
for inclusion into the user prompt for the gptel request."
(require 'mailcap) ;FIXME Avoid this somehow
- (let ((parts) (from-pt) (mime)
- (link-regex (concat "\\(?:" org-link-bracket-re "\\|"
- org-link-angle-re "\\)")))
+ (let ((parts) (from-pt) (mime))
(save-excursion
(setq from-pt (goto-char beg))
- (while (re-search-forward link-regex end t)
+ (while (re-search-forward gptel-org--link-regex end t)
(setq mime nil)
(when-let* ((link (org-element-context))
((gptel-org--link-standalone-p link))
@@ -400,6 +402,45 @@ for inclusion into the user prompt for the gptel request."
(push (list :text (buffer-substring-no-properties from-pt end))
parts)))
(nreverse parts)))
+(defun gptel-org--annotate-links (beg end)
+ (when gptel-track-media
+ (save-excursion
+ (goto-char beg)
+ (forward-line -1)
+ (let ((link-ovs (cl-delete-if-not
+ (lambda (o) (overlay-get o 'gptel-track-media))
+ (overlays-in (point) end))))
+ (while (re-search-forward gptel-org--link-regex end t)
+ (if-let* ((link (org-element-context))
+ (from (org-element-begin link))
+ (to (org-element-end link))
+ ((gptel-org--link-standalone-p link))
+ (type (org-element-property :type link))
+ ;; (path (org-element-property :path link))
+ ((member type `("attachment" "file"
+ ,@(and (gptel--model-capable-p 'url)
+ '("http" "https" "ftp"))))))
+ (if-let* ((ov (cl-loop
+ for o in (overlays-in from to)
+ if (overlay-get o 'gptel-track-media)
+ return o)))
+ (progn (move-overlay ov from to)
+ (setq link-ovs (delq ov link-ovs)))
+ (setq ov (make-overlay from to nil t))
+ (overlay-put ov 'gptel-track-media t)
+ (overlay-put ov 'before-string
+ (concat
+ (propertize "SEND" 'face '( :inherit success
:box t
+ :height 0.9 :weight
semi-light))
+ (propertize " @" 'face 'success)))
+ (overlay-put ov 'help-echo
+ (propertize "Sending file with gptel requests"))
+ (overlay-put ov 'priority -80))
+ (dolist (o (overlays-in from to))
+ (when (overlay-get o 'gptel-track-media) (delete-overlay o)))))
+ (and link-ovs (mapc #'delete-overlay link-ovs))))
+ `(jit-lock-bounds ,beg . ,end)))
+
(defun gptel-org--link-standalone-p (object)
"Check if link OBJECT is on a line by itself."
(when-let* ((par (gptel-org--element-parent object))