@@ -3,61 +3,11 @@ Watchers track changes in Neovim buffers by comparing buffer content over time.
33a state for each watched buffer, recording the current content and last sent content. When
44checked, it compares states to detect line additions, deletions, and modifications.
55]]
6+ local config = require (" codecompanion.config" )
67local log = require (" codecompanion.utils.log" )
78
89local api = vim .api
910
10- --- @class CodeCompanion.Watchers
11- local Watchers = {}
12-
13- function Watchers .new ()
14- return setmetatable ({
15- buffers = {},
16- augroup = api .nvim_create_augroup (" CodeCompanionWatcher" , { clear = true }),
17- }, { __index = Watchers })
18- end
19-
20- --- Watch a buffer for changes
21- --- @param bufnr number
22- --- @return nil
23- function Watchers :watch (bufnr )
24- if self .buffers [bufnr ] then
25- return
26- end
27-
28- if not api .nvim_buf_is_valid (bufnr ) then
29- log :debug (" Cannot watch invalid buffer: %d" , bufnr )
30- return
31- end
32-
33- log :debug (" Starting to watch buffer: %d" , bufnr )
34- local initial_content = api .nvim_buf_get_lines (bufnr , 0 , - 1 , false )
35-
36- self .buffers [bufnr ] = {
37- content = initial_content ,
38- last_sent = initial_content ,
39- changedtick = api .nvim_buf_get_changedtick (bufnr ),
40- }
41-
42- api .nvim_create_autocmd (" BufDelete" , {
43- group = self .augroup ,
44- buffer = bufnr ,
45- callback = function ()
46- self :unwatch (bufnr )
47- end ,
48- })
49- end
50-
51- --- Stop watching a buffer
52- --- @param bufnr number
53- --- @return nil
54- function Watchers :unwatch (bufnr )
55- if self .buffers [bufnr ] then
56- log :debug (" Unwatching buffer %d" , bufnr )
57- self .buffers [bufnr ] = nil
58- end
59- end
60-
6111--- Find the index of a line in a list of lines
6212--- @param line string
6313--- @param lines table
@@ -184,6 +134,57 @@ local function detect_changes(old_lines, new_lines)
184134 return changes
185135end
186136
137+ --- @class CodeCompanion.Watchers
138+ local Watchers = {}
139+
140+ function Watchers .new ()
141+ return setmetatable ({
142+ buffers = {},
143+ augroup = api .nvim_create_augroup (" CodeCompanionWatcher" , { clear = true }),
144+ }, { __index = Watchers })
145+ end
146+
147+ --- Watch a buffer for changes
148+ --- @param bufnr number
149+ --- @return nil
150+ function Watchers :watch (bufnr )
151+ if self .buffers [bufnr ] then
152+ return
153+ end
154+
155+ if not api .nvim_buf_is_valid (bufnr ) then
156+ log :debug (" Cannot watch invalid buffer: %d" , bufnr )
157+ return
158+ end
159+
160+ log :debug (" Starting to watch buffer: %d" , bufnr )
161+ local initial_content = api .nvim_buf_get_lines (bufnr , 0 , - 1 , false )
162+
163+ self .buffers [bufnr ] = {
164+ content = initial_content ,
165+ last_sent = initial_content ,
166+ changedtick = api .nvim_buf_get_changedtick (bufnr ),
167+ }
168+
169+ api .nvim_create_autocmd (" BufDelete" , {
170+ group = self .augroup ,
171+ buffer = bufnr ,
172+ callback = function ()
173+ self :unwatch (bufnr )
174+ end ,
175+ })
176+ end
177+
178+ --- Stop watching a buffer
179+ --- @param bufnr number
180+ --- @return nil
181+ function Watchers :unwatch (bufnr )
182+ if self .buffers [bufnr ] then
183+ log :debug (" Unwatching buffer %d" , bufnr )
184+ self .buffers [bufnr ] = nil
185+ end
186+ end
187+
187188--- Get any changes in a watched buffer
188189--- @param bufnr number
189190--- @return CodeCompanion.Change[] | nil
@@ -210,4 +211,61 @@ function Watchers:get_changes(bufnr)
210211 return changes
211212end
212213
214+ --- Check all watched buffers for changes
215+ --- @param chat CodeCompanion.Chat
216+ function Watchers :check_for_changes (chat )
217+ for _ , ref in ipairs (chat .refs ) do
218+ if ref .bufnr and ref .opts and ref .opts .watched then
219+ local changes = self :get_changes (ref .bufnr )
220+ log :debug (" Checking watched buffer %d, found %d changes" , ref .bufnr , changes and # changes or 0 )
221+
222+ if changes and # changes > 0 then
223+ local changes_text = string.format (
224+ " Changes detected in `%s` (buffer %d):\n " ,
225+ vim .fn .fnamemodify (api .nvim_buf_get_name (ref .bufnr ), " :t" ),
226+ ref .bufnr
227+ )
228+
229+ for _ , change in ipairs (changes ) do
230+ if change .type == " delete" then
231+ changes_text = changes_text
232+ .. string.format (
233+ " Lines %d-%d were deleted:\n ```%s\n %s\n ```\n " ,
234+ change .start ,
235+ change .end_line ,
236+ vim .bo [ref .bufnr ].filetype ,
237+ table.concat (change .lines , " \n " )
238+ )
239+ elseif change .type == " modify" then
240+ changes_text = changes_text
241+ .. string.format (
242+ " Lines %d-%d were modified from:\n ```%s\n %s\n ```\n to:\n ```%s\n %s\n ```\n " ,
243+ change .start ,
244+ change .end_line ,
245+ vim .bo [ref .bufnr ].filetype ,
246+ table.concat (change .old_lines , " \n " ),
247+ vim .bo [ref .bufnr ].filetype ,
248+ table.concat (change .new_lines , " \n " )
249+ )
250+ else -- type == "add"
251+ changes_text = changes_text
252+ .. string.format (
253+ " Lines %d-%d were added:\n ```%s\n %s\n ```\n " ,
254+ change .start ,
255+ change .end_line ,
256+ vim .bo [ref .bufnr ].filetype ,
257+ table.concat (change .lines , " \n " )
258+ )
259+ end
260+ end
261+
262+ chat :add_message ({
263+ role = config .constants .USER_ROLE ,
264+ content = changes_text ,
265+ }, { visible = false })
266+ end
267+ end
268+ end
269+ end
270+
213271return Watchers
0 commit comments