diff --git a/init.lua b/init.lua index 45993dc..e24a596 100644 --- a/init.lua +++ b/init.lua @@ -37,6 +37,10 @@ require("pack").setup({ "https://github.com/stevearc/oil.nvim", "https://github.com/hedyhli/outline.nvim", "https://github.com/jiaoshijie/undotree", + { + "https://github.com/saghen/blink.cmp", + version = vim.version.range("^1"), + }, { "https://github.com/tree-sitter/tree-sitter-bash", ts_parser = "bash", diff --git a/lua/core/keymap.lua b/lua/core/keymap.lua index b6545fc..0ae67e7 100644 --- a/lua/core/keymap.lua +++ b/lua/core/keymap.lua @@ -99,9 +99,7 @@ vim.keymap.set("n", "gr", "") vim.cmd.aunmenu({ "PopUp.-1-" }) vim.cmd.aunmenu({ "PopUp.How-to\\ disable\\ mouse" }) --- Insert-mode Emacs bindings -vim.keymap.set("i", "", "") -vim.keymap.set("i", "", "") +-- Insert-mode Emacs bindings (C-f/C-b live further down inside hover_scroll_map) vim.keymap.set("i", "", "^") vim.keymap.set("i", "", function() -- Fall through to Vim's default (close popup + revert) during completion. @@ -160,8 +158,43 @@ vim.keymap.set("n", "K", function() vim.lsp.buf.hover({ max_width = 80 }) end) vim.keymap.set({ "i", "s" }, "", function() + local winid = vim.b.lsp_floating_preview + if winid and vim.api.nvim_win_is_valid(winid) then + vim.api.nvim_win_close(winid, false) + return + end vim.lsp.buf.signature_help({ max_width = 80 }) end) + +---@param mode string | string[] +---@param key string +---@param direction "up" | "down" +---@param count integer +---@param fallback? string +local function hover_scroll_map(mode, key, direction, count, fallback) + vim.keymap.set(mode, key, function() + local winid = vim.b.lsp_floating_preview + if not winid or not vim.api.nvim_win_is_valid(winid) then + return fallback or key + end + vim.schedule(function() + local scroll_key = direction == "down" and vim.keycode("") + or vim.keycode("") + vim.api.nvim_win_call(winid, function() + vim.cmd.normal({ + args = { count .. scroll_key }, + bang = true, + }) + end) + end) + return "" + end, { expr = true, replace_keycodes = true }) +end +hover_scroll_map({ "n", "s" }, "", "down", 5) +hover_scroll_map({ "n", "s" }, "", "up", 5) +hover_scroll_map("i", "", "down", 5, "") +hover_scroll_map("i", "", "up", 5, "") + ---@param key string ---@param dir 1 | -1 local function snippet_jump_map(key, dir) @@ -174,6 +207,7 @@ local function snippet_jump_map(key, dir) end snippet_jump_map("", 1) snippet_jump_map("", -1) + vim.keymap.set({ "n", "i" }, "", vim.lsp.buf.document_highlight) vim.keymap.set({ "n", "x" }, "lf", vim.lsp.buf.format) vim.keymap.set("n", "grl", function() diff --git a/lua/lsp/completion/init.lua b/lua/lsp/completion/init.lua index 3f0d54e..e366a3d 100644 --- a/lua/lsp/completion/init.lua +++ b/lua/lsp/completion/init.lua @@ -6,16 +6,9 @@ local GROUP = vim.api.nvim_create_augroup("ow.lsp.completion", { clear = true }) local popup = Popup.new() -local M = {} - ----@param capabilities lsp.ClientCapabilities -function M.apply_capabilities(capabilities) - capabilities.textDocument.completion.completionItem.snippetSupport = true -end - ---@param client vim.lsp.Client ---@param buf integer -function M.on_attach(client, buf) +local function on_attach(client, buf) if not client:supports_method( vim.lsp.protocol.Methods.textDocument_completion @@ -34,7 +27,29 @@ function M.on_attach(client, buf) }) end +local M = {} + function M.setup() + vim.lsp.config("*", { + capabilities = { + textDocument = { + completion = { + completionItem = { snippetSupport = true }, + }, + }, + }, + }) + + vim.api.nvim_create_autocmd("LspAttach", { + group = GROUP, + callback = function(ev) + local client = vim.lsp.get_client_by_id(ev.data.client_id) + if client then + on_attach(client, ev.buf) + end + end, + }) + vim.api.nvim_create_autocmd("CompleteChanged", { group = GROUP, callback = function(ev) diff --git a/lua/lsp/init.lua b/lua/lsp/init.lua index f7a3676..2eea8c1 100644 --- a/lua/lsp/init.lua +++ b/lua/lsp/init.lua @@ -4,7 +4,6 @@ ---@field context lsp.HandlerContext local codelens = require("lsp.codelens") -local completion = require("lsp.completion") local diagnostic = require("lsp.diagnostic") local log = require("log") @@ -43,8 +42,6 @@ local function on_attach(client, buf) client.settings ) or client.settings - completion.on_attach(client, buf) - vim.api.nvim_clear_autocmds({ group = GROUP, buffer = buf }) vim.api.nvim_create_autocmd("LspProgress", { buffer = buf, @@ -91,8 +88,7 @@ function M.setup() "zls", }) - local capabilities = vim.lsp.protocol.make_client_capabilities() - completion.apply_capabilities(capabilities) + local capabilities = require("blink.cmp").get_lsp_capabilities({}, true) vim.lsp.config("*", { capabilities = capabilities, }) @@ -107,7 +103,7 @@ function M.setup() end, }) - completion.setup() + -- require("lsp.completion").setup() codelens.setup() vim.lsp.log.set_level(vim.log.levels.WARN) diff --git a/nvim-pack-lock.json b/nvim-pack-lock.json index 9668002..ffd1f3b 100644 --- a/nvim-pack-lock.json +++ b/nvim-pack-lock.json @@ -4,6 +4,11 @@ "rev": "e30b7f2008e52442154b66f7c519bfd2f1e32acb", "src": "https://github.com/numToStr/Comment.nvim" }, + "blink.cmp": { + "rev": "78336bc89ee5365633bcf754d93df01678b5c08f", + "src": "https://github.com/saghen/blink.cmp", + "version": "1.0.0 - 2.0.0" + }, "fzf-lua": { "rev": "1e866cce085cc6df3d3e4fb59f00105fa84cef6c", "src": "https://github.com/ibhagwan/fzf-lua" diff --git a/plugins/blink.cmp.lua b/plugins/blink.cmp.lua new file mode 100644 index 0000000..2ed9c18 --- /dev/null +++ b/plugins/blink.cmp.lua @@ -0,0 +1,89 @@ +local blink = require("blink.cmp") +blink.setup({ + completion = { + documentation = { + auto_show = true, + auto_show_delay_ms = 0, + window = { + winhighlight = "", + }, + }, + ghost_text = { + enabled = true, + }, + list = { + selection = { + preselect = false, + auto_insert = false, + }, + }, + menu = { + border = "none", + draw = { + align_to = "simple_label", + columns = { + { "simple_label" }, + { "kind_icon" }, + }, + components = { + simple_label = { + width = { fill = true, max = 60 }, + text = function(ctx) + return ctx.label + end, + highlight = function(ctx) + local highlights = { + { + 0, + #ctx.label, + group = ctx.deprecated + and "BlinkCmpLabelDeprecated" + or "BlinkCmpLabel", + }, + } + for _, idx in ipairs(ctx.label_matched_indices) do + table.insert(highlights, { + idx, + idx + 1, + group = "BlinkCmpLabelMatch", + }) + end + + return highlights + end, + }, + }, + }, + }, + }, + fuzzy = { + implementation = "prefer_rust_with_warning", + }, + signature = { + enabled = true, + window = { + winhighlight = "", + show_documentation = false, + }, + }, + sources = { + default = { + "lsp", + "path", + "snippets", + }, + transform_items = function(_, items) + ---@param item blink.cmp.CompletionItem + return vim.tbl_map(function(item) + item.kind_icon, item.kind_hl = + require("lsp.kind").get(item.kind) + + return item + end, items) + end, + }, + keymap = { + preset = "default", + [""] = { "accept", "fallback" }, + }, +})