@@ -71,6 +71,20 @@ local function set_keymap(keymap)
7171 })
7272 end
7373
74+ if keymap .accept_word then
75+ vim .keymap .set (" i" , keymap .accept_word , mod .accept_word , {
76+ desc = " [copilot] accept suggestion (word)" ,
77+ silent = true ,
78+ })
79+ end
80+
81+ if keymap .accept_line then
82+ vim .keymap .set (" i" , keymap .accept_line , mod .accept_line , {
83+ desc = " [copilot] accept suggestion (line)" ,
84+ silent = true ,
85+ })
86+ end
87+
7488 if keymap .next then
7589 vim .keymap .set (" i" , keymap .next , mod .next , {
7690 desc = " [copilot] next suggestion" ,
@@ -348,22 +362,68 @@ function mod.prev()
348362 end )
349363end
350364
351- function mod .accept ()
365+ --- @param partial ? ' word' | ' line'
366+ local function accept_suggestion (partial )
352367 local suggestion = get_current_suggestion ()
353- if suggestion and vim .fn .empty (suggestion .text ) == 0 then
354- reset_state ()
355- with_client (function (client )
356- api .notify_accepted (client , { uuid = suggestion .uuid }, function () end )
357- end )
358- copilot .uuid = nil
359- clear_preview ()
368+ if not suggestion or vim .fn .empty (suggestion .text ) == 1 then
369+ return
370+ end
371+
372+ reset_state ()
373+ with_client (function (client )
374+ if partial then
375+ -- do not notify_accepted for partial accept.
376+ -- revisit if upstream copilot.vim adds this feature.
377+ return
378+ end
379+
380+ api .notify_accepted (client , { uuid = suggestion .uuid }, function () end )
381+ end )
382+ copilot .uuid = nil
383+ clear_preview ()
384+
385+ local range , newText = suggestion .range , suggestion .text
360386
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 (" <End>" , true , false , true ), " n" , false )
387+ if partial then
388+ local cursor = vim .api .nvim_win_get_cursor (0 )
389+ local _ , character = cursor [1 ], cursor [2 ]
390+
391+ if partial == " word" then
392+ local _ , char_idx = string.find (newText , " %s*%p*[^%s%p]*%s*" , character + 1 )
393+ if not char_idx then
394+ return
395+ end
396+
397+ newText = string.sub (newText , 1 , char_idx )
398+
399+ range [" end" ].line = range [" start" ].line
400+ range [" end" ].character = char_idx
401+ elseif partial == " line" then
402+ local next_char = string.sub (newText , character + 1 , character + 1 )
403+ local _ , char_idx = string.find (newText , next_char == " \n " and " \n %s*[^\n ]*\n %s*" or " \n %s*" , character )
404+ if char_idx then
405+ newText = string.sub (newText , 1 , char_idx )
406+ end
407+ end
366408 end
409+
410+ -- Hack for 'autoindent', makes the indent persist. Check `:help 'autoindent'`.
411+ vim .api .nvim_feedkeys (vim .api .nvim_replace_termcodes (" <Space><Left><Del>" , true , false , true ), " n" , false )
412+ vim .lsp .util .apply_text_edits ({ { range = range , newText = newText } }, 0 , " utf-16" )
413+ -- Put cursor at the end of current line.
414+ vim .api .nvim_feedkeys (vim .api .nvim_replace_termcodes (" <End>" , true , false , true ), " n" , false )
415+ end
416+
417+ function mod .accept ()
418+ accept_suggestion ()
419+ end
420+
421+ function mod .accept_word ()
422+ accept_suggestion (" word" )
423+ end
424+
425+ function mod .accept_line ()
426+ accept_suggestion (" line" )
367427end
368428
369429function mod .dismiss ()
0 commit comments