diff --git a/README.md b/README.md index 9f15e9a9..7a72eaa1 100644 --- a/README.md +++ b/README.md @@ -30,22 +30,22 @@ Terms](https://docs.github.com/en/site-policy/github-terms/github-terms-for-addi * Vim, Linux/macOS: - git clone https://github.com/github/copilot.vim.git \ + git clone https://github.com/abdullah8a0/copilot.vim.git \ ~/.vim/pack/github/start/copilot.vim * Neovim, Linux/macOS: - git clone https://github.com/github/copilot.vim.git \ + git clone https://github.com/abdullah8a0/copilot.vim.git \ ~/.config/nvim/pack/github/start/copilot.vim * Vim, Windows (PowerShell command): - git clone https://github.com/github/copilot.vim.git ` + git clone https://github.com/abdullah8a0/copilot.vim.git ` $HOME/vimfiles/pack/github/start/copilot.vim * Neovim, Windows (PowerShell command): - git clone https://github.com/github/copilot.vim.git ` + git clone https://github.com/abdullah8a0/copilot.vim.git ` $HOME/AppData/Local/nvim/pack/github/start/copilot.vim 4. Start Neovim and invoke `:Copilot setup`. diff --git a/autoload/copilot.vim b/autoload/copilot.vim index 2163618f..9a1cd2a4 100644 --- a/autoload/copilot.vim +++ b/autoload/copilot.vim @@ -421,6 +421,12 @@ function! s:Trigger(bufnr, timer) abort return copilot#Suggest() endfunction +function! copilot#IsMapped() abort + return get(g:, 'copilot_assume_mapped') || + \ hasmapto('copilot#AcceptOne(', 'i') +endfunction +let s:is_mapped = copilot#IsMapped() + function! copilot#Schedule(...) abort if !s:has_ghost_text || !copilot#Enabled() call copilot#Clear() @@ -481,7 +487,57 @@ function! copilot#TextQueuedForInsertion() abort endtry endfunction -function! copilot#Accept(...) abort +let s:sugg_buffer = {'sugg': '', 'count': 0, 'text': '', 'valid': v:false} +function! copilot#AcceptOne(...) abort + + if !s:sugg_buffer.valid + let s = copilot#GetDisplayedSuggestion() + if !empty(s) + " split the suggestion into words, keep the trailing space + let s:sugg_buffer = {'sugg': s, 'count': 0, 'text': split(s.text, '\w\W\+\zs'), 'valid': v:true} + " if the text is whitespace, invalidate the buffer + if (len(s:sugg_buffer.text)==0) || !(s:sugg_buffer.text[0] =~# '\S') + let s:sugg_buffer.valid = v:false + endif + endif + endif + + if s:sugg_buffer.valid + let s:suggestion_text = s:sugg_buffer.text[s:sugg_buffer.count] + let s:sugg_buffer.count += 1 + if s:sugg_buffer.count >= len(s:sugg_buffer.text) + let s:sugg_buffer.valid = v:false + unlet! b:_copilot + call copilot#Request('notifyAccepted', {'uuid': s:sugg_buffer.sugg.uuid}) + unlet! s:uuid + call s:ClearPreview() + endif + if s:sugg_buffer.valid && s:sugg_buffer.count == 1 + return repeat("\\", s:sugg_buffer.sugg.outdentSize) . repeat("\", s:sugg_buffer.sugg.deleteSize) . + \ "\\=copilot#TextQueuedForInsertion()\" + endif + return "\\=copilot#TextQueuedForInsertion()\" + endif + + let default = get(g:, 'copilot_tab_fallback', pumvisible() ? "\" : "\t") + if !a:0 + return default + elseif type(a:1) == v:t_string + return a:1 + elseif type(a:1) == v:t_func + try + return call(a:1, []) + catch + call copilot#logger#Exception() + return default + endtry + else + return default + endif +endfunction + + +function! copilot#AcceptAll(...) abort let s = copilot#GetDisplayedSuggestion() if !empty(s.text) unlet! b:_copilot @@ -514,6 +570,27 @@ function! copilot#Accept(...) abort endif endfunction +function! copilot#clearBuffer(...) abort + let s:sugg_buffer.valid = v:false + if a:0 + return a:1 + endif +endfunction + +function! copilot#OnInsertCharPre() abort + " If the user has pressed a key that is not a completion key, clear the + " suggestion buffer. + if !s:is_mapped || !s:dest || !copilot#Enabled() + return + endif + let key = v:char + if key ==# "\t" + return + endif + call copilot#clearBuffer() + return key +endfunction + function! copilot#AcceptWord(...) abort return copilot#Accept(a:0 ? a:1 : '', '\%(\k\@!.\)*\k*') endfunction diff --git a/plugin/copilot.vim b/plugin/copilot.vim index 36a745ab..08a698fe 100644 --- a/plugin/copilot.vim +++ b/plugin/copilot.vim @@ -20,13 +20,19 @@ function! s:ColorScheme() abort hi def link CopilotAnnotation Normal endfunction -function! s:MapTab() abort +" Map and to accept suggestions. +" If is already mapped, use it as a fallback. +" Map to clear the suggestion buffer. +" If is already mapped, use it as a fallback. +function! s:MapShortcuts() abort if get(g:, 'copilot_no_tab_map') || get(g:, 'copilot_no_maps') return endif let tab_map = maparg('', 'i', 0, 1) + let cr_map = maparg('', 'i', 0, 1) if !has_key(tab_map, 'rhs') - imap