Comments (29)
word by word and line by line. I second this as well
from codeium.vim.
I second this request. I have found myself needing this feature many times.
from codeium.vim.
Hello guys,
I have implemented a quick and dirty solution for NeoVim in lua. I've been using it for several weeks, it handles word and line completion quite well (line completion has some indentation problems with auto indenting).
I thought I share it with you, maybe someone has some more time to clear it up a bit.
use {
'Exafunction/codeium.vim',
config = function ()
vim.g.codeium_no_map_tab = true
vim.keymap.set('i', '<M-BS>', function () return vim.fn['codeium#Accept']() end, { expr = true })
vim.keymap.set('i', '<M-Right>', function () return vim.fn['codeium#CycleCompletions'](1) end, { expr = true })
vim.keymap.set('i', '<M-Left>', function () return vim.fn['codeium#CycleCompletions'](-1) end, { expr = true })
vim.keymap.set('i', '<M-Esc>', function () return vim.fn['codeium#Clear']() end, { expr = true })
-- Line completion
vim.keymap.set('i', '<M-Enter>', function ()
local fullCompletion = vim.api.nvim_eval("b:_codeium_completions.items[b:_codeium_completions.index].completionParts[0].text")
local cursor = vim.api.nvim_win_get_cursor(0)
local line = vim.api.nvim_get_current_line()
local completion = string.gsub(fullCompletion, '\n.*$', '')
if (completion ~= '') then
vim.defer_fn(function ()
local nline = line:sub(0, cursor[2]) .. completion .. line:sub(cursor[2] + 1)
vim.api.nvim_set_current_line(nline)
vim.api.nvim_win_set_cursor(0, { cursor[1], cursor[2] + #completion })
print('pre enter ' .. vim.inspect(cursor))
vim.api.nvim_feedkeys('\n', 'i', true)
end, 0)
end
end, { expr = true })
-- Word completion
vim.keymap.set('i', '<M-Space>', function ()
local fullCompletion = vim.api.nvim_eval("b:_codeium_completions.items[b:_codeium_completions.index].completionParts[0].text")
local cursor = vim.api.nvim_win_get_cursor(0)
local line = vim.api.nvim_get_current_line()
local completion = string.match(fullCompletion, '[ ,;.]*[^ ,;.]+')
vim.defer_fn(function ()
if (string.match(completion, '^\t')) then
vim.api.nvim_buf_set_lines(0, cursor[1], cursor[1], true, { completion })
vim.api.nvim_win_set_cursor(0, { cursor[1] + 1, #completion })
else
local nline = line:sub(0, cursor[2]) .. completion .. line:sub(cursor[2] + 1)
vim.api.nvim_set_current_line(nline)
vim.api.nvim_win_set_cursor(0, { cursor[1], cursor[2] + #completion })
end
end, 0)
end, { expr = true })
end
}
from codeium.vim.
Me too :)
The more I work with codeium the more I see useless suggestions in another lines. Accepting partial completion word-by-word or by-line would be nice.
from codeium.vim.
As a small update, we've confirmed that per-word/per-line is something we could probably do across all editors. Before we figure out what it looks like, I want to ask anyone who is familiar with the copilot.lua, etc., what are the word boundaries that we should be using to make this most useful?
from codeium.vim.
Hello guys,
I have implemented a quick and dirty solution for NeoVim in lua. I've been using it for several weeks, it handles word and line completion quite well (line completion has some indentation problems with auto indenting). I thought I share it with you, maybe someone has some more time to clear it up a bit.
use { 'Exafunction/codeium.vim', config = function () vim.g.codeium_no_map_tab = true vim.keymap.set('i', '<M-BS>', function () return vim.fn['codeium#Accept']() end, { expr = true }) vim.keymap.set('i', '<M-Right>', function () return vim.fn['codeium#CycleCompletions'](1) end, { expr = true }) vim.keymap.set('i', '<M-Left>', function () return vim.fn['codeium#CycleCompletions'](-1) end, { expr = true }) vim.keymap.set('i', '<M-Esc>', function () return vim.fn['codeium#Clear']() end, { expr = true }) -- Line completion vim.keymap.set('i', '<M-Enter>', function () local fullCompletion = vim.api.nvim_eval("b:_codeium_completions.items[b:_codeium_completions.index].completionParts[0].text") local cursor = vim.api.nvim_win_get_cursor(0) local line = vim.api.nvim_get_current_line() local completion = string.gsub(fullCompletion, '\n.*$', '') if (completion ~= '') then vim.defer_fn(function () local nline = line:sub(0, cursor[2]) .. completion .. line:sub(cursor[2] + 1) vim.api.nvim_set_current_line(nline) vim.api.nvim_win_set_cursor(0, { cursor[1], cursor[2] + #completion }) print('pre enter ' .. vim.inspect(cursor)) vim.api.nvim_feedkeys('\n', 'i', true) end, 0) end end, { expr = true }) -- Word completion vim.keymap.set('i', '<M-Space>', function () local fullCompletion = vim.api.nvim_eval("b:_codeium_completions.items[b:_codeium_completions.index].completionParts[0].text") local cursor = vim.api.nvim_win_get_cursor(0) local line = vim.api.nvim_get_current_line() local completion = string.match(fullCompletion, '[ ,;.]*[^ ,;.]+') vim.defer_fn(function () if (string.match(completion, '^\t')) then vim.api.nvim_buf_set_lines(0, cursor[1], cursor[1], true, { completion }) vim.api.nvim_win_set_cursor(0, { cursor[1] + 1, #completion }) else local nline = line:sub(0, cursor[2]) .. completion .. line:sub(cursor[2] + 1) vim.api.nvim_set_current_line(nline) vim.api.nvim_win_set_cursor(0, { cursor[1], cursor[2] + #completion }) end end, 0) end, { expr = true }) end }
These are the coolest bindings I've seen
from codeium.vim.
Does anyone feel confident enough to make a PR that adds native support for this
Almost there. I've been working on this and pretty happy with the results so far. I'll submit a PR soon.
from codeium.vim.
This is an interesting one. Do you have an example of a situation recently where you found yourself really wishing for this?
from codeium.vim.
I see no inconvenience just follow the ghost text and type the next word(~10 chars on average) ourselves.
There's also no issue in pressing ← 10 times, but we tend to prefer db. That's kind of the point of using Vim/Neovim. Saving a few keystrokes over a long period of time to preserve our sanity (and our fingers) in the long run.
When most plugins don't provide a feature, we probably need to think about why they don't, too.
copilot.lua
does implement this.
In fact, in implements both a 'by word' completion (complete the current word, leaving the rest of the completion intact), and a 'by line' completion (complete the current line, leaving the rest of the completion intact). I find myself using the line completion quite more often than the 'full' completion.
That would mean the ghost text will become a requirement for this feature, then it will conflict with the on-the-plan feature proposed in #3.
It doesn't have to conflict with support for a completion engine, if you keep the functionalities separate.
I use both copilot.lua
and copilot-cmp
. copilot-cmp
has nothing that we are discussing in here, nor is it aware of any of it, and just hooks to nvim-cmp
. copilot.lua
on the other hand, which provides the ghost text, provides the functionality of 'by-word' and 'by-line' completion.
That is, disabling ghost-text (and just using nvim-cmp
for completions) would just disable this feature.
from codeium.vim.
I heavily third this request. I'd go further and also suggest adding a 'line-by-line' completion.
It's quite common for codeium.vim
to have a completion that is perfect for the current line, but also attaches 1-to-3 unnecessary (or wrong) lines extra. I constantly find myself completing everything, and then deleting the extra lines, keeping only one. Having a feature for that would be great.
copilot.lua
has this feature, and I tend to use it a lot.
from codeium.vim.
An opinion about the line-by-line completion (which is mostly a critique of copilot.lua's implementation):
When you complete the current line on copilot.lua, the cursor automatically jumps to the next line (i.e. it adds a newline in the end of the completion). It's quite common to find myself completing, and then removing the superfluous empty line added. However, I understand why this is the case: It's mostly so you can 'chain complete' (i.e. repeatedly press the mapping to complete the next lines if you wish).
Here's my proposed solution:
- If there's some completion in the current line, complete the current line (without adding a newline, keeping the cursor at the end of the completion).
- If there's nothing to complete in the current line, but there is a remaining completion below, complete the next line (so the cursor would land at the end of the next completion).
- If there's no completion at all, do nothing.
This implementation makes possible to chain complete, without adding a superfluous line in the case where you only want one line.
from codeium.vim.
Vim has build in meaning of "word" and "WORD". First one is build of letters, digits and underscores. Second one is a sequence of non-blank chars. See :help word, :help WORD
I think that those options will be most intuitive for vim users.
Altenarnative way may be something like this: when completion is accepted, mode is changed to Visual and it allows to use standard Vim movement commands to select as much of suggestion as we want, and then another "tab" confirms accepted part.
from codeium.vim.
I second klew's idea of using the built-in 'word' and/or 'WORD' from vim.
Specially because most users will be familiar with them, and each user can already customize the definition themselves (e.g. the iskeyword
option).
from codeium.vim.
It would be nice to implement an option to let the user choose between an autocomplete based on "word" or "WORD".
from codeium.vim.
This seems to be working:
function! CompleteNextWord()
let dict = copilot#GetDisplayedSuggestion()
let text = dict['text']
let first = split(text, ' ')[0]
return first . ' '
endfunction
inoremap <silent><expr> <C-J> CompleteNextWord()
from codeium.vim.
@aranc In which file did you put that function?
from codeium.vim.
@aranc In which file did you put that function?
Hi, I added it to my .vimrc
from codeium.vim.
@aranc-pix Are your dotfiles public? Also i see that you use copilot in the function. Is this working with codeium?
from codeium.vim.
@aranc-pix Are your dotfiles public? Also i see that you use copilot in the function. Is this working with codeium?
Oops, seems like I thought this was an "nvim copilot" discussion and not codeium
not public. I only added those lines for word-by-word copilot support. but it's probably not relevant to codeium
from codeium.vim.
I wrote a version of line and word completion in vimscript based on the lua implementation by @szilu, with a few changes and my own preferred key mappings. After a few days of use, it is also working OK for me. During autocompletion there is sometimes a lag with a race condition, where my typing will get ahead of codeium and some characters (usually parentheses) are placed before the completed text instead of after it. However, this is intermittent and may be general codeium behavior on my workstation, I am not sure. It might not happen on a faster machine.
`
" Line completion
imap <C-.> call CompleteLine()
function! CompleteLine() abort
let fullCompletion = b:_codeium_completions.items[b:_codeium_completions.index].completionParts[0].text
let curpos = getcurpos()
let line = getline(".")
let completion = substitute(fullCompletion, "\n.*$", "", "")
if completion != ''
let nline = line[0:curpos[2]] . completion . line[curpos[2] + 1:]
call setline(curpos[1], nline)
call cursor(line, len(nline) + 1)
endif
endfunction
" Word completion
imap <C-,> call CompleteWord()
function! CompleteWord() abort
let fullCompletion = b:_codeium_completions.items[b:_codeium_completions.index].completionParts[0].text
let curpos = getcurpos()
let line = getline(".")
let completion = matchstr(fullCompletion, '[ ,;.\t]*[^ ,;.\t]+')
if completion != ''
let nline = line[0:curpos[2]] . completion . line[curpos[2] + 1:]
call setline(curpos[1], nline)
call cursor(line, len(nline) + 1)
endif
endfunction
`
BTW, I am running codeium.vim on Windows 10. I mention this because I haven't noticed other postings from Windows users.
from codeium.vim.
@pqn what is the status of getting this feature implemented? Very excited to see this supported without .vimrc tweaks
from codeium.vim.
For those that use whichkey
, I've made a version of the mappings suggested by @fwy with some error handling for when there are no completions:
-- Executes a normal key presses. Used to fallback to the normal behavior of the keys in the keymap
local function fallback(key)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<C-g>u" .. key .. "<C-g>u", true, true, true), "n", true)
end
-- See if there are Codeium completions. If there are, return them
local function getCodeiumCompletions()
local status, completions = pcall(function()
return vim.api.nvim_eval "b:_codeium_completions.items[b:_codeium_completions.index].completionParts[0].text"
end)
if status then
return completions
else
return nil
end
end
M.codeium = {
i = {
["<A-l>"] = {
function()
return vim.fn["codeium#Accept"]()
end,
"Accept completion",
opts = { expr = true, silent = true },
},
["<A-Bslash>"] = {
function()
return vim.fn["codeium#Complete"]()
end,
"Manually trigger suggestion",
opts = { expr = true, silent = true },
},
["<A-]>"] = {
function()
return vim.fn["codeium#CycleCompletions"](1)
end,
"Cycle completions forwards",
opts = { expr = true, silent = true },
},
["<A-[>"] = {
function()
return vim.fn["codeium#CycleCompletions"](-1)
end,
"Cycle completions backwards",
opts = { expr = true, silent = true },
},
["<A-BS>"] = {
function()
return vim.fn["codeium#Clear"]()
end,
"Clear completion",
opts = { expr = true },
},
["<C-Right>"] = {
function()
local fullCompletion = getCodeiumCompletions()
local cursor = vim.api.nvim_win_get_cursor(0)
local line = vim.api.nvim_get_current_line()
if not fullCompletion then
return fallback "<C-Right>"
end
local completion = fullCompletion:match "[ ,;.]*[^ ,;.]+"
vim.defer_fn(function()
if string.match(completion, "^\t") then
vim.api.nvim_buf_set_lines(0, cursor[1], cursor[1], true, { completion })
vim.api.nvim_win_set_cursor(0, { cursor[1] + 1, #completion })
else
local nline = line:sub(0, cursor[2]) .. completion .. line:sub(cursor[2] + 1)
vim.api.nvim_set_current_line(nline)
vim.api.nvim_win_set_cursor(0, { cursor[1], cursor[2] + #completion })
end
end, 0)
end,
"Accept next word in completion",
opts = { expr = true },
},
["<Right>"] = {
function()
local fullCompletion = getCodeiumCompletions()
local cursor = vim.api.nvim_win_get_cursor(0)
local line = vim.api.nvim_get_current_line()
if not fullCompletion then
return fallback "<Right>"
end
local completion = fullCompletion:gsub("\n.*$", "")
if completion == "" then
return fallback "<Right>"
end
vim.defer_fn(function()
local nline = line:sub(0, cursor[2]) .. completion .. line:sub(cursor[2] + 1)
vim.api.nvim_set_current_line(nline)
vim.api.nvim_win_set_cursor(0, { cursor[1], cursor[2] + #completion })
fallback "<CR>"
end, 0)
end,
"Accept next line in completion",
opts = { expr = true },
},
},
}
from codeium.vim.
I had this in copilot and I'm trying codeium and I find it super important. Here is how I've done it which seems to work well (inspired by the two snippets above) and is a lot shorter:
local expr_opts = {
noremap = true,
silent = true,
expr = true,
-- With expr = true, replace_keycodes is set to true. See https://github.com/orgs/community/discussions/29817
-- We need to set it to false to avoid extraneous caracters when accepting a suggestion.
replace_keycodes = false,
}
local function getCodeiumCompletions()
local status, completion = pcall(function()
return vim.api.nvim_eval("b:_codeium_completions.items[b:_codeium_completions.index].completionParts[0].text")
end)
if status then
return completion
else
return ""
end
end
local function accept_one_line()
local text = getCodeiumCompletions()
return vim.fn.split(text, [[[\n]\zs]])[1] .. "\n"
end
local function accept_one_word()
local text = getCodeiumCompletions()
return vim.fn.split(text, [[\(\w\+\|\W\+\)\zs]])[1]
end
vim.keymap.set("i", "<C-L>", accept_one_line, expr_opts)
vim.keymap.set("i", "<C-G><C-L>", accept_one_word, expr_opts)
There is some wonkiness with indentation and completing at the end of a line, maybe someone else can figure out something simple to fix that.
from codeium.vim.
I had this in copilot and I'm trying codeium and I find it super important. Here is how I've done it which seems to work well (inspired by the two snippets above) and is a lot shorter:
local expr_opts = { noremap = true, silent = true, expr = true, -- With expr = true, replace_keycodes is set to true. See https://github.com/orgs/community/discussions/29817 -- We need to set it to false to avoid extraneous caracters when accepting a suggestion. replace_keycodes = false, } local function getCodeiumCompletions() local status, completion = pcall(function() return vim.api.nvim_eval("b:_codeium_completions.items[b:_codeium_completions.index].completionParts[0].text") end) if status then return completion else return "" end end local function accept_one_line() local text = getCodeiumCompletions() return vim.fn.split(text, [[[\n]\zs]])[1] .. "\n" end local function accept_one_word() local text = getCodeiumCompletions() return vim.fn.split(text, [[\(\w\+\|\W\+\)\zs]])[1] end vim.keymap.set("i", "<C-L>", accept_one_line, expr_opts) vim.keymap.set("i", "<C-G><C-L>", accept_one_word, expr_opts)There is some wonkiness with indentation and completing at the end of a line, maybe someone else can figure out something simple to fix that.
Pretty neat. Thanks
from codeium.vim.
I had this in copilot and I'm trying codeium and I find it super important. Here is how I've done it which seems to work well (inspired by the two snippets above) and is a lot shorter:
local expr_opts = { noremap = true, silent = true, expr = true, -- With expr = true, replace_keycodes is set to true. See https://github.com/orgs/community/discussions/29817 -- We need to set it to false to avoid extraneous caracters when accepting a suggestion. replace_keycodes = false, } local function getCodeiumCompletions() local status, completion = pcall(function() return vim.api.nvim_eval("b:_codeium_completions.items[b:_codeium_completions.index].completionParts[0].text") end) if status then return completion else return "" end end local function accept_one_line() local text = getCodeiumCompletions() return vim.fn.split(text, [[[\n]\zs]])[1] .. "\n" end local function accept_one_word() local text = getCodeiumCompletions() return vim.fn.split(text, [[\(\w\+\|\W\+\)\zs]])[1] end vim.keymap.set("i", "<C-L>", accept_one_line, expr_opts) vim.keymap.set("i", "<C-G><C-L>", accept_one_word, expr_opts)There is some wonkiness with indentation and completing at the end of a line, maybe someone else can figure out something simple to fix that.
One thing with this is that, if the next thing in the completion is a space, you have to accept it and then accept it again to get the next non-space thing.
One way to fix that is by ending that function like this:
local word_delimeters = " %(%)%[%]%{%}',\"`|%.%%"
local nextword_pattern = "[" .. word_delimeters .. "]*[^" .. word_delimeters .. "]+"
return full_completion:match(nextword_pattern)
Populate the word delimiters with whatever you prefer. This has been working well.
from codeium.vim.
This proved to work well for me, no funny spacing behavior.
local function accept_one_word()
local text = getCodeiumCompletions()
-- Adjusting the pattern to consider a broader range of non-whitespace characters, including punctuation.
local first_non_space = text:find "%S" -- Find the index of the first non-space character.
if not first_non_space then return "" end -- If there's no non-space character, return an empty string.
-- Capture the first word along with any immediately preceding spaces.
-- The pattern looks for any leading spaces, followed by a sequence of non-space characters.
local captured = text:match("^(%s*%S+)", first_non_space)
if not captured then return "" end -- Safety check, though at this point captured should always be non-nil.
-- Look ahead for any syntactically significant characters that should be included with the word.
local next_char_index = first_non_space + #captured
local next_char = text:sub(next_char_index, next_char_index)
if next_char:match "[%s,{}%[%]\"']" then captured = captured .. next_char end
return captured
end
from codeium.vim.
Here's my hacky/fragile attempt, though I can't break it anymore: https://github.com/JohnRigoni/codeium.vim
I apologize to the devs as it needs to ignore call codeium#server#Request('AcceptCompletion', {'metadata': codeium#server#RequestMetadata(), 'completion_id': current_completion.completion.completionId})
, but hopefully we can see this feature officially rolled out soon.
This is prone to breakage with updates and no promises I keep the repo updated.
from codeium.vim.
I find @fwy approach superior because it works even if there's existing text already in front of the cursor. It still breaks on some circumstances but less often than other solutions.
from codeium.vim.
Does anyone feel confident enough to make a PR that adds native support for this
from codeium.vim.
Related Issues (20)
- Codeium is not working HOT 1
- '$HOME' directory in my "$HOME"
- Inibition shortcut HOT 2
- where do get auth token?
- Missing chat language server URL.
- It always duplicates the current row within the return statement when I exit insert mode after accepting its suggestion when I destructure props within function param (typescriptreact) HOT 1
- Codeium auth issue HOT 1
- Whether Zed will be supported?
- Hi HOT 1
- Support For Zed?
- Does not work on Neovim HOT 4
- language server error HOT 1
- A possible resolution of tab completion HOT 3
- Language Server Failed
- java.lang.IllegalArgumentException: Invalid URL port: "0" HOT 3
- Failed start on Dev Container
- Neofetch Interferes with Codeium Functionality in Neovim
- Why is my codeium spitting out this error HOT 3
- Language server memory leakage HOT 4
- Default Tab mapping is not mapped with lazy loading
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from codeium.vim.