diff --git a/CHANGELOG.md b/CHANGELOG.md index b0606dd4..a8c9cc0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,42 @@ # Changelog +## [11.4.0](https://github.com/LazyVim/LazyVim/compare/v11.3.2...v11.4.0) (2024-05-20) + + +### Features + +* **cmp:** add missing documentation to snippets when needed ([24a2a9f](https://github.com/LazyVim/LazyVim/commit/24a2a9fb0ba60e0e7c6c8c4ee95a5db7ea0e123e)) +* **cmp:** better error handling and automatic fixing of snippets that fail to parse with native Neovim snippets ([97862f4](https://github.com/LazyVim/LazyVim/commit/97862f425997bf89f581e6aeceed9aac85d90432)) +* **cmp:** move cmp autobracket support to util class ([39f3ebc](https://github.com/LazyVim/LazyVim/commit/39f3ebcadf49b285d8ae06270ed0c2098e7f03bd)) +* **cmp:** resolve placeholders in generated missing snippet documentation ([7d72436](https://github.com/LazyVim/LazyVim/commit/7d72436193b3624a9198a5e57ec1bd7e90260c00)) +* **extras.lang:** Add kotlin ([#2890](https://github.com/LazyVim/LazyVim/issues/2890)) ([94c9f4c](https://github.com/LazyVim/LazyVim/commit/94c9f4cf379e472fbd1a342ef28687dfa418dec0)) +* **java:** enable inlay hints. Fixes [#3244](https://github.com/LazyVim/LazyVim/issues/3244) ([e5ea8ab](https://github.com/LazyVim/LazyVim/commit/e5ea8abd38c4b93edccd69c9ef4462377103a9c3)) +* **kotlin:** added recommended checks ([dd417c3](https://github.com/LazyVim/LazyVim/commit/dd417c36cd14b5b347b4f82e9e7683b085c768fb)) +* **lang:** add toml ([#3022](https://github.com/LazyVim/LazyVim/issues/3022)) ([e0c67f6](https://github.com/LazyVim/LazyVim/commit/e0c67f6776a5e6f1b72852567ce4fec16598b2da)) +* **lsp:** properly update certain Neovim functionlity based on dynamic capabilities. See [#3244](https://github.com/LazyVim/LazyVim/issues/3244). Fixes [#3246](https://github.com/LazyVim/LazyVim/issues/3246) ([20e002f](https://github.com/LazyVim/LazyVim/commit/20e002f9f0e9bfdff1ffc638987fbd46b31e5f9b)) +* **toml:** also recommend toml when theres toml files in the cwd ([c264253](https://github.com/LazyVim/LazyVim/commit/c264253d8fd4f068c7c2ddb5ea3c63596ab5d23f)) +* **vscode:** enable more compatible plugins ([#3250](https://github.com/LazyVim/LazyVim/issues/3250)) ([5726f39](https://github.com/LazyVim/LazyVim/commit/5726f3966df7c1e9b350d24aa94f621d0ea484da)) + + +### Bug Fixes + +* **bufferline:** unpin bufferline with 0.9.x compatibility ([#3252](https://github.com/LazyVim/LazyVim/issues/3252)) ([ea1c3ad](https://github.com/LazyVim/LazyVim/commit/ea1c3ad6b46dfaeca9ff4564499b4cdc8f839610)) +* **cmp:** no need to setup native snippets with latest cmp ([57a31c3](https://github.com/LazyVim/LazyVim/commit/57a31c3920bcb9baec9a6d3915506a638b0801b8)) +* **cmp:** use better cmp.confirm ([2961162](https://github.com/LazyVim/LazyVim/commit/2961162ebaef96e4ffbc1e6c97dba0dc32efbbb0)) +* **config:** add some extra LazyVim keys to lazy health ([76033c6](https://github.com/LazyVim/LazyVim/commit/76033c6aa92e633de968b515d3fd5f9e0447a74f)) + +## [11.3.2](https://github.com/LazyVim/LazyVim/compare/v11.3.1...v11.3.2) (2024-05-19) + + +### Bug Fixes + +* **bufferline:** pin bufferline to older version on 0.9.x for now ([573aa22](https://github.com/LazyVim/LazyVim/commit/573aa226f9f9b9fb9c9886381d3fd06746b7ae6a)) +* **cmp:** only complete on `<cr>` when cmp is really visible. Dont wait till it might be visible. Faster and more correct imho ([ad22ada](https://github.com/LazyVim/LazyVim/commit/ad22adab7d446018875de2dc96168295cad9298e)) +* **git:** off-by-one issue in lazygit blame line ([#3230](https://github.com/LazyVim/LazyVim/issues/3230)) ([4208a09](https://github.com/LazyVim/LazyVim/commit/4208a09df8cd20fe491a5fdcc722c12fb07588dc)) +* **gitui:** properly delete lazygit keymap at the correct time. Fixes [#3227](https://github.com/LazyVim/LazyVim/issues/3227) ([e346d17](https://github.com/LazyVim/LazyVim/commit/e346d17812de516ad0789ede49b49a8b7ba213fe)) +* show refactored success msg ([#3233](https://github.com/LazyVim/LazyVim/issues/3233)) ([4a41012](https://github.com/LazyVim/LazyVim/commit/4a41012483e67ffe5ff65f31934ed668325ea131)) +* **yanky:** load yanky earlier to avoid losing deleted lines ([#3234](https://github.com/LazyVim/LazyVim/issues/3234)) ([93c156a](https://github.com/LazyVim/LazyVim/commit/93c156a0a54e5400436a950263dd140ca591d3e5)) + ## [11.3.1](https://github.com/LazyVim/LazyVim/compare/v11.3.0...v11.3.1) (2024-05-18) 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 @@ -
- -
- -
- -

- Installieren - · - Konfigurieren - · - Dokumentation -

- -

- - Latest release - - - Last commit - - - License - - - Stars - - - Issues - - - Repo Size - - - follow on Twitter - -

- -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. - -![image](https://user-images.githubusercontent.com/292349/213447056-92290767-ea16-430c-8727-ce994c93e9cc.png) - -![image](https://user-images.githubusercontent.com/292349/211285846-0b7bb3bf-0462-4029-b64c-4ee1d037fc1c.png) - -## ✨ 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). +
+ +
+ +
+ +

+ Installieren + · + Konfigurieren + · + Dokumentation +

+ +

+ + Latest release + + + Last commit + + + License + + + Stars + + + Issues + + + Repo Size + + + follow on Twitter + +

+ +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. + +![image](https://user-images.githubusercontent.com/292349/213447056-92290767-ea16-430c-8727-ce994c93e9cc.png) + +![image](https://user-images.githubusercontent.com/292349/211285846-0b7bb3bf-0462-4029-b64c-4ee1d037fc1c.png) + +## ✨ 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/doc/LazyVim.txt b/doc/LazyVim.txt index 774f7969..9fb3ea57 100644 --- a/doc/LazyVim.txt +++ b/doc/LazyVim.txt @@ -1,4 +1,4 @@ -*LazyVim.txt* For Neovim >= 0.9.0 Last change: 2024 May 19 +*LazyVim.txt* For Neovim >= 0.9.0 Last change: 2024 May 20 ============================================================================== Table of Contents *LazyVim-table-of-contents* 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/coding/yanky.lua b/lua/lazyvim/plugins/extras/coding/yanky.lua index b915bc7b..46dca784 100644 --- a/lua/lazyvim/plugins/extras/coding/yanky.lua +++ b/lua/lazyvim/plugins/extras/coding/yanky.lua @@ -3,6 +3,7 @@ return { "gbprod/yanky.nvim", recommended = true, desc = "Better Yank/Paste", + event = "LazyFile", opts = { highlight = { timer = 150 }, }, diff --git a/lua/lazyvim/plugins/extras/editor/refactoring.lua b/lua/lazyvim/plugins/extras/editor/refactoring.lua index cf6988a9..ff6351c7 100644 --- a/lua/lazyvim/plugins/extras/editor/refactoring.lua +++ b/lua/lazyvim/plugins/extras/editor/refactoring.lua @@ -112,6 +112,8 @@ return { }, printf_statements = {}, print_var_statements = {}, + show_success_message = true, -- shows a message with information about the refactor on success + -- i.e. [Refactor] Inlined 3 variable occurrences }, config = function(_, opts) require("refactoring").setup(opts) diff --git a/lua/lazyvim/plugins/extras/lang/java.lua b/lua/lazyvim/plugins/extras/lang/java.lua index 2d99a6cd..a1b49716 100644 --- a/lua/lazyvim/plugins/extras/lang/java.lua +++ b/lua/lazyvim/plugins/extras/lang/java.lua @@ -118,11 +118,18 @@ return { dap = { hotcodereplace = "auto", config_overrides = {} }, dap_main = {}, test = true, + settings = { + java = { + inlayHints = { + parameterNames = { + enabled = "all", + }, + }, + }, + }, } end, - config = function() - local opts = LazyVim.opts("nvim-jdtls") or {} - + config = function(_, opts) -- Find the extra bundles that should be passed on the jdtls command-line -- if nvim-dap is enabled with java debug/test. local mason_registry = require("mason-registry") @@ -158,6 +165,7 @@ return { init_options = { bundles = bundles, }, + settings = opts.settings, -- enable CMP capabilities capabilities = LazyVim.has("cmp-nvim-lsp") and require("cmp_nvim_lsp").default_capabilities() or nil, }, opts.jdtls) diff --git a/lua/lazyvim/plugins/extras/lang/kotlin.lua b/lua/lazyvim/plugins/extras/lang/kotlin.lua new file mode 100644 index 00000000..1db56545 --- /dev/null +++ b/lua/lazyvim/plugins/extras/lang/kotlin.lua @@ -0,0 +1,117 @@ +return { + recommended = function() + return LazyVim.extras.wants({ + ft = "kotlin", + root = { + "settings.gradle", -- Gradle (multi-project) + "settings.gradle.kts", -- Gradle (multi-project) + "build.xml", -- Ant + "pom.xml", -- Maven + "build.gradle", -- Gradle + "build.gradle.kts", -- Gradle + }, + }) + end, + -- Add packages(linting, debug adapter) + { + "williamboman/mason.nvim", + opts = function(_, opts) + vim.list_extend(opts.ensure_installed or {}, { "ktlint", "kotlin-debug-adapter" }) + end, + }, + -- Add syntax highlighting + { + "nvim-treesitter/nvim-treesitter", + opts = function(_, opts) + vim.list_extend(opts.ensure_installed or {}, { "kotlin" }) + end, + }, + -- Add language server + { + "neovim/nvim-lspconfig", + opts = { + servers = { + kotlin_language_server = {}, + }, + }, + }, + -- Add linting as optional + { + "mfussenegger/nvim-lint", + optional = true, + dependencies = "williamboman/mason.nvim", + opts = { + linters_by_ft = { kotlin = { "ktlint" } }, + }, + }, + -- Add formatting as optional + { + "stevearc/conform.nvim", + optional = true, + opts = { + formatters_by_ft = { kotlin = { "ktlint" } }, + }, + }, + -- Add formatting and linting as optional + { + "nvimtools/none-ls.nvim", + optional = true, + opts = function(_, opts) + local nls = require("null-ls") + opts.sources = vim.list_extend(opts.sources or {}, { + nls.builtins.formatting.ktlint, + nls.builtins.diagnostics.ktlint, + }) + end, + }, + -- Add debugger + { + "mfussenegger/nvim-dap", + optional = true, + dependencies = "williamboman/mason.nvim", + opts = function() + local dap = require("dap") + if not dap.adapters.kotlin then + require("dap").adapters.kotlin = { + type = "executable", + command = "kotlin-debug-adapter", + options = { auto_continue_if_many_stopped = false }, + } + end + + dap.configurations.kotlin = { + { + type = "kotlin", + request = "launch", + name = "This file", + -- may differ, when in doubt, whatever your project structure may be, + -- it has to correspond to the class file located at `build/classes/` + -- and of course you have to build before you debug + mainClass = function() + local root = vim.fs.find("src", { path = vim.uv.cwd(), upward = true, stop = vim.env.HOME })[1] or "" + local fname = vim.api.nvim_buf_get_name(0) + -- src/main/kotlin/websearch/Main.kt -> websearch.MainKt + return fname:gsub(root, ""):gsub("main/kotlin/", ""):gsub(".kt", "Kt"):gsub("/", "."):sub(2, -1) + end, + projectRoot = "${workspaceFolder}", + jsonLogFile = "", + enableJsonLogging = false, + }, + { + -- Use this for unit tests + -- First, run + -- ./gradlew --info cleanTest test --debug-jvm + -- then attach the debugger to it + type = "kotlin", + request = "attach", + name = "Attach to debugging session", + port = 5005, + args = {}, + projectRoot = vim.fn.getcwd, + hostName = "localhost", + timeout = 2000, + }, + } + end, + }, +} diff --git a/lua/lazyvim/plugins/extras/lang/toml.lua b/lua/lazyvim/plugins/extras/lang/toml.lua new file mode 100644 index 00000000..9dcc029d --- /dev/null +++ b/lua/lazyvim/plugins/extras/lang/toml.lua @@ -0,0 +1,31 @@ +return { + recommended = function() + return LazyVim.extras.wants({ + ft = "toml", + root = "*.toml", + }) + end, + { + "nvim-treesitter/nvim-treesitter", + opts = function(_, opts) + if type(opts.ensure_installed) == "table" then + vim.list_extend(opts.ensure_installed, { "toml" }) + end + end, + }, + { + "williamboman/mason.nvim", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "taplo" }) + end, + }, + { + "neovim/nvim-lspconfig", + opts = { + servers = { + taplo = {}, + }, + }, + }, +} diff --git a/lua/lazyvim/plugins/extras/vscode.lua b/lua/lazyvim/plugins/extras/vscode.lua index 6f78fd9f..49172cdb 100644 --- a/lua/lazyvim/plugins/extras/vscode.lua +++ b/lua/lazyvim/plugins/extras/vscode.lua @@ -3,17 +3,20 @@ if not vim.g.vscode then end local enabled = { + "dial.nvim", "flit.nvim", "lazy.nvim", "leap.nvim", "mini.ai", "mini.comment", + "mini.move", "mini.pairs", "mini.surround", "nvim-treesitter", "nvim-treesitter-textobjects", "nvim-ts-context-commentstring", "vim-repeat", + "yanky.nvim", "LazyVim", } diff --git a/lua/lazyvim/plugins/lsp/init.lua b/lua/lazyvim/plugins/lsp/init.lua index 3a6ae964..5cc32494 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() + 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..fd836d4e --- /dev/null +++ b/lua/lazyvim/util/cmp.lua @@ -0,0 +1,106 @@ +---@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. +---@param snippet string +---@return string +function M.snippet_preview(snippet) + local ret = M.snippet_replace(snippet, function(placeholder) + return M.snippet_preview(placeholder.text) + end):gsub("%$0", "") + return ret +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_preview(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_preview(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..6479f1df 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,13 +21,85 @@ 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 + +---@type table>> +M._supports_method = {} + +function M.setup() + 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 + M.on_attach(M._check_methods) + M.on_dynamic_capability(M._check_methods) +end + +---@param client vim.lsp.Client +function M._check_methods(client, buffer) + for method, clients in pairs(M._supports_method) do + clients[client] = clients[client] or {} + if not clients[client][buffer] then + if client.supports_method(method, { bufnr = buffer }) then + clients[client][buffer] = true + vim.api.nvim_exec_autocmds("User", { + pattern = "LspSupportsMethod", + data = { client_id = client.id, buffer = buffer, method = method }, + }) + end + end + 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 + +---@param method string +---@param fn fun(client:vim.lsp.Client, buffer) +function M.on_supports_method(method, fn) + M._supports_method[method] = M._supports_method[method] or setmetatable({}, { __mode = "k" }) + return vim.api.nvim_create_autocmd("User", { + pattern = "LspSupportsMethod", + callback = function(args) + local client = vim.lsp.get_client_by_id(args.data.client_id) + local buffer = args.data.buffer ---@type number + if client and method == args.data.method then + return fn(client, buffer) + end end, }) end @@ -89,12 +161,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 +215,20 @@ 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(_, buf) + 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 - end, - }) - end + end + end, + }) end) end