mirror of
https://github.com/LazyVim/LazyVim.git
synced 2026-07-25 14:01:06 +00:00
Merge branch 'LazyVim:main' into main
This commit is contained in:
commit
3849f3dad9
8 changed files with 359 additions and 211 deletions
|
|
@ -191,6 +191,13 @@ function M.setup(opts)
|
|||
vim.cmd([[Lazy! load all]])
|
||||
vim.cmd([[checkhealth]])
|
||||
end, { desc = "Load all plugins and run :checkhealth" })
|
||||
|
||||
local health = require("lazy.health")
|
||||
vim.list_extend(health.valid, {
|
||||
"recommended",
|
||||
"desc",
|
||||
"vscode",
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -36,19 +36,8 @@ return {
|
|||
["<C-f>"] = cmp.mapping.scroll_docs(4),
|
||||
["<C-Space>"] = cmp.mapping.complete(),
|
||||
["<C-e>"] = cmp.mapping.abort(),
|
||||
["<CR>"] = function(fallback)
|
||||
if cmp.core.view:visible() or vim.fn.pumvisible() == 1 then
|
||||
LazyVim.create_undo()
|
||||
if cmp.confirm({ select = true }) then
|
||||
return
|
||||
end
|
||||
end
|
||||
return fallback()
|
||||
end,
|
||||
["<S-CR>"] = cmp.mapping.confirm({
|
||||
behavior = cmp.ConfirmBehavior.Replace,
|
||||
select = true,
|
||||
}), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
|
||||
["<CR>"] = LazyVim.cmp.confirm(),
|
||||
["<S-CR>"] = LazyVim.cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
|
||||
["<C-CR>"] = function(fallback)
|
||||
cmp.abort()
|
||||
fallback()
|
||||
|
|
@ -83,23 +72,15 @@ return {
|
|||
source.group_index = source.group_index or 1
|
||||
end
|
||||
local cmp = require("cmp")
|
||||
local Kind = cmp.lsp.CompletionItemKind
|
||||
cmp.setup(opts)
|
||||
cmp.event:on("confirm_done", function(event)
|
||||
if not vim.tbl_contains(opts.auto_brackets or {}, vim.bo.filetype) then
|
||||
return
|
||||
end
|
||||
local entry = event.entry
|
||||
local item = entry:get_completion_item()
|
||||
if vim.tbl_contains({ Kind.Function, Kind.Method }, item.kind) and item.insertTextFormat ~= 2 then
|
||||
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||
local prev_char = vim.api.nvim_buf_get_text(0, cursor[1] - 1, cursor[2], cursor[1] - 1, cursor[2] + 1, {})[1]
|
||||
if prev_char ~= "(" and prev_char ~= ")" then
|
||||
local keys = vim.api.nvim_replace_termcodes("()<left>", false, false, true)
|
||||
vim.api.nvim_feedkeys(keys, "i", true)
|
||||
end
|
||||
if vim.tbl_contains(opts.auto_brackets or {}, vim.bo.filetype) then
|
||||
LazyVim.cmp.auto_brackets(event.entry)
|
||||
end
|
||||
end)
|
||||
cmp.event:on("menu_opened", function(event)
|
||||
LazyVim.cmp.add_missing_snippet_docs(event.window)
|
||||
end)
|
||||
end,
|
||||
},
|
||||
|
||||
|
|
@ -113,8 +94,8 @@ return {
|
|||
},
|
||||
opts = function(_, opts)
|
||||
opts.snippet = {
|
||||
expand = function(args)
|
||||
vim.snippet.expand(args.body)
|
||||
expand = function(item)
|
||||
return LazyVim.cmp.expand(item.body)
|
||||
end,
|
||||
}
|
||||
table.insert(opts.sources, { name = "snippets" })
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ return {
|
|||
recommended = function()
|
||||
return LazyVim.extras.wants({
|
||||
ft = "toml",
|
||||
root = "*.toml",
|
||||
})
|
||||
end,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -121,16 +121,8 @@ return {
|
|||
require("lazyvim.plugins.lsp.keymaps").on_attach(client, buffer)
|
||||
end)
|
||||
|
||||
local register_capability = vim.lsp.handlers["client/registerCapability"]
|
||||
|
||||
vim.lsp.handlers["client/registerCapability"] = function(err, res, ctx)
|
||||
---@diagnostic disable-next-line: no-unknown
|
||||
local ret = register_capability(err, res, ctx)
|
||||
local client = vim.lsp.get_client_by_id(ctx.client_id)
|
||||
local buffer = vim.api.nvim_get_current_buf()
|
||||
require("lazyvim.plugins.lsp.keymaps").on_attach(client, buffer)
|
||||
return ret
|
||||
end
|
||||
LazyVim.lsp.setup_dynamic_capability()
|
||||
LazyVim.lsp.on_dynamic_capability(require("lazyvim.plugins.lsp.keymaps").on_attach)
|
||||
|
||||
LazyVim.lsp.words.setup(opts.document_highlight)
|
||||
|
||||
|
|
@ -148,24 +140,19 @@ return {
|
|||
if vim.fn.has("nvim-0.10") == 1 then
|
||||
-- inlay hints
|
||||
if opts.inlay_hints.enabled then
|
||||
LazyVim.lsp.on_attach(function(client, buffer)
|
||||
if client.supports_method("textDocument/inlayHint") then
|
||||
LazyVim.lsp.on_supports_method("textDocument/inlayHint", function(client, buffer)
|
||||
LazyVim.toggle.inlay_hints(buffer, true)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- code lens
|
||||
if opts.codelens.enabled and vim.lsp.codelens then
|
||||
LazyVim.lsp.on_attach(function(client, buffer)
|
||||
if client.supports_method("textDocument/codeLens") then
|
||||
LazyVim.lsp.on_supports_method("textDocument/codeLens", function(client, buffer)
|
||||
vim.lsp.codelens.refresh()
|
||||
--- autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.codelens.refresh()
|
||||
vim.api.nvim_create_autocmd({ "BufEnter", "CursorHold", "InsertLeave" }, {
|
||||
buffer = buffer,
|
||||
callback = vim.lsp.codelens.refresh,
|
||||
})
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
103
lua/lazyvim/util/cmp.lua
Normal file
103
lua/lazyvim/util/cmp.lua
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
---@class lazyvim.util.cmp
|
||||
local M = {}
|
||||
|
||||
---@param snippet string
|
||||
---@param fn fun(placeholder:Placeholder):string
|
||||
---@return string
|
||||
function M.snippet_replace(snippet, fn)
|
||||
return snippet:gsub("%$%b{}", function(m)
|
||||
local n, name = m:match("^%${(%d+):(.+)}$")
|
||||
return n and fn({ n = n, text = name }) or m
|
||||
end) or snippet
|
||||
end
|
||||
|
||||
-- This function resolves nested placeholders in a snippet.
|
||||
function M.snippet_resolve(snippet)
|
||||
return M.snippet_replace(snippet, function(placeholder)
|
||||
return M.snippet_resolve(placeholder.text)
|
||||
end):gsub("%$0", "")
|
||||
end
|
||||
|
||||
-- This function replaces nested placeholders in a snippet with LSP placeholders.
|
||||
function M.snippet_fix(snippet)
|
||||
return M.snippet_replace(snippet, function(placeholder)
|
||||
return "${" .. placeholder.n .. ":" .. M.snippet_resolve(placeholder.text) .. "}"
|
||||
end)
|
||||
end
|
||||
|
||||
---@param entry cmp.Entry
|
||||
function M.auto_brackets(entry)
|
||||
local cmp = require("cmp")
|
||||
local Kind = cmp.lsp.CompletionItemKind
|
||||
local item = entry:get_completion_item()
|
||||
if vim.tbl_contains({ Kind.Function, Kind.Method }, item.kind) then
|
||||
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||
local prev_char = vim.api.nvim_buf_get_text(0, cursor[1] - 1, cursor[2], cursor[1] - 1, cursor[2] + 1, {})[1]
|
||||
if prev_char ~= "(" and prev_char ~= ")" then
|
||||
local keys = vim.api.nvim_replace_termcodes("()<left>", false, false, true)
|
||||
vim.api.nvim_feedkeys(keys, "i", true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function adds missing documentation to snippets.
|
||||
-- The documentation is a preview of the snippet.
|
||||
---@param window cmp.CustomEntriesView|cmp.NativeEntriesView
|
||||
function M.add_missing_snippet_docs(window)
|
||||
local cmp = require("cmp")
|
||||
local Kind = cmp.lsp.CompletionItemKind
|
||||
local entries = window:get_entries()
|
||||
for _, entry in ipairs(entries) do
|
||||
if entry:get_kind() == Kind.Snippet then
|
||||
local item = entry:get_completion_item()
|
||||
if not item.documentation and item.insertText then
|
||||
item.documentation = {
|
||||
kind = cmp.lsp.MarkupKind.Markdown,
|
||||
value = string.format("```%s\n%s\n```", vim.bo.filetype, M.snippet_resolve(item.insertText)),
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This is a better implementation of `cmp.confirm`:
|
||||
-- * check if the completion menu is visible without waiting for running sources
|
||||
-- * create an undo point before confirming
|
||||
-- This function is both faster and more reliable.
|
||||
---@param opts? {select: boolean, behavior: cmp.ConfirmBehavior}
|
||||
function M.confirm(opts)
|
||||
local cmp = require("cmp")
|
||||
opts = vim.tbl_extend("force", {
|
||||
select = true,
|
||||
behavior = cmp.ConfirmBehavior.Insert,
|
||||
}, opts or {})
|
||||
return function(fallback)
|
||||
if cmp.core.view:visible() or vim.fn.pumvisible() == 1 then
|
||||
LazyVim.create_undo()
|
||||
if cmp.confirm(opts) then
|
||||
return
|
||||
end
|
||||
end
|
||||
return fallback()
|
||||
end
|
||||
end
|
||||
|
||||
function M.expand(snippet)
|
||||
local ok = pcall(vim.snippet.expand, snippet)
|
||||
if not ok then
|
||||
local fixed = M.snippet_fix(snippet)
|
||||
ok = pcall(vim.snippet.expand, fixed)
|
||||
|
||||
local msg = ok and "Failed to parse snippet,\nbut was able to fix it automatically." or "Failed to parse snippet."
|
||||
|
||||
LazyVim[ok and "warn" or "error"](
|
||||
([[%s
|
||||
```%s
|
||||
%s
|
||||
```]]):format(msg, vim.bo.filetype, snippet),
|
||||
{ title = "vim.snippet" }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -17,6 +17,7 @@ local LazyUtil = require("lazy.core.util")
|
|||
---@field json lazyvim.util.json
|
||||
---@field lualine lazyvim.util.lualine
|
||||
---@field mini lazyvim.util.mini
|
||||
---@field cmp lazyvim.util.cmp
|
||||
local M = {}
|
||||
|
||||
---@type table<string, string|string[]>
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ local M = {}
|
|||
|
||||
---@param opts? lsp.Client.filter
|
||||
function M.get_clients(opts)
|
||||
local ret = {} ---@type lsp.Client[]
|
||||
local ret = {} ---@type vim.lsp.Client[]
|
||||
if vim.lsp.get_clients then
|
||||
ret = vim.lsp.get_clients(opts)
|
||||
else
|
||||
---@diagnostic disable-next-line: deprecated
|
||||
ret = vim.lsp.get_active_clients(opts)
|
||||
if opts and opts.method then
|
||||
---@param client lsp.Client
|
||||
---@param client vim.lsp.Client
|
||||
ret = vim.tbl_filter(function(client)
|
||||
return client.supports_method(opts.method, { bufnr = opts.bufnr })
|
||||
end, ret)
|
||||
|
|
@ -21,17 +21,81 @@ function M.get_clients(opts)
|
|||
return opts and opts.filter and vim.tbl_filter(opts.filter, ret) or ret
|
||||
end
|
||||
|
||||
---@param on_attach fun(client:lsp.Client, buffer)
|
||||
---@param on_attach fun(client:vim.lsp.Client, buffer)
|
||||
function M.on_attach(on_attach)
|
||||
vim.api.nvim_create_autocmd("LspAttach", {
|
||||
return vim.api.nvim_create_autocmd("LspAttach", {
|
||||
callback = function(args)
|
||||
local buffer = args.buf ---@type number
|
||||
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
||||
on_attach(client, buffer)
|
||||
if client then
|
||||
return on_attach(client, buffer)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
function M.setup_dynamic_capability()
|
||||
local register_capability = vim.lsp.handlers["client/registerCapability"]
|
||||
vim.lsp.handlers["client/registerCapability"] = function(err, res, ctx)
|
||||
---@diagnostic disable-next-line: no-unknown
|
||||
local ret = register_capability(err, res, ctx)
|
||||
local client = vim.lsp.get_client_by_id(ctx.client_id)
|
||||
local buffer = vim.api.nvim_get_current_buf()
|
||||
if client then
|
||||
vim.api.nvim_exec_autocmds("User", {
|
||||
pattern = "LspDynamicCapability",
|
||||
data = { client_id = client.id, buffer = buffer },
|
||||
})
|
||||
end
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
---@param fn fun(client:vim.lsp.Client, buffer):boolean?
|
||||
---@param opts? {group?: integer}
|
||||
function M.on_dynamic_capability(fn, opts)
|
||||
return vim.api.nvim_create_autocmd("User", {
|
||||
pattern = "LspDynamicCapability",
|
||||
group = opts and opts.group or nil,
|
||||
callback = function(args)
|
||||
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
||||
local buffer = args.data.buffer ---@type number
|
||||
if client then
|
||||
return fn(client, buffer)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
M._on_supports_method_id = 0
|
||||
|
||||
---@param method string
|
||||
---@param fn fun(client:vim.lsp.Client, buffer)
|
||||
function M.on_supports_method(method, fn)
|
||||
M.on_attach(function(client, buffer)
|
||||
if client.supports_method(method, { bufnr = buffer }) then
|
||||
fn(client, buffer)
|
||||
else
|
||||
M._on_supports_method_id = M._on_supports_method_id + 1
|
||||
local id = M._on_supports_method_id
|
||||
local group = vim.api.nvim_create_augroup("on_supports_method_" .. id, { clear = true })
|
||||
M.on_dynamic_capability(function(c, b)
|
||||
if c == client and b == buffer and client.supports_method(method, { bufnr = buffer }) then
|
||||
fn(client, buffer)
|
||||
pcall(vim.api.nvim_del_augroup_by_id, group)
|
||||
end
|
||||
end, { group = group })
|
||||
vim.api.nvim_create_autocmd({ "LspDetach", "BufDelete" }, {
|
||||
group = group,
|
||||
buffer = buffer,
|
||||
callback = function()
|
||||
pcall(vim.api.nvim_del_augroup_by_id, group)
|
||||
end,
|
||||
})
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@param from string
|
||||
---@param to string
|
||||
function M.on_rename(from, to)
|
||||
|
|
@ -89,12 +153,12 @@ function M.formatter(opts)
|
|||
end,
|
||||
sources = function(buf)
|
||||
local clients = M.get_clients(LazyVim.merge({}, filter, { bufnr = buf }))
|
||||
---@param client lsp.Client
|
||||
---@param client vim.lsp.Client
|
||||
local ret = vim.tbl_filter(function(client)
|
||||
return client.supports_method("textDocument/formatting")
|
||||
or client.supports_method("textDocument/rangeFormatting")
|
||||
end, clients)
|
||||
---@param client lsp.Client
|
||||
---@param client vim.lsp.Client
|
||||
return vim.tbl_map(function(client)
|
||||
return client.name
|
||||
end, ret)
|
||||
|
|
@ -143,10 +207,10 @@ function M.words.setup(opts)
|
|||
return handler(err, result, ctx, config)
|
||||
end
|
||||
|
||||
M.on_attach(function(client, buf)
|
||||
if client.supports_method("textDocument/documentHighlight") then
|
||||
M.on_supports_method("textDocument/documentHighlight", function(client, buf)
|
||||
local group = vim.api.nvim_create_augroup("lsp_word_" .. buf, { clear = true })
|
||||
vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI", "CursorMoved", "CursorMovedI" }, {
|
||||
group = vim.api.nvim_create_augroup("lsp_word_" .. buf, { clear = true }),
|
||||
group = group,
|
||||
buffer = buf,
|
||||
callback = function(ev)
|
||||
if not M.words.at() then
|
||||
|
|
@ -158,7 +222,11 @@ function M.words.setup(opts)
|
|||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
vim.api.nvim_create_autocmd("LspDetach", {
|
||||
callback = function()
|
||||
vim.api.nvim_create_augroup("lsp_word_" .. buf, { clear = true })
|
||||
end,
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue