copilot.lua
copilot.lua copied to clipboard
Errors using .accept API
Hello.
I'm trying to use Copilot in a 'super-tab' fashion like this:
local keys = {
['tab'] = vim.api.nvim_replace_termcodes('<Tab>', true, true, true),
['ctrl-y'] = vim.api.nvim_replace_termcodes('<C-y>', true, true, true),
['ctrl-tab'] = vim.api.nvim_replace_termcodes('<C-Tab>', true, true, true),
}
_G.tab_action = function()
if vim.fn.pumvisible() ~= 0 then
return keys['ctrl-y']
elseif require("copilot.suggestion").is_visible() then
require("copilot.suggestion").accept()
return
else
return keys['tab']
end
end
vim.keymap.set('i', '<Tab>', 'v:lua._G.tab_action()', { expr = true })
However, whenever I try to use tab to fill in a suggestion I get the following Neovim here:
E5108: Error executing lua /usr/share/nvim/runtime/lua/vim/lsp/util.lua:515: E565: Not allowed to change text or change window
stack traceback:
[C]: in function 'nvim_buf_set_text'
/usr/share/nvim/runtime/lua/vim/lsp/util.lua:515: in function 'apply_text_edits'
...ite/pack/deps/opt/copilot.lua/lua/copilot/suggestion.lua:487: in function 'accept'
/home/louis/git/dotfiles/config/nvim/init.lua:503: in function </home/louis/git/dotfiles/config/nvim/init.lua:499>
same here
Same here. I'm using neovim 0.9.4,.
It only happens when using require("copilot.suggestion").accept
, if I use require("copilot.suggestion").accept_word
it works.
Here's a stack trace:
E5108: Error executing lua: ...-unwrapped-0.9.4/share/nvim/runtime/lua/vim/lsp/util.lua:501: Failed to save undo information
stack traceback:
[C]: in function 'nvim_buf_set_text'
...-unwrapped-0.9.4/share/nvim/runtime/lua/vim/lsp/util.lua:501: in function 'apply_text_edits'
...l/share/nvim/lazy/copilot.lua/lua/copilot/suggestion.lua:487: in function 'accept'
/home/vini/.config/nvim/lua/plugins/coding.lua:10: in function </home/vini/.config/nvim/lua/plugins/coding.lua:8>
been awhile, and while the error seems to me be present, trying to use tab to complete is just broken. I traced it out a bit, and it seems like it begins to fail for some reason at the lsp replace text methods :(
vim.keymap.set('i', '<Tab>', 'v:lua._G.tab_action()', { expr = true })
Idk if this will fix your issue, but you're better off passing a function here:
vim.keymap.set('i', '<Tab>', _G.tab_action, { expr = true })
Also, you can wrap the _G.tab_action
reference in a function if you need tab_action
to be looked-up dynamically every time the mapping executes:
vim.keymap.set('i', '<Tab>', function() return _G.tab_action() end, { expr = true })
That's kinda strange.
Here's what :help E565
says:
*E565*
Note: While completion is active Insert mode can't be used recursively and
buffer text cannot be changed. Mappings that somehow invoke ":normal i.."
will generate an E565 error.
So basically you cannot change the buffer's text while in completion mode (i.e. completion window is visible).
Edit (I figured it out)
If you compare the default mappings made by this plugin with yours, the main difference is that yours is an expr
mapping. That's what's causing this issue (it's not necessarily a problem with the plugin). Apparently, changing buffer text is also prohibited while inside an expr
mapping. Maybe that counts as using insert mode recursively
, but some more detail wouldn't hurt that error message/explanation for E565
(edit: although technically this is also explained in :help :map-<expr>
).
Minimal reproduction:
vim.keymap.set(
'i',
'<Tab>',
function() vim.api.nvim_buf_set_lines(0, -1, -1, true, { 'NEW' }) end,
{
expr = true,
}
)
The problem is not with the plugin or the vim.lsp
utility function, but with your mapping. There's multiple ways to work around this. Some ideas:
- Don't use an
expr
mapping at all, use a regular mapping. In this case you can usenvim_feedkeys()
instead for the keys that you were otherwise returning in theexpr
mapping. Even better if you can accomplish what you need to without feeding any keys. - Exit insert mode before changing the buffer (or before calling a function which does). Insert mode could then be reentered on the next tick of the event loop with
vim.cmd 'startinsert'
. Probably not a great solution (if it even works). - Schedule/defer the buffer changes so that they occur after the
expr
mapping has finished. For example you can usevim.schedule(require("copilot.suggestion").accept)
. Since you are using anexpr
mapping, you can also just return'<Cmd>lua require("copilot.suggestion").accept()<CR>'
(which is probably better than scheduling the call and this is also the workaround that the vim docs recommend forexpr
mappings).