Compare commits

...

4 Commits

Author SHA1 Message Date
Yi Ming
6888f65be1 feat(lsp): vim.lsp.inline_completion on_accept #35507 2025-09-01 08:46:29 -07:00
Volodymyr Chernetskyi
06df337617 vim-patch:9.1.1718: filetype: kubectl config file is not recognized #35583
Problem:  filetype: kubectl config file is not recognized
Solution: Detect .kube/kubectl as yaml filetype
          (Volodymyr Chernetskyi).

References:
- https://kubernetes.io/docs/reference/kubectl/kuberc/

closes: vim/vim#18169

6cd6857cbe
2025-09-01 08:16:43 -07:00
Volodymyr Chernetskyi
8fc1db043a vim-patch:9.1.1717: filetype: AWS cli alias file is not recognized #35581
Problem:  filetype: AWS cli alias file is not recognized
Solution: Detect .aws/cli/alias as confini filetype
          (Volodymyr Chernetskyi).

References:
- https://docs.aws.amazon.com/cli/v1/userguide/cli-usage-alias.html

related: vim/vim#18169

be0589f1d2
2025-09-01 08:16:34 -07:00
Justin M. Keyes
d4f789fd78 ci(release): link to release notes #35585
fix #35580
2025-09-01 08:12:11 -07:00
7 changed files with 121 additions and 33 deletions

View File

@@ -2,21 +2,26 @@
${NVIM_VERSION}
```
## Release notes
- [Changelog](https://github.com/neovim/neovim/commit/${NVIM_COMMIT}) (fixes + features)
- [News](./runtime/doc/news.txt) (`:help news` in Nvim)
## Install
### Windows
#### Zip
1. Download **nvim-win64.zip**
1. Download **nvim-win64.zip** (or **nvim-win-arm64.zip** for ARM)
2. Extract the zip
3. Run `nvim.exe` on your CLI of choice
3. Run `nvim.exe` in your terminal
#### MSI
1. Download **nvim-win64.msi**
1. Download **nvim-win64.msi** (or **nvim-win-arm64.msi** for ARM)
2. Run the MSI
3. Run `nvim.exe` on your CLI of choice
3. Run `nvim.exe` in your terminal
Note: On Windows "Server" you may need to [install vcruntime140.dll](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170).

View File

@@ -213,6 +213,7 @@ jobs:
- name: Publish release
env:
NVIM_VERSION: ${{ needs.linux.outputs.version }}
NVIM_COMMIT: ${{ github.sha }}
DEBUG: api
run: |
envsubst < "$GITHUB_WORKSPACE/.github/workflows/notes.md" > "$RUNNER_TEMP/notes.md"

View File

@@ -2229,6 +2229,16 @@ is_enabled({filter}) *vim.lsp.inlay_hint.is_enabled()*
==============================================================================
Lua module: vim.lsp.inline_completion *lsp-inline_completion*
*vim.lsp.inline_completion.Item*
Fields: ~
• {client_id} (`integer`) Client ID
• {insert_text} (`string|lsp.StringValue`) The text to be inserted, can
be a snippet.
• {range}? (`vim.Range`) Which range it be applied.
• {command}? (`lsp.Command`) Corresponding server command.
enable({enable}, {filter}) *vim.lsp.inline_completion.enable()*
Enables or disables inline completion for the {filter}ed scope, inline
completion will automatically be refreshed when you are in insert mode.
@@ -2246,9 +2256,9 @@ enable({enable}, {filter}) *vim.lsp.inline_completion.enable()*
for all.
get({opts}) *vim.lsp.inline_completion.get()*
Apply the currently displayed completion candidate to the buffer.
Accept the currently displayed completion candidate to the buffer.
It returns false when no candidate can be applied, so you can use the
It returns false when no candidate can be accepted, so you can use the
return value to implement a fallback: >lua
vim.keymap.set('i', '<Tab>', function()
if not vim.lsp.inline_completion.get() then
@@ -2265,6 +2275,10 @@ get({opts}) *vim.lsp.inline_completion.get()*
• {opts} (`table?`) A table with the following fields:
• {bufnr}? (`integer`, default: 0) Buffer handle, or 0 for
current.
• {on_accept}? (`fun(item: vim.lsp.inline_completion.Item)`)
Accept handler, called with the accepted item. If not
provided, the default handler is used, which applies changes
to the buffer based on the completion item.
Return: ~
(`boolean`) `true` if a completion was applied, else `false`.

View File

@@ -2236,6 +2236,7 @@ local pattern = {
},
['/%.'] = {
['/%.aws/credentials$'] = 'confini',
['/%.aws/cli/alias$'] = 'confini',
['/%.gitconfig%.d/'] = starsetf('gitconfig'),
['/%.gnupg/gpg%.conf$'] = 'gpg',
['/%.gnupg/options$'] = 'gpg',
@@ -2244,6 +2245,7 @@ local pattern = {
['/%.pinforc$'] = 'pinfo',
['/%.cargo/credentials$'] = 'toml',
['/%.init/.*%.override$'] = 'upstart',
['/%.kube/kuberc$'] = 'yaml',
},
['calendar/'] = {
['/%.calendar/'] = starsetf('calendar'),

View File

@@ -11,11 +11,11 @@ local M = {}
local namespace = api.nvim_create_namespace('nvim.lsp.inline_completion')
---@class (private) vim.lsp.inline_completion.CurrentItem
---@field index integer The index among all items form all clients.
---@class vim.lsp.inline_completion.Item
---@field _index integer The index among all items form all clients.
---@field client_id integer Client ID
---@field insert_text string|lsp.StringValue The text to be inserted, can be a snippet.
---@field filter_text? string
---@field _filter_text? string
---@field range? vim.Range Which range it be applied.
---@field command? lsp.Command Corresponding server command.
@@ -25,7 +25,7 @@ local namespace = api.nvim_create_namespace('nvim.lsp.inline_completion')
---@class (private) vim.lsp.inline_completion.Completor : vim.lsp.Capability
---@field active table<integer, vim.lsp.inline_completion.Completor?>
---@field timer? uv.uv_timer_t Timer for debouncing automatic requests
---@field current? vim.lsp.inline_completion.CurrentItem Currently selected item
---@field current? vim.lsp.inline_completion.Item Currently selected item
---@field client_state table<integer, vim.lsp.inline_completion.ClientState>
local Completor = {
name = 'inline_completion',
@@ -146,11 +146,11 @@ function Completor:select(index, show_index)
local client = assert(vim.lsp.get_client_by_id(client_id))
local range = item.range and vim.range.lsp(self.bufnr, item.range, client.offset_encoding)
self.current = {
index = index,
_index = index,
client_id = client_id,
insert_text = item.insertText,
range = range,
filter_text = item.filterText,
_filter_text = item.filterText,
command = item.command,
}
@@ -281,19 +281,14 @@ function Completor:abort()
self.current = nil
end
--- Apply the current completion item to the buffer.
--- Accept the current completion item to the buffer.
---
---@package
function Completor:apply()
local current = self.current
self:abort()
if not current then
return
end
local insert_text = current.insert_text
---@param item vim.lsp.inline_completion.Item
function Completor:accept(item)
local insert_text = item.insert_text
if type(insert_text) == 'string' then
local range = current.range
local range = item.range
if range then
local lines = vim.split(insert_text, '\n')
api.nvim_buf_set_text(
@@ -304,7 +299,7 @@ function Completor:apply()
range.end_.col,
lines
)
local pos = range.start:to_cursor()
local pos = item.range.start:to_cursor()
api.nvim_win_set_cursor(vim.fn.bufwinid(self.bufnr), {
pos[1] + #lines - 1,
(#lines == 1 and pos[2] or 0) + #lines[#lines],
@@ -317,9 +312,9 @@ function Completor:apply()
end
-- Execute the command *after* inserting this completion.
if current.command then
local client = assert(vim.lsp.get_client_by_id(current.client_id))
client:exec_cmd(current.command, { bufnr = self.bufnr })
if item.command then
local client = assert(vim.lsp.get_client_by_id(item.client_id))
client:exec_cmd(item.command, { bufnr = self.bufnr })
end
end
@@ -381,7 +376,7 @@ function M.select(opts)
end
local n = completor:count_items()
local index = current.index + count
local index = current._index + count
if wrap then
index = (index - 1) % n + 1
else
@@ -396,10 +391,15 @@ end
--- Buffer handle, or 0 for current.
--- (default: 0)
---@field bufnr? integer
--- Apply the currently displayed completion candidate to the buffer.
---
--- It returns false when no candidate can be applied,
--- Accept handler, called with the accepted item.
--- If not provided, the default handler is used,
--- which applies changes to the buffer based on the completion item.
---@field on_accept? fun(item: vim.lsp.inline_completion.Item)
--- Accept the currently displayed completion candidate to the buffer.
---
--- It returns false when no candidate can be accepted,
--- so you can use the return value to implement a fallback:
---
--- ```lua
@@ -420,11 +420,23 @@ function M.get(opts)
opts = opts or {}
local bufnr = vim._resolve_bufnr(opts.bufnr)
local on_accept = opts.on_accept
local completor = Completor.active[bufnr]
if completor and completor.current then
-- Schedule apply to allow `get()` can be mapped with `<expr>`.
vim.schedule(function()
completor:apply()
local item = completor.current
completor:abort()
if not item then
return
end
if on_accept then
on_accept(item)
else
completor:accept(item)
end
end)
return true
end

View File

@@ -4,6 +4,7 @@ local t_lsp = require('test.functional.plugin.lsp.testutil')
local Screen = require('test.functional.ui.screen')
local dedent = t.dedent
local eq = t.eq
local api = n.api
local exec_lua = n.exec_lua
@@ -183,6 +184,59 @@ describe('vim.lsp.inline_completion', function()
feed('<Esc>')
screen:expect({ grid = grid_applied_candidates })
end)
it('accepts on_accept callback', function()
feed('i')
screen:expect({ grid = grid_with_candidates })
local result = exec_lua(function()
---@type vim.lsp.inline_completion.Item
local result
vim.lsp.inline_completion.get({
on_accept = function(item)
result = item
end,
})
vim.wait(1000, function()
return result ~= nil
end) -- Wait for async callback.
return result
end)
feed('<Esc>')
screen:expect({ grid = grid_without_candidates })
eq({
_index = 1,
client_id = 1,
command = {
command = 'dummy',
title = 'Completion Accepted',
},
insert_text = dedent([[
function fibonacci(n) {
if (n <= 0) return 0;
if (n === 1) return 1;
let a = 0, b = 1, c;
for (let i = 2; i <= n; i++) {
c = a + b;
a = b;
b = c;
}
return b;
}]]),
range = {
end_ = {
buf = 1,
col = 20,
row = 0,
},
start = {
buf = 1,
col = 0,
row = 0,
},
},
}, result)
end)
end)
describe('select()', function()

View File

@@ -192,7 +192,7 @@ func s:GetFilenameChecks() abort
\ 'conaryrecipe': ['file.recipe'],
\ 'conf': ['auto.master', 'file.conf', 'texdoc.cnf', '.x11vncrc', '.chktexrc', '.ripgreprc', 'ripgreprc', 'file.ctags'],
\ 'config': ['/etc/hostname.file', 'any/etc/hostname.file', 'configure.in', 'configure.ac', 'file.at', 'aclocal.m4'],
\ 'confini': ['pacman.conf', 'paru.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials', 'file.nmconnection',
\ 'confini': ['pacman.conf', 'paru.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials', 'any/.aws/cli/alias', 'file.nmconnection',
\ 'any/.gnuradio/grc.conf', 'any/gnuradio/config.conf', 'any/gnuradio/conf.d/modtool.conf'],
\ 'context': ['tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi', 'file.mkxl', 'file.mklx'],
\ 'cook': ['file.cook'],
@@ -928,7 +928,7 @@ func s:GetFilenameChecks() abort
\ 'xslt': ['file.xsl', 'file.xslt'],
\ 'yacc': ['file.yy', 'file.yxx', 'file.y++'],
\ 'yaml': ['file.yaml', 'file.yml', 'file.eyaml', 'file.kyaml', 'file.kyml', 'any/.bundle/config', '.clangd', '.clang-format', '.clang-tidy', 'file.mplstyle', 'matplotlibrc', 'yarn.lock',
\ '/home/user/.kube/config', '.condarc', 'condarc', 'pixi.lock'],
\ '/home/user/.kube/config', '/home/user/.kube/kuberc', '.condarc', 'condarc', 'pixi.lock'],
\ 'yang': ['file.yang'],
\ 'yuck': ['file.yuck'],
\ 'z8a': ['file.z8a'],