diff --git a/README-DE.md b/README-DE.md
index f5a05985..a9522c84 100644
--- a/README-DE.md
+++ b/README-DE.md
@@ -1,138 +1,138 @@
-
-

-
-
-
-
-
-
-
-
-LazyVim ist ein Neovim-Setup aufgebaut auf [💤 lazy.nvim](https://github.com/folke/lazy.nvim).
-Es erleichtert das Anpassen und Erweitern von Ihrer Konfiguration.
-Anstatt von vorne anzufangen oder eine vorgefertigte Distro zu verwenden, gibt LazyVim das beste aus
-beiden Welten - die Flexibilität Ihre Konfiguration zu verändern und einzustellen wie Sie es wollen
-und die Einfachheit von einem vorgefertigten Setup.
-
-
-
-
-
-## ✨ Features
-
-- 🔥 Transformiere dein Neovim in eine komplette IDE
-- 💤 Passe deine Konfiguration einfach an und erweitere diese mit [lazy.nvim](https://github.com/folke/lazy.nvim)
-- 🚀 Extrem schnell
-- 🧹 Logische Voreinstellungen für optionen, autocmds und keymaps
-- 📦 Kommt mit einem Haufen vorkonfigurierter, ready-to-use Plugins
-
-## ⚡️ Vorraussetzungen
-
-- Neovim >= **0.8.0** (gebraucht um mit **LuaJIT** zu bauen)
-- Git >= **2.19.0** (um Teil-Klone zu unterstützen)
-- eine [Nerd Font](https://www.nerdfonts.com/) **_(optional)_**
-
-## 🚀 Einstieg
-
-Sie können eine Startvorlage für **LazyVim** [hier](https://github.com/LazyVim/starter) finden
-
-Versuchen Sie's mit Docker
-
-```sh
-docker run -w /root -it --rm alpine:edge sh -uelic '
- apk add git lazygit neovim ripgrep alpine-sdk --update
- git clone https://github.com/LazyVim/starter ~/.config/nvim
- cd ~/.config/nvim
- nvim
-'
-```
-
-
-
-Installieren von LazyVim Starter
-
-- Neovim Files sichern:
-
- ```sh
- mv ~/.config/nvim ~/.config/nvim.bak
- mv ~/.local/share/nvim ~/.local/share/nvim.bak
- ```
-
-- Den Starter Klonen:
-
- ```sh
- git clone https://github.com/LazyVim/starter ~/.config/nvim
- ```
-
-- Den `.git` Folder löschen, um die Konfiguration zu einer eigenen distro hinzuzufügen:
-
- ```sh
- rm -rf ~/.config/nvim/.git
- ```
-
-- Neovim starten!
-
- ```sh
- nvim
- ```
-
- Refer to the comments in the files on how to customize **LazyVim**.
-
-
-
-## 📂 Dateistruktur
-
-Die Dateien unter `config` werden automatisch und zur richtigen Zeit geladen,
-sodass ein manuelles `require` nicht nötig ist.
-**LazyVim** bringt Konfigurationsdatein mit, die **_vor_** Ihren eigenen geladen werden -
-siehe [hier](https://github.com/LazyVim/LazyVim/tree/main/lua/lazyvim/config)
-Sie können eigene Plugins unter `lua/plugins/` hinzufügen. Alle Dateien innerhalb
-dieses Ordners werden automatisch mit [lazy.nvim](https://github.com/folke/lazy.nvim)
-geladen.
-
-
-~/.config/nvim
-├── lua
-│ ├── config
-│ │ ├── autocmds.lua
-│ │ ├── keymaps.lua
-│ │ ├── lazy.lua
-│ │ └── options.lua
-│ └── plugins
-│ ├── spec1.lua
-│ ├── **
-│ └── spec2.lua
-└── init.toml
-
-
-## ⚙️ Konfiguration
-
-Siehe [Dokumentation](https://lazyvim.github.io).
+
+

+
+
+
+
+
+
+
+
+LazyVim ist ein Neovim-Setup aufgebaut auf [💤 lazy.nvim](https://github.com/folke/lazy.nvim).
+Es erleichtert das Anpassen und Erweitern von Ihrer Konfiguration.
+Anstatt von vorne anzufangen oder eine vorgefertigte Distro zu verwenden, gibt LazyVim das beste aus
+beiden Welten - die Flexibilität Ihre Konfiguration zu verändern und einzustellen wie Sie es wollen
+und die Einfachheit von einem vorgefertigten Setup.
+
+
+
+
+
+## ✨ Features
+
+- 🔥 Transformiere dein Neovim in eine komplette IDE
+- 💤 Passe deine Konfiguration einfach an und erweitere diese mit [lazy.nvim](https://github.com/folke/lazy.nvim)
+- 🚀 Extrem schnell
+- 🧹 Logische Voreinstellungen für optionen, autocmds und keymaps
+- 📦 Kommt mit einem Haufen vorkonfigurierter, ready-to-use Plugins
+
+## ⚡️ Vorraussetzungen
+
+- Neovim >= **0.8.0** (gebraucht um mit **LuaJIT** zu bauen)
+- Git >= **2.19.0** (um Teil-Klone zu unterstützen)
+- eine [Nerd Font](https://www.nerdfonts.com/) **_(optional)_**
+
+## 🚀 Einstieg
+
+Sie können eine Startvorlage für **LazyVim** [hier](https://github.com/LazyVim/starter) finden
+
+Versuchen Sie's mit Docker
+
+```sh
+docker run -w /root -it --rm alpine:edge sh -uelic '
+ apk add git lazygit neovim ripgrep alpine-sdk --update
+ git clone https://github.com/LazyVim/starter ~/.config/nvim
+ cd ~/.config/nvim
+ nvim
+'
+```
+
+
+
+Installieren von LazyVim Starter
+
+- Neovim Files sichern:
+
+ ```sh
+ mv ~/.config/nvim ~/.config/nvim.bak
+ mv ~/.local/share/nvim ~/.local/share/nvim.bak
+ ```
+
+- Den Starter Klonen:
+
+ ```sh
+ git clone https://github.com/LazyVim/starter ~/.config/nvim
+ ```
+
+- Den `.git` Folder löschen, um die Konfiguration zu einer eigenen distro hinzuzufügen:
+
+ ```sh
+ rm -rf ~/.config/nvim/.git
+ ```
+
+- Neovim starten!
+
+ ```sh
+ nvim
+ ```
+
+ Refer to the comments in the files on how to customize **LazyVim**.
+
+
+
+## 📂 Dateistruktur
+
+Die Dateien unter `config` werden automatisch und zur richtigen Zeit geladen,
+sodass ein manuelles `require` nicht nötig ist.
+**LazyVim** bringt Konfigurationsdatein mit, die **_vor_** Ihren eigenen geladen werden -
+siehe [hier](https://github.com/LazyVim/LazyVim/tree/main/lua/lazyvim/config)
+Sie können eigene Plugins unter `lua/plugins/` hinzufügen. Alle Dateien innerhalb
+dieses Ordners werden automatisch mit [lazy.nvim](https://github.com/folke/lazy.nvim)
+geladen.
+
+
+~/.config/nvim
+├── lua
+│ ├── config
+│ │ ├── autocmds.lua
+│ │ ├── keymaps.lua
+│ │ ├── lazy.lua
+│ │ └── options.lua
+│ └── plugins
+│ ├── spec1.lua
+│ ├── **
+│ └── spec2.lua
+└── init.toml
+
+
+## ⚙️ Konfiguration
+
+Siehe [Dokumentation](https://lazyvim.github.io).
diff --git a/lua/lazyvim/config/init.lua b/lua/lazyvim/config/init.lua
index d990f94d..62b14237 100644
--- a/lua/lazyvim/config/init.lua
+++ b/lua/lazyvim/config/init.lua
@@ -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,
})
diff --git a/lua/lazyvim/plugins/coding.lua b/lua/lazyvim/plugins/coding.lua
index 9a3f674a..589e4b1c 100644
--- a/lua/lazyvim/plugins/coding.lua
+++ b/lua/lazyvim/plugins/coding.lua
@@ -36,19 +36,8 @@ return {
[""] = cmp.mapping.scroll_docs(4),
[""] = cmp.mapping.complete(),
[""] = cmp.mapping.abort(),
- [""] = 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,
- [""] = cmp.mapping.confirm({
- behavior = cmp.ConfirmBehavior.Replace,
- select = true,
- }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
+ [""] = LazyVim.cmp.confirm(),
+ [""] = LazyVim.cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
[""] = 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("()", 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" })
diff --git a/lua/lazyvim/plugins/extras/lang/toml.lua b/lua/lazyvim/plugins/extras/lang/toml.lua
index 03ec5029..9dcc029d 100644
--- a/lua/lazyvim/plugins/extras/lang/toml.lua
+++ b/lua/lazyvim/plugins/extras/lang/toml.lua
@@ -2,6 +2,7 @@ return {
recommended = function()
return LazyVim.extras.wants({
ft = "toml",
+ root = "*.toml",
})
end,
{
diff --git a/lua/lazyvim/plugins/lsp/init.lua b/lua/lazyvim/plugins/lsp/init.lua
index 3a6ae964..f99c997c 100644
--- a/lua/lazyvim/plugins/lsp/init.lua
+++ b/lua/lazyvim/plugins/lsp/init.lua
@@ -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.toggle.inlay_hints(buffer, true)
- end
+ LazyVim.lsp.on_supports_method("textDocument/inlayHint", function(client, buffer)
+ LazyVim.toggle.inlay_hints(buffer, true)
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
- vim.lsp.codelens.refresh()
- --- autocmd BufEnter,CursorHold,InsertLeave lua vim.lsp.codelens.refresh()
- vim.api.nvim_create_autocmd({ "BufEnter", "CursorHold", "InsertLeave" }, {
- buffer = buffer,
- callback = vim.lsp.codelens.refresh,
- })
- end
+ LazyVim.lsp.on_supports_method("textDocument/codeLens", function(client, buffer)
+ vim.lsp.codelens.refresh()
+ vim.api.nvim_create_autocmd({ "BufEnter", "CursorHold", "InsertLeave" }, {
+ buffer = buffer,
+ callback = vim.lsp.codelens.refresh,
+ })
end)
end
end
diff --git a/lua/lazyvim/util/cmp.lua b/lua/lazyvim/util/cmp.lua
new file mode 100644
index 00000000..d0e5b48f
--- /dev/null
+++ b/lua/lazyvim/util/cmp.lua
@@ -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("()", 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
diff --git a/lua/lazyvim/util/init.lua b/lua/lazyvim/util/init.lua
index 433efda8..c36ef101 100644
--- a/lua/lazyvim/util/init.lua
+++ b/lua/lazyvim/util/init.lua
@@ -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
diff --git a/lua/lazyvim/util/lsp.lua b/lua/lazyvim/util/lsp.lua
index e2eb82de..af04b1c4 100644
--- a/lua/lazyvim/util/lsp.lua
+++ b/lua/lazyvim/util/lsp.lua
@@ -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,22 +207,26 @@ 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
- vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI", "CursorMoved", "CursorMovedI" }, {
- group = vim.api.nvim_create_augroup("lsp_word_" .. buf, { clear = true }),
- buffer = buf,
- callback = function(ev)
- if not M.words.at() then
- if ev.event:find("CursorMoved") then
- vim.lsp.buf.clear_references()
- else
- vim.lsp.buf.document_highlight()
- end
+ 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 = group,
+ buffer = buf,
+ callback = function(ev)
+ if not M.words.at() then
+ if ev.event:find("CursorMoved") then
+ vim.lsp.buf.clear_references()
+ else
+ vim.lsp.buf.document_highlight()
end
- end,
- })
- end
+ end
+ end,
+ })
+ vim.api.nvim_create_autocmd("LspDetach", {
+ callback = function()
+ vim.api.nvim_create_augroup("lsp_word_" .. buf, { clear = true })
+ end,
+ })
end)
end