mirror of
https://github.com/neovim/neovim.git
synced 2025-09-03 18:08:16 +00:00
Compare commits
4 Commits
3c601d02dc
...
6888f65be1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6888f65be1 | ||
![]() |
06df337617 | ||
![]() |
8fc1db043a | ||
![]() |
d4f789fd78 |
13
.github/workflows/notes.md
vendored
13
.github/workflows/notes.md
vendored
@@ -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).
|
||||
|
||||
|
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -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"
|
||||
|
@@ -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`.
|
||||
|
@@ -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'),
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
@@ -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'],
|
||||
|
Reference in New Issue
Block a user