@@ -122,69 +122,49 @@ local function cancel_inflight_requests()
122122 end )
123123end
124124
125- --- @return string text
126- --- @return integer outdent
127- --- @return integer delete
128- --- @return string uuid
129- local function suggestion_text_with_adjustments ()
130- local ok , text , outdent , delete , uuid = pcall (function ()
125+ local function clear_preview ()
126+ vim . api . nvim_buf_del_extmark ( 0 , copilot . ns_id , copilot . extmark_id )
127+ end
128+
129+ local function get_current_suggestion ()
130+ local ok , choice = pcall (function ()
131131 if
132132 not vim .fn .mode ():match (" ^[iR]" )
133133 or vim .fn .pumvisible () == 1
134134 or vim .b .copilot_suggestion_hidden
135135 or not copilot ._copilot .suggestions
136136 or # copilot ._copilot .suggestions == 0
137137 then
138- return " " , 0 , 0 , " "
138+ return nil
139139 end
140140
141141 local choice = copilot ._copilot .suggestions [copilot ._copilot .choice ]
142142 if not choice or not choice .range or choice .range .start .line ~= vim .fn .line (" ." ) - 1 then
143- return " " , 0 , 0 , " "
143+ return nil
144144 end
145145
146146 if choice .range .start .character ~= 0 then
147147 -- unexpected range
148- return " " , 0 , 0 , " "
148+ return nil
149149 end
150150
151- local line = vim .fn .getline (" ." )
152- local offset = vim .fn .col (" ." ) - 1
153-
154- local typed = vim .fn .strpart (line , 0 , offset )
155- local delete = vim .fn .strpart (line , offset )
156-
157- local uuid = choice .uuid or " "
158-
159- if typed :match (" ^%s*$" ) then
160- local leading = vim .fn .matchstr (choice .text , " ^s+" )
161- local unindented = vim .fn .strpart (choice .text , # leading )
162- if vim .fn .strpart (typed , 0 , # leading ) == leading or unindented ~= delete then
163- return unindented , # typed - # leading , vim .fn .strchars (delete ), uuid
164- end
165- else
166- return vim .fn .strpart (choice .text , offset ), 0 , vim .fn .strchars (delete ), uuid
167- end
151+ return choice
168152 end )
169153
170154 if ok then
171- return text , outdent , delete , uuid
155+ return choice
172156 end
173157
174- return " " , 0 , 0 , " "
175- end
176-
177- local function clear_preview ()
178- vim .api .nvim_buf_del_extmark (0 , copilot .ns_id , copilot .extmark_id )
158+ return nil
179159end
180160
181161local function update_preview ()
182- local text , _ , delete , uuid = suggestion_text_with_adjustments ()
183- text = vim .split (text , " \n " , { plain = true , trimempty = true })
162+ local suggestion = get_current_suggestion ()
163+ local displayLines = suggestion and vim .split (suggestion . displayText , " \n " , { plain = true }) or {}
184164
185165 clear_preview ()
186166
187- if # text == 0 then
167+ if not suggestion or # displayLines == 0 then
188168 return
189169 end
190170
@@ -200,16 +180,16 @@ local function update_preview()
200180 local extmark = {
201181 id = copilot .extmark_id ,
202182 virt_text_win_col = vim .fn .virtcol (" ." ) - 1 ,
203- virt_text = { { text [1 ] .. string.rep ( " " , delete - # text [ 1 ]) , hl_group .CopilotSuggestion } },
183+ virt_text = { { displayLines [1 ], hl_group .CopilotSuggestion } },
204184 }
205185
206- if # text > 1 then
186+ if # displayLines > 1 then
207187 extmark .virt_lines = {}
208- for i = 2 , # text do
209- extmark .virt_lines [i - 1 ] = { { text [i ], hl_group .CopilotSuggestion } }
188+ for i = 2 , # displayLines do
189+ extmark .virt_lines [i - 1 ] = { { displayLines [i ], hl_group .CopilotSuggestion } }
210190 end
211191 if # annot > 0 then
212- extmark .virt_lines [# text ] = { { " " }, { annot , hl_group .CopilotAnnotation } }
192+ extmark .virt_lines [# displayLines ] = { { " " }, { annot , hl_group .CopilotAnnotation } }
213193 end
214194 elseif # annot > 0 then
215195 extmark .virt_text [2 ] = { " " }
@@ -220,10 +200,10 @@ local function update_preview()
220200
221201 vim .api .nvim_buf_set_extmark (0 , copilot .ns_id , vim .fn .line (" ." ) - 1 , vim .fn .col (" ." ) - 1 , extmark )
222202
223- if uuid ~= copilot .uuid then
224- copilot .uuid = uuid
203+ if suggestion . uuid ~= copilot .uuid then
204+ copilot .uuid = suggestion . uuid
225205 with_client (function (client )
226- api .notify_shown (client , { uuid = uuid }, function () end )
206+ api .notify_shown (client , { uuid = suggestion . uuid }, function () end )
227207 end )
228208 end
229209end
@@ -368,33 +348,21 @@ function mod.prev()
368348 end )
369349end
370350
371- local function get_displayed_suggestion ()
372- local text , outdent , delete , uuid = suggestion_text_with_adjustments ()
373- return {
374- uuid = uuid ,
375- text = text ,
376- outdent_size = outdent ,
377- delete_size = delete ,
378- }
379- end
380-
381351function mod .accept ()
382- local s = get_displayed_suggestion ()
383- if vim .fn .empty (s .text ) == 0 then
352+ local suggestion = get_current_suggestion ()
353+ if suggestion and vim .fn .empty (suggestion .text ) == 0 then
384354 reset_state ()
385355 with_client (function (client )
386- api .notify_accepted (client , { uuid = s .uuid }, function () end )
356+ api .notify_accepted (client , { uuid = suggestion .uuid }, function () end )
387357 end )
388358 copilot .uuid = nil
389359 clear_preview ()
390360
391- local keys = vim .api .nvim_replace_termcodes (
392- string.rep (" <Left><Del>" , s .outdent_size ) .. string.rep (" <Del>" , s .delete_size ),
393- true ,
394- false ,
395- true
396- ) or " "
397- vim .api .nvim_feedkeys (keys .. s .text , " n" , false )
361+ -- Hack for 'autoindent', makes the indent persist. Check `:help 'autoindent'`.
362+ vim .api .nvim_feedkeys (vim .api .nvim_replace_termcodes (" <Space><Left><Del>" , true , false , true ), " n" , false )
363+ vim .lsp .util .apply_text_edits ({ { range = suggestion .range , newText = suggestion .text } }, 0 , " utf-16" )
364+ -- Put cursor at the end of current line.
365+ vim .api .nvim_feedkeys (vim .api .nvim_replace_termcodes (" <C-O>$" , true , false , true ), " n" , false )
398366 end
399367end
400368
0 commit comments