diff --git a/gptel-curl.el b/gptel-curl.el index e6ca0dd..9c07d71 100644 --- a/gptel-curl.el +++ b/gptel-curl.el @@ -59,6 +59,8 @@ PROMPTS is the data to send, TOKEN is a unique identifier." (push (format "-d%s" data) args) (nreverse (cons url args)))) +;;TODO: The :transformer argument here is an alternate implementation of +;;`gptel-response-filter-functions'. The two need to be unified. ;;;###autoload (defun gptel-curl-get-response (info &optional callback) "Retrieve response to prompt in INFO. @@ -83,7 +85,13 @@ the response is inserted into the current buffer after point." :callback (or callback (if gptel-playback #'gptel--insert-response-stream - #'gptel--insert-response))) + #'gptel--insert-response)) + :transformer (when (or (eq gptel-default-mode 'org-mode) + (eq (buffer-local-value + 'major-mode + (plist-get info :gptel-buffer)) + 'org-mode)) + (gptel--convert-playback-markdown->org))) info)) (if gptel-playback (progn (set-process-sentinel process #'gptel-curl--cleanup-stream) @@ -122,7 +130,8 @@ See `gptel--url-get-response' for details." (status-str (plist-get response :status)) (gptel-buffer (plist-get info :gptel-buffer)) (start-marker (plist-get info :insert-marker)) - (tracking-marker (plist-get info :tracking-marker))) + (tracking-marker (plist-get info :tracking-marker)) + (transformer (plist-get info :transformer))) (if content-str (with-current-buffer gptel-buffer (save-excursion @@ -134,8 +143,9 @@ See `gptel--url-get-response' for details." (set-marker-insertion-type tracking-marker t) (plist-put info :tracking-marker tracking-marker)) - (setq content-str (gptel--transform-response - content-str gptel-buffer)) + (when transformer + (setq content-str (funcall transformer content-str))) + (put-text-property 0 (length content-str) 'gptel 'response content-str) (goto-char tracking-marker) (insert content-str))) diff --git a/gptel.el b/gptel.el index a1836b5..18ed080 100644 --- a/gptel.el +++ b/gptel.el @@ -550,6 +550,58 @@ elements." (insert "/"))))))) (buffer-string))) +(defun gptel--convert-playback-markdown->org () + "" + (let ((in-src-block) + (temp-buf (generate-new-buffer-name "*gptel-temp*")) + (start-pt (make-marker))) + (lambda (str) + (let ((noop-p)) + (with-current-buffer (get-buffer-create temp-buf) + (save-excursion (goto-char (point-max)) + (insert str)) + (when (marker-position start-pt) (goto-char start-pt)) + (save-excursion + (while (re-search-forward "`\\|\\*\\{1,2\\}\\|_" nil t) + (pcase (match-string 0) + ("`" + (cond + ((looking-at "``") + (backward-char 1) + (delete-char 3) + (if in-src-block + (progn (insert "#+end_src") + (setq in-src-block nil)) + (insert "#+begin_src ") + (setq in-src-block t))) + ((looking-at "`\\|$") + (setq noop-p t) + (set-marker start-pt (1- (point))) + (unless (eobp) (forward-char 1))) + ((not in-src-block) (replace-match "=")))) + ((and "**" (guard (not in-src-block))) + (cond + ((looking-at "\\*\\(?:[[:word:]]\\|\s\\)") + (delete-char 1)) + ((looking-back "\\(?:[[:word:]]\\|\s\\)\\*\\{2\\}" + (max (- (point) 3) (point-min))) + (backward-delete-char 1)))) + ((and (or "_" "*") (guard (not in-src-block))) + (when (save-match-data + (save-excursion + (backward-char 2) + (or + (looking-at + "[^[:space:][:punct:]\n]\\(?:_\\|\\*\\)\\(?:[[:space:][:punct:]]\\|$\\)") + (looking-at + "\\(?:[[:space:][:punct:]]\\)\\(?:_\\|\\*\\)\\([^[:space:][:punct:]]\\|$\\)")))) + (backward-delete-char 1) + (insert "/")))))) + (if noop-p + (buffer-substring (point) start-pt) + (prog1 (buffer-substring (point) (point-max)) + (set-marker start-pt (point-max))))))))) + (defun gptel--playback (buf content-str start-pt) "Playback CONTENT-STR in BUF.