From 3e369ee31ec9583f794ff910a1ad68cc77d389ce Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Wed, 14 Aug 2024 23:12:55 +0200 Subject: [PATCH] nvim: Refactor completion plugins Begin a larger refactor with nvim-cmp, which separates out the different nvim-cmp modules to be loaded at different times and for different files (such as beancount completion on loaded for beancount files and so on). This is by no means complete but the start of a larger overhaul process. --- nvim/.config/nvim/lua/plugins/completion.lua | 213 +++++++++++++------ 1 file changed, 143 insertions(+), 70 deletions(-) diff --git a/nvim/.config/nvim/lua/plugins/completion.lua b/nvim/.config/nvim/lua/plugins/completion.lua index e8dedd7..aaf31fc 100644 --- a/nvim/.config/nvim/lua/plugins/completion.lua +++ b/nvim/.config/nvim/lua/plugins/completion.lua @@ -1,53 +1,29 @@ -return { - -- completion setup +local completion_engine = { { "hrsh7th/nvim-cmp", branch = "main", - version = false, + version = false, -- new releases (>2022) are sadly not versioned dependencies = { - "andersevenrud/cmp-tmux", - "cbarrete/completion-vcard", - "f3fora/cmp-spell", + -- TODO: Move to lsp "hrsh7th/cmp-nvim-lsp", + "hrsh7th/cmp-nvim-lsp-signature-help", "hrsh7th/cmp-path", "hrsh7th/cmp-buffer", "hrsh7th/cmp-calc", "hrsh7th/cmp-cmdline", - "hrsh7th/cmp-nvim-lsp-signature-help", - "dmitmel/cmp-digraphs", + -- TODO: Move me into a separate load? + "cbarrete/completion-vcard", + "f3fora/cmp-spell", "jc-doyle/cmp-pandoc-references", - "kdheepak/cmp-latex-symbols", + -- TODO: Decide: get rid or just enable in very specific circumstances "lukas-reineke/cmp-rg", - "crispgm/cmp-beancount", + -- TODO: Move to treesitter { "ray-x/cmp-treesitter", dependencies = { "nvim-treesitter/nvim-treesitter" } }, - { - "saadparwaiz1/cmp_luasnip", - dependencies = { - - { - "L3MON4D3/LuaSnip", - dependencies = { - "rafamadriz/friendly-snippets", - { - "benfowler/telescope-luasnip.nvim", - dependencies = { { "nvim-telescope/telescope.nvim", optional = true } }, - config = function() - require("telescope").load_extension("luasnip") - end, - }, - }, - build = "make install_jsregexp", - config = function() - require("luasnip.loaders.from_vscode").lazy_load({ exclude = { "markdown", "quarto" } }) - require("luasnip.loaders.from_snipmate").lazy_load() - end, - }, - }, - }, }, - config = function() - local luasnip = require("luasnip") + opts = function() local cmp = require("cmp") + -- style 'ghosttext' which appears behind cursor, showing current completion + vim.api.nvim_set_hl(0, "CmpGhostText", { link = "Comment", default = true }) local has_words_before = function() ---@diagnostic disable-next-line:deprecated @@ -84,32 +60,42 @@ return { TypeParameter = "", } - cmp.setup({ + -- `/` cmdline setup. + cmp.setup.cmdline("/", { + completion = { completeopt = "menu,menuone,noinsert,noselect" }, + preselect = cmp.PreselectMode.None, + mapping = cmp.mapping.preset.cmdline(), + sources = { { name = "buffer" } }, + }) + -- `:` cmdline setup. + cmp.setup.cmdline(":", { + completion = { completeopt = "menu,menuone,noinsert,noselect" }, + preselect = cmp.PreselectMode.None, + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ { name = "path" } }, { + { name = "cmdline", option = { ignore_cmds = { "Man", "!" } } }, + }), + }) + return { window = { documentation = cmp.config.window.bordered() }, - snippet = { - expand = function(args) - require("luasnip").lsp_expand(args.body) - end, + -- add noselect to not automatically select first item + completion = { completeopt = "menu,menuone,noinsert" }, + preselect = cmp.PreselectMode.Item, -- not sure what this changes diff than above? + experimental = { + ghost_text = { + hl_group = "CmpGhostText", + }, }, sources = { - { - name = "beancount", - option = { - account = vim.env["HOME"] .. "/documents/records/budget/main.beancount", -- TODO implement dynamically - }, - }, { name = "nvim_lsp" }, { name = "nvim_lsp_signature_help" }, - { name = "luasnip", keyword_length = 1 }, { name = "pandoc_references" }, { name = "calc" }, { name = "path" }, { name = "buffer", keyword_length = 3 }, - { name = "latex_symbols" }, { name = "spell", keyword_length = 3 }, - { name = "tmux" }, -- { name = 'rg', keyword_length = 5 }, + -- { name = 'rg', keyword_length = 5 }, { name = "vCard" }, - { name = "digraphs", keyword_length = 2 }, }, mapping = cmp.mapping.preset.insert({ [""] = cmp.mapping.scroll_docs(-4), @@ -134,9 +120,7 @@ return { [""] = cmp.mapping(function(fallback) -- expand_or_jumpable() will always jump -- expand_or_locally_jumpable() only jumps when still inside snippet region - if luasnip.expand_or_locally_jumpable() then - luasnip.expand_or_jump() - elseif cmp.visible() then + if cmp.visible() then cmp.select_next_item() elseif has_words_before() then cmp.complete() @@ -145,9 +129,7 @@ return { end end, { "i", "s" }), [""] = cmp.mapping(function(fallback) - if luasnip.jumpable(-1) then - luasnip.jump(-1) - elseif cmp.visible() then + if cmp.visible() then cmp.select_prev_item() else fallback() @@ -178,20 +160,111 @@ return { return vim_item end, }, - }) - -- `/` cmdline setup. - cmp.setup.cmdline("/", { - mapping = cmp.mapping.preset.cmdline(), - sources = { { name = "buffer" } }, - }) - -- `:` cmdline setup. - cmp.setup.cmdline(":", { - mapping = cmp.mapping.preset.cmdline(), - sources = cmp.config.sources({ { name = "path" } }, { - { name = "cmdline", option = { ignore_cmds = { "Man", "!" } } }, - }), - }) + } end, event = { "InsertEnter", "CmdlineEnter" }, }, } +-- +-- TODO: Enable more lazy loaded startup? And integrate into +-- cmp as insert source instead of in its setup config below. +local snippet_engine = { + "nvim-cmp", + dependencies = { + "L3MON4D3/LuaSnip", + "rafamadriz/friendly-snippets", + "saadparwaiz1/cmp_luasnip", + { + "benfowler/telescope-luasnip.nvim", + dependencies = { { "nvim-telescope/telescope.nvim", optional = true } }, + config = function() + if require("core.util").is_available("telescope") then + require("telescope").load_extension("luasnip") + end + end, + }, + }, + event = { "InsertEnter" }, + build = "make install_jsregexp", + opts = function(_, opts) + local cmp = require("cmp") + local luasnip = require("luasnip") + + require("luasnip.loaders.from_vscode").lazy_load({ exclude = { "markdown", "quarto" } }) + require("luasnip.loaders.from_snipmate").lazy_load() + + opts.snippet = { + expand = function(item) + require("luasnip").lsp_expand(item.body) + end, + } + local has_words_before = function() + ---@diagnostic disable-next-line:deprecated + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil + end + + table.insert(opts.sources, { name = "luasnip", keyword_length = 1 }) + + opts.mapping[""] = cmp.mapping(function(fallback) -- expand_or_jumpable() will always jump + -- expand_or_locally_jumpable() only jumps when still inside snippet region + if luasnip.expand_or_locally_jumpable() then + luasnip.expand_or_jump() + elseif cmp.visible() then + cmp.select_next_item() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { "i", "s" }) + opts.mapping[""] = cmp.mapping(function(fallback) + if luasnip.locally_jumpable(-1) then + luasnip.jump(-1) + elseif cmp.visible() then + cmp.select_prev_item() + else + fallback() + end + end, { "i", "s" }) + end, +} + +local beancount_cmp = { + "nvim-cmp", + dependencies = { + "crispgm/cmp-beancount", + }, + ft = "beancount", + opts = function(_, opts) + vim.g.python3_host_prog = "/home/marty/.local/pipx/venvs/beancount/bin/python" + table.insert(opts.sources, { + name = "beancount", + -- option = { + -- -- TODO: implement dynamically + -- -- I believe if we don't supply this it automatically takes + -- -- from the open file which would be good enough + -- account = "/home/marty/documents/records/budget/main.beancount", + -- }, + }) + end, +} + +local latex_cmp = { + "nvim-cmp", + dependencies = { + -- TODO: Needs better lazy loading + "kdheepak/cmp-latex-symbols", + }, + event = "CursorHold", + opts = function(_, opts) + table.insert(opts.sources, { name = "latex_symbols" }) + end, +} + +return { + completion_engine, + snippet_engine, + beancount_cmp, + latex_cmp +}