Closed rhusiev closed 1 year ago
The complexity/effort to implement this is too high, and the potential gain is too low... imo.
You can't just do vim motions on virtual texts, so that would need a whole bunch of hacks to implement. And supporting a few motions (e.g. t/f/;) using custom implementation is a rabbit-hole, there will always be another one to implement... can't keep implementing those.
I won't be working on it.
The require("copilot.suggestion").accept
function accepts a modifier function to change the suggestion before inserting. This is how accept_line
and accept_word
are implemented:
You can try to implement it yourself by doing something similar.
Try something like this:
vim.keymap.set("i", "<C-g>t", function()
require("copilot.suggestion").accept(function(suggestion)
local char = vim.fn.getcharstr()
local range, text = suggestion.range, suggestion.text
local cursor = vim.api.nvim_win_get_cursor(0)
local _, character = cursor[1], cursor[2]
local _, char_idx = string.find(text, char, character + 1, true)
if char_idx then
suggestion.text = string.sub(text, 1, char_idx - 1)
range["end"].line = range["start"].line
range["end"].character = char_idx - 1
end
return suggestion
end)
end, {
desc = "[copilot] accept suggestion (t)",
silent = true,
})
I'll look into this, but can't say for sure anything, as neither do I have experience in lua(except making init.lua) nor enough spare time at the moment.
You can try the snippet from https://github.com/zbirenbaum/copilot.lua/issues/151#issuecomment-1514782725
I think that would work.
For some reason when I try to use these functions in by keybindings, it just accepts the whole the whole suggestion. I even tried straight up copying the implementation of word suggestion, it stille accepts everything
Are you using the latest version? I just tried the snippet from https://github.com/zbirenbaum/copilot.lua/issues/151#issuecomment-1514782725 and it worked as expected for me.
Make sure :Copilot version
says copilot.lua decc8d43bcd73a288fa689690c20faf0485da217
Oh, ok, thank you!
For anybody searching later.
In the end I have this file:
local last_called = { func = nil, char = nil }
local function till()
if not char then
char = vim.fn.getcharstr()
end
require("copilot.suggestion").accept(function(suggestion)
local range, text = suggestion.range, suggestion.text
local cursor = vim.api.nvim_win_get_cursor(0)
local _, character = cursor[1], cursor[2]
local _, char_idx = string.find(text, char, character + 1, true)
if char_idx then
suggestion.text = string.sub(text, 1, char_idx - 1)
range["end"].line = range["start"].line
range["end"].character = char_idx - 1
else
-- Leave what is already typed
suggestion.text = string.sub(text, 1, character)
range["end"].line = range["start"].line
range["end"].character = character
end
last_called = { func = till, char = char }
return suggestion
end)
end
local function find(char)
if not char then
char = vim.fn.getcharstr()
end
require("copilot.suggestion").accept(function(suggestion)
local range, text = suggestion.range, suggestion.text
local cursor = vim.api.nvim_win_get_cursor(0)
local _, character = cursor[1], cursor[2]
local _, char_idx = string.find(text, char, character + 1, true)
if char_idx then
suggestion.text = string.sub(text, 1, char_idx)
range["end"].line = range["start"].line
range["end"].character = char_idx
else
-- Leave what is already typed
suggestion.text = string.sub(text, 1, character)
range["end"].line = range["start"].line
range["end"].character = character
end
last_called = { func = find, char = char }
return suggestion
end)
end
local function call_last()
if last_called.func then
last_called.func(last_called.char)
end
end
vim.keymap.set("i", "<C-m>t", till, {
desc = "Copilot: accept [t]ill",
silent = true,
})
vim.keymap.set("i", "<C-m>f", find, {
desc = "Copilot: accept [f]ind",
silent = true,
})
vim.keymap.set("i", "<C-m>;", call_last, {
desc = "Copilot: accept last",
silent = true,
})
When pressing <C-m>t
and some symbol, it will accept till that character, not including
<C-m>f
finds that symbol and accepts, including it
<C-m>;
repeats the last of those 2 with the last used character
I am just not sure, whether it is a good practice to use
local last_called = { func = nil, char = nil }
as a way to save the last function called, as I really don't know how lua works, especially with neovim
I am just not sure, whether it is a good practice to use
local last_called = { func = nil, char = nil }
as a way to save the last function called, as I really don't know how lua works, especially with neovim
That's okay. If it's working, it's a perfectly acceptable thing to do.
But you forgot to add char
parameter to the till
function:
local function till()
should be
local function till(char)
right?
Oops, right
Thank you a lot for help
I already love this plugins, as it allows accepting suggestions per word and per line. It would also be awesome if it was possible to use other vim movements. For example, when setting a binding
accept_til="<C-g>"
, the following would be possible(suggestion by copilot I write in the [] brackets):Now press
<C-g>t(
Something similar can also be added for
<C-g>f
. Another possibility would be;
to accept til the next occurrence.It would be very useful in longer line suggestions, where per word acceptance is too small, but accepting the whole line is too much.
I understand that this may be difficult or impossible from the technical view, but I think it is worth looking into.