Skip to content

Commit f1bd42c

Browse files
committed
Support ways to include lines range in prompts
Fixes editor-code-assistant/eca#164
1 parent b97d50d commit f1bd42c

File tree

1 file changed

+102
-71
lines changed

1 file changed

+102
-71
lines changed

eca-chat.el

Lines changed: 102 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ ECA chat opens in a regular buffer that follows standard
9393
:type 'string
9494
:group 'eca)
9595

96-
(defcustom eca-chat-file-prefix "#"
97-
"The file prefix string used in eca chat buffer."
96+
(defcustom eca-chat-filepath-prefix "#"
97+
"The filepath prefix string used in eca chat buffer."
9898
:type 'string
9999
:group 'eca)
100100

@@ -751,7 +751,7 @@ the prompt/context line."
751751
(expanded-str (get-text-property pos 'eca-chat-expanded-item-str prompt))
752752
(item-type (get-text-property pos 'eca-chat-item-type prompt)))
753753
(if expanded-str
754-
(setq result (concat result (if (eq 'file item-type)
754+
(setq result (concat result (if (eq 'filepath item-type)
755755
(substring expanded-str 1)
756756
expanded-str)))
757757
(setq result (concat result (substring prompt pos next-change))))
@@ -1183,8 +1183,10 @@ If STATIC? return strs with no dynamic values."
11831183
("file" (propertize (concat eca-chat-context-prefix
11841184
(eca-chat--context-presentable-path (plist-get context :path))
11851185
(-when-let ((&plist :start start :end end) (plist-get context :linesRange))
1186-
(format " (%d-%d)" start end)))
1187-
'eca-chat-expanded-item-str (concat eca-chat-context-prefix (plist-get context :path))
1186+
(format "(%d-%d)" start end)))
1187+
'eca-chat-expanded-item-str (concat eca-chat-context-prefix (plist-get context :path)
1188+
(-when-let ((&plist :start start :end end) (plist-get context :linesRange))
1189+
(format ":L%d-L%d" start end)))
11881190
'font-lock-face 'eca-chat-context-file-face))
11891191
("directory" (propertize (concat eca-chat-context-prefix (eca-chat--context-presentable-path (plist-get context :path)))
11901192
'eca-chat-expanded-item-str (concat eca-chat-context-prefix (plist-get context :path))
@@ -1201,7 +1203,7 @@ If STATIC? return strs with no dynamic values."
12011203
"("
12021204
(-some-> (plist-get eca-chat--cursor-context :path)
12031205
(f-filename))
1204-
":"
1206+
" "
12051207
(-some->>
12061208
(-> eca-chat--cursor-context
12071209
(plist-get :position)
@@ -1224,6 +1226,21 @@ If STATIC? return strs with no dynamic values."
12241226
'eca-chat-item-str-length (length context-str)
12251227
'eca-chat-context-item context)))
12261228

1229+
(defun eca-chat--filepath->str (filepath lines-range)
1230+
"Convert FILEPATH and LINES-RANGE to a presentable str in buffer."
1231+
(let* ((item-str (concat eca-chat-filepath-prefix
1232+
(eca-chat--context-presentable-path filepath)
1233+
(-when-let ((&plist :start start :end end) lines-range)
1234+
(format "(%d-%d)" start end)))))
1235+
(propertize item-str
1236+
'eca-chat-item-type 'filepath
1237+
'eca-chat-item-str-length (length item-str)
1238+
'eca-chat-expanded-item-str (concat eca-chat-filepath-prefix
1239+
filepath
1240+
(-when-let ((&plist :start start :end end) lines-range)
1241+
(format ":L%d-L%d" start end)))
1242+
'font-lock-face 'eca-chat-context-file-face)))
1243+
12271244
(defun eca-chat--refresh-context ()
12281245
"Refresh chat context."
12291246
(save-excursion
@@ -1317,15 +1334,10 @@ Add text property to prompt text to match context."
13171334
"Add to files the selected ITEM."
13181335
(let* ((file (get-text-property 0 'eca-chat-completion-item item))
13191336
(start-pos (save-excursion
1320-
(search-backward eca-chat-file-prefix (line-beginning-position) t)))
1321-
(end-pos (point))
1322-
(item-str (concat eca-chat-file-prefix (eca-chat--context-presentable-path (plist-get file :path)))))
1337+
(search-backward eca-chat-filepath-prefix (line-beginning-position) t)))
1338+
(end-pos (point)))
13231339
(delete-region start-pos end-pos)
1324-
(insert (propertize item-str
1325-
'eca-chat-item-type 'file
1326-
'eca-chat-item-str-length (length item-str)
1327-
'eca-chat-expanded-item-str (concat eca-chat-file-prefix (plist-get file :path))
1328-
'font-lock-face 'eca-chat-context-file-face)))
1340+
(insert (eca-chat--filepath->str (plist-get file :path) nil)))
13291341
(insert " "))
13301342

13311343
(defun eca-chat--completion-prompt-exit-function (item _status)
@@ -1485,6 +1497,46 @@ string."
14851497
(string-trim (buffer-substring-no-properties (+ last-prefix-pos (length prefix)) end))
14861498
""))))
14871499

1500+
(declare-function dired-get-marked-files "dired")
1501+
(declare-function treemacs-node-at-point "treemacs")
1502+
(declare-function treemacs-button-get "treemacs")
1503+
1504+
(defun eca-chat--get-contexts-dwim ()
1505+
"Get contexts in a DWIM manner."
1506+
(cond
1507+
((and (buffer-file-name)
1508+
(use-region-p))
1509+
(-let (((start . end) `(,(line-number-at-pos (region-beginning)) . ,(line-number-at-pos (region-end)))))
1510+
(list
1511+
(list :type "file"
1512+
:path (buffer-file-name)
1513+
:linesRange (list :start start :end end)))))
1514+
1515+
((derived-mode-p 'dired-mode)
1516+
(--map (list :type (if (f-dir? it) "directory" "file")
1517+
:path it)
1518+
(dired-get-marked-files)))
1519+
1520+
((derived-mode-p 'treemacs-mode)
1521+
(when-let (path (-some-> (treemacs-node-at-point)
1522+
(treemacs-button-get :path)))
1523+
(list
1524+
(list :type (if (f-dir? path) "directory" "file")
1525+
:path path))))
1526+
1527+
((buffer-file-name)
1528+
(list
1529+
(list :type "file" :path (buffer-file-name))))))
1530+
1531+
(defun eca-chat--insert-prompt (text)
1532+
"Insert TEXT to latest chat prompt point."
1533+
(save-excursion
1534+
(goto-char (eca-chat--prompt-field-start-point))
1535+
(goto-char (line-end-position))
1536+
(when (= (line-beginning-position) (line-end-position))
1537+
(insert " "))
1538+
(insert text)))
1539+
14881540
;; Public
14891541

14901542
(define-derived-mode eca-chat-mode markdown-mode "eca-chat"
@@ -1566,7 +1618,7 @@ Calls CB with the resulting message."
15661618
(funcall cb (format "%s: %s"
15671619
(pcase item-type
15681620
('context "Context")
1569-
('file "File"))
1621+
('filepath "Filepath"))
15701622
(propertize item-str 'face face)))))))
15711623

15721624
(defun eca-chat-completion-at-point ()
@@ -1582,7 +1634,7 @@ Calls CB with the resulting message."
15821634
'contexts-from-prompt)
15831635

15841636
((when-let (last-word (car (last (string-split full-text "[\s]"))))
1585-
(string-match-p (concat "^" eca-chat-file-prefix) last-word))
1637+
(string-match-p (concat "^" eca-chat-filepath-prefix) last-word))
15861638
'files-from-prompt)
15871639

15881640
;; completing commands with `/`
@@ -1616,7 +1668,7 @@ Calls CB with the resulting message."
16161668
items))))
16171669

16181670
('files-from-prompt
1619-
(let ((query (eca-chat--find-typed-query eca-chat-file-prefix)))
1671+
(let ((query (eca-chat--find-typed-query eca-chat-filepath-prefix)))
16201672
(or (gethash query eca-chat--file-completion-cache)
16211673
(-let* (((&plist :files files) (eca-api-request-while-no-input
16221674
(eca-session)
@@ -2161,82 +2213,61 @@ Just open if FORCE-OPEN? is non-nil."
21612213
(when-let ((ov (eca-chat--expandable-content-at-point)))
21622214
(eca-chat--expandable-content-toggle (overlay-get ov 'eca-chat--expandable-content-id) (when force-open? t) (not force-open?)))))
21632215

2164-
(declare-function dired-get-marked-files "dired")
2165-
(declare-function treemacs-node-at-point "treemacs")
2166-
(declare-function treemacs-button-get "treemacs")
2167-
21682216
;;;###autoload
2169-
(defun eca-chat-add-context ()
2170-
"Add context to chat in a DWIM manner.
2217+
(defun eca-chat-add-context-to-system-prompt ()
2218+
"Add context to system prompt in chat in a DWIM manner.
21712219
21722220
- If a region selected, add file with lines range selected.
21732221
- If in Dired, add the marked files/dirs or current file/dir at point.
21742222
- If in Treemacs, add selected file/dir.
21752223
- Else add current file."
21762224
(interactive)
21772225
(eca-assert-session-running (eca-session))
2178-
(let* ((contexts (cond
2179-
((and (buffer-file-name)
2180-
(use-region-p))
2181-
(-let (((start . end) `(,(line-number-at-pos (region-beginning)) . ,(line-number-at-pos (region-end)))))
2182-
(list
2183-
(list :type "file"
2184-
:path (buffer-file-name)
2185-
:linesRange (list :start start :end end)))))
2186-
2187-
((derived-mode-p 'dired-mode)
2188-
(--map (list :type (if (f-dir? it) "directory" "file")
2189-
:path it)
2190-
(dired-get-marked-files)))
2191-
2192-
((derived-mode-p 'treemacs-mode)
2193-
(when-let (path (-some-> (treemacs-node-at-point)
2194-
(treemacs-button-get :path)))
2195-
(list
2196-
(list :type (if (f-dir? path) "directory" "file")
2197-
:path path))))
2198-
2199-
((buffer-file-name)
2200-
(list
2201-
(list :type "file" :path (buffer-file-name)))))))
2226+
(let* ((contexts (eca-chat--get-contexts-dwim)))
22022227
(eca-chat--with-current-buffer (eca-chat--get-last-buffer (eca-session))
22032228
(seq-doseq (context contexts)
22042229
(eca-chat--add-context context)))))
22052230

22062231
;;;###autoload
2207-
(defun eca-chat-add-context-at-point ()
2208-
"Add file content with range at point to chat as context.
2209-
Consider the defun at point unless a region is selected."
2232+
(defun eca-chat-add-context-to-user-prompt ()
2233+
"Add context to user prompt in chat in a DWIM manner.
2234+
2235+
- If a region selected, add file with lines range selected.
2236+
- If in Dired, add the marked files/dirs or current file/dir at point.
2237+
- If in Treemacs, add selected file/dir.
2238+
- Else add current file."
22102239
(interactive)
22112240
(eca-assert-session-running (eca-session))
2212-
(-let (((start . end) (if (use-region-p)
2213-
`(,(line-number-at-pos (region-beginning)) . ,(line-number-at-pos (region-end)))
2214-
(-let (((s . e) (bounds-of-thing-at-point 'defun)))
2215-
`(,(line-number-at-pos s) . ,(line-number-at-pos e)))))
2216-
(path (buffer-file-name)))
2241+
(let* ((contexts (eca-chat--get-contexts-dwim)))
22172242
(eca-chat--with-current-buffer (eca-chat--get-last-buffer (eca-session))
2218-
(eca-chat--add-context (list :type "file"
2219-
:path path
2220-
:linesRange (list :start start :end end))))))
2243+
(seq-doseq (context contexts)
2244+
(eca-chat--insert-prompt (concat (eca-chat--context->str context 'static)
2245+
" ")))
2246+
(eca-chat--select-window)
2247+
(goto-char (line-end-position)))))
22212248

22222249
;;;###autoload
2223-
(defun eca-chat-add-file-context (&optional arg)
2224-
"Add full file to chat as context.
2225-
if ARG is current prefix, ask for file, otherwise add current file."
2226-
(interactive "P")
2250+
(defun eca-chat-add-filepath-to-user-prompt ()
2251+
"Add filepath to user prompt in chat in a DWIM manner.
2252+
2253+
- If a region selected, add filepath with lines range selected.
2254+
- If in Dired, add the marked files/dirs / current file/dir paths at point.
2255+
- If in Treemacs, add selected file/dir path.
2256+
- Else add current filepath."
2257+
(interactive)
22272258
(eca-assert-session-running (eca-session))
2228-
(-let ((path (if (equal arg '(4))
2229-
(read-file-name "Select the file to add to context: " (eca-find-root-for-buffer))
2230-
(buffer-file-name))))
2259+
(let* ((contexts (eca-chat--get-contexts-dwim)))
22312260
(eca-chat--with-current-buffer (eca-chat--get-last-buffer (eca-session))
2232-
(eca-chat--add-context (list :type "file"
2233-
:path path))
2234-
(eca-chat-open (eca-session)))))
2261+
(seq-doseq (context contexts)
2262+
(eca-chat--insert-prompt (concat (eca-chat--filepath->str (plist-get context :path) (plist-get context :linesRange))
2263+
" ")))
2264+
(eca-chat--select-window)
2265+
(goto-char (line-end-position)))))
22352266

22362267
;;;###autoload
2237-
(defun eca-chat-drop-file-context (&optional arg)
2238-
"Drop file from chat as context.
2239-
if ARG is current prefix, ask for file, otherwise add current file."
2268+
(defun eca-chat-drop-context-from-system-prompt (&optional arg)
2269+
"Drop context from system prompt in chat if found.
2270+
if ARG is current prefix, ask for file, otherwise drop current file."
22402271
(interactive "P")
22412272
(eca-assert-session-running (eca-session))
22422273
(-let ((path (if (equal arg '(4))

0 commit comments

Comments
 (0)