[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/gptel 8e0de5dd25 13/14: gptel: overhaul bounds, support mo
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/gptel 8e0de5dd25 13/14: gptel: overhaul bounds, support more text property types |
Date: |
Fri, 7 Mar 2025 04:03:51 -0500 (EST) |
branch: elpa/gptel
commit 8e0de5dd25b85122e35da9e2e3a7d09e2e46ece8
Author: Psionik K <73710933+psionic-k@users.noreply.github.com>
Commit: Karthik Chikmagalur <karthikchikmagalur@gmail.com>
gptel: overhaul bounds, support more text property types
Store the chat buffer's gptel bounds in an alist for compactness.
Each entry maps a text designation type (`response', `tool',
`ignore' etc) to a list of bounds. Each bound is a
list (previously a cons) of the form (BEG END) or (BEG END VAL).
VAL is used for text properties like tool calls that can store an
ID.
The previous variant of gptel's bounds (as a list of conses)
will continue to be supported.
* gptel-org.el (gptel-org--restore-state, gptel-org--save-state):
Update for new bounds data type.
* gptel.el (gptel--in-response-p, gptel--restore-props,
gptel--restore-state): New function 'gptel--restore-props' to
restore the gptel text-property from either of the supported
bounds types. Other modifications are to handle the fact that
the `gptel' text-property can have many valid values now.
---
gptel-org.el | 9 ++++-----
gptel.el | 58 +++++++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 51 insertions(+), 16 deletions(-)
diff --git a/gptel-org.el b/gptel-org.el
index 6550425310..ace590e5cd 100644
--- a/gptel-org.el
+++ b/gptel-org.el
@@ -50,6 +50,7 @@
(declare-function gptel-backend-name "gptel")
(declare-function gptel--parse-buffer "gptel")
(declare-function gptel--parse-directive "gptel")
+(declare-function gptel--restore-props "gptel")
(declare-function org-entry-get "org")
(declare-function org-entry-put "org")
(declare-function org-with-wide-buffer "org-macs")
@@ -408,10 +409,7 @@ ARGS are the original function call arguments."
(condition-case status
(progn
(when-let* ((bounds (org-entry-get (point-min) "GPTEL_BOUNDS")))
- (mapc (pcase-lambda (`(,beg . ,end))
- (add-text-properties
- beg end '(gptel response front-sticky (gptel))))
- (read bounds)))
+ (gptel--restore-props (read bounds)))
(pcase-let ((`(,system ,backend ,model ,temperature ,tokens ,num)
(gptel-org--entry-properties (point-min))))
(when system (setq-local gptel--system-message system))
@@ -470,7 +468,8 @@ non-nil (default), display a message afterwards."
(letrec ((write-bounds
(lambda (attempts)
(let* ((bounds (gptel--get-buffer-bounds))
- (offset (caar bounds))
+ ;; first value of ((prop . ((beg end val)...))...)
+ (offset (caadar bounds))
(offset-marker (set-marker (make-marker) offset)))
(org-entry-put (point-min) "GPTEL_BOUNDS"
(prin1-to-string (gptel--get-buffer-bounds)))
diff --git a/gptel.el b/gptel.el
index bf90a0f91c..52810fd9ff 100644
--- a/gptel.el
+++ b/gptel.el
@@ -998,12 +998,18 @@ FILE is assumed to exist and be a regular file."
(save-restriction
(widen)
(goto-char (point-max))
- (let ((prop) (bounds))
- (while (setq prop (text-property-search-backward
- 'gptel 'response t))
- (push (cons (prop-match-beginning prop)
- (prop-match-end prop))
- bounds))
+ (let ((bounds) (prev-pt (point)))
+ (while (and (/= prev-pt (point-min))
+ (goto-char (previous-single-property-change
+ (point) 'gptel nil (point-min))))
+ (when-let* ((prop (get-char-property (point) 'gptel)))
+ (let* ((prop-name (if (symbolp prop) prop (car prop)))
+ (val (when (consp prop) (cdr prop)))
+ (bound (if val
+ (list (point) prev-pt val)
+ (list (point) prev-pt))))
+ (push bound (alist-get prop-name bounds))))
+ (setq prev-pt (point)))
bounds))))
(define-obsolete-function-alias
@@ -1022,7 +1028,7 @@ FILE is assumed to exist and be a regular file."
(defun gptel--in-response-p (&optional pt)
"Check if position PT is inside a gptel response."
- (get-char-property (or pt (point)) 'gptel))
+ (eq (get-char-property (or pt (point)) 'gptel) 'response))
(defun gptel--at-response-history-p (&optional pt)
"Check if gptel response at position PT has variants."
@@ -1139,6 +1145,39 @@ Valid JSON unless NO-JSON is t."
;;; Saving and restoring state
+(defun gptel--restore-props (bounds-alist)
+ "Restore text properties from BOUNDS-ALIST.
+BOUNDS-ALIST is (PROP . BOUNDS). BOUNDS is a list of BOUND. Each BOUND
+is either (BEG END VAL) or (BEG END).
+
+For (BEG END VAL) forms, even if VAL is nil, the gptel property will be
+set to (PROP . VAL). For (BEG END) forms, except when PROP is response,
+the gptel property is set to just PROP.
+
+The legacy structure, a list of (BEG . END) is also supported and will be
+applied before being re-persisted in the new structure."
+ (if (symbolp (caar bounds-alist))
+ (mapc
+ (lambda (bounds)
+ (let* ((prop (pop bounds)))
+ (mapc
+ (lambda (bound)
+ (let ((prop-has-val (> (length bound) 2)))
+ (add-text-properties
+ (pop bound) (pop bound)
+ (if (eq prop 'response)
+ '(gptel response front-sticky (gptel))
+ (list 'gptel
+ (if prop-has-val
+ (cons prop (pop bound))
+ prop))))))
+ bounds)))
+ bounds-alist)
+ (mapc (lambda (bound)
+ (add-text-properties
+ (car bound) (cdr bound) '(gptel response front-sticky (gptel))))
+ bounds-alist)))
+
(defun gptel--restore-state ()
"Restore gptel state when turning on `gptel-mode'."
(when (buffer-file-name)
@@ -1147,10 +1186,7 @@ Valid JSON unless NO-JSON is t."
(require 'gptel-org)
(gptel-org--restore-state))
(when gptel--bounds
- (mapc (pcase-lambda (`(,beg . ,end))
- (add-text-properties
- beg end '(gptel response front-sticky (gptel))))
- gptel--bounds)
+ (gptel--restore-props gptel--bounds)
(message "gptel chat restored."))
(when gptel--backend-name
(if-let* ((backend (alist-get
- [nongnu] elpa/gptel 13757388ca 09/14: gptel-gemini: Parse tool results from buffer, (continued)
- [nongnu] elpa/gptel 13757388ca 09/14: gptel-gemini: Parse tool results from buffer, ELPA Syncer, 2025/03/07
- [nongnu] elpa/gptel 1a3b393a4b 10/14: gptel-anthropic: Parse tool results from buffer, ELPA Syncer, 2025/03/07
- [nongnu] elpa/gptel aded7787d6 04/14: gptel: Make tool call records in buffer recoverable, ELPA Syncer, 2025/03/07
- [nongnu] elpa/gptel 00f39ea179 08/14: gptel: Ignore blank/whitespace messages, ELPA Syncer, 2025/03/07
- [nongnu] elpa/gptel 2a6f714d30 14/14: README: Fix typo (#676), ELPA Syncer, 2025/03/07
- [nongnu] elpa/gptel d222ed823a 05/14: gptel-org: Always create prompt in a temp buffer, ELPA Syncer, 2025/03/07
- [nongnu] elpa/gptel e53076f43e 12/14: test: Update submodule, ELPA Syncer, 2025/03/07
- [nongnu] elpa/gptel cb420b6928 03/14: gptel: Breaking change to gptel-request API, ELPA Syncer, 2025/03/07
- [nongnu] elpa/gptel e96ca2aa46 07/14: gptel-openai: Parse tool results from buffer, ELPA Syncer, 2025/03/07
- [nongnu] elpa/gptel 1d0b3d112b 11/14: gptel-ollama: Parse tool results from buffer, ELPA Syncer, 2025/03/07
- [nongnu] elpa/gptel 8e0de5dd25 13/14: gptel: overhaul bounds, support more text property types,
ELPA Syncer <=
- [nongnu] elpa/gptel 56623b9889 06/14: gptel-org: Tool result handling for Org, ELPA Syncer, 2025/03/07