diff --git a/modules/programs/nvim/default.nix b/modules/programs/nvim/default.nix index 5549f2b..7b70593 100644 --- a/modules/programs/nvim/default.nix +++ b/modules/programs/nvim/default.nix @@ -33,7 +33,10 @@ in plugins = with pkgs.vimPlugins; [ catppuccin-nvim cmp-nvim-lsp + cmp_luasnip dashboard-nvim + lsp_lines-nvim + luasnip neogit noice-nvim nui-nvim # for noice-nvim @@ -44,9 +47,6 @@ in plenary-nvim # for telescope, neogit telescope-nvim which-key-nvim - cmp_luasnip - luasnip - lsp_lines-nvim ]; }; }; diff --git a/modules/programs/nvim/init.lua b/modules/programs/nvim/init.lua index 4e20fbe..37c8f3f 100644 --- a/modules/programs/nvim/init.lua +++ b/modules/programs/nvim/init.lua @@ -4,7 +4,7 @@ vim.g.maplocalleader = "," -- FIX to create spell dir if not existent local spelldir = vim.fn.stdpath("data") .. "/site/spell" if not vim.loop.fs_stat(spelldir) then - vim.fn.mkdir(spelldir, "p") + vim.fn.mkdir(spelldir, "p") end vim.opt.autoindent = true @@ -34,10 +34,10 @@ vim.opt_local.spell = true vim.opt_local.spelllang = { "en", "de_20" } -- all English regions and new German spelling require("catppuccin").setup({ - compile_path = vim.fn.stdpath("cache") .. "/catppuccin", -- fix issue of writing to nix store - integrations = { - which_key = true, - }, + compile_path = vim.fn.stdpath("cache") .. "/catppuccin", -- fix issue of writing to nix store + integrations = { + which_key = true, + }, }) vim.cmd.colorscheme("catppuccin-macchiato") @@ -46,88 +46,88 @@ vim.o.timeoutlen = 300 local wk = require("which-key") require("noice").setup({ - lsp = { - -- override markdown rendering so that **cmp** and other plugins use **Treesitter** - override = { - ["vim.lsp.util.convert_input_to_markdown_lines"] = true, - ["vim.lsp.util.stylize_markdown"] = true, - ["cmp.entry.get_documentation"] = true, - }, - }, - -- you can enable a preset for easier configuration - presets = { - bottom_search = true, -- use a classic bottom cmdline for search - command_palette = true, -- position the cmdline and popupmenu together - long_message_to_split = true, -- long messages will be sent to a split - inc_rename = false, -- enables an input dialog for inc-rename.nvim - lsp_doc_border = false, -- add a border to hover docs and signature help - }, + lsp = { + -- override markdown rendering so that **cmp** and other plugins use **Treesitter** + override = { + ["vim.lsp.util.convert_input_to_markdown_lines"] = true, + ["vim.lsp.util.stylize_markdown"] = true, + ["cmp.entry.get_documentation"] = true, + }, + }, + -- you can enable a preset for easier configuration + presets = { + bottom_search = true, -- use a classic bottom cmdline for search + command_palette = true, -- position the cmdline and popupmenu together + long_message_to_split = true, -- long messages will be sent to a split + inc_rename = false, -- enables an input dialog for inc-rename.nvim + lsp_doc_border = false, -- add a border to hover docs and signature help + }, }) wk.register({ - f = { - name = "find", - f = { "Telescope find_files", "find file" }, - g = { "Telescope live_grep", "live grep" }, - b = { "Telescope buffers", "find buffer" }, - }, + f = { + name = "find", + f = { "Telescope find_files", "find file" }, + g = { "Telescope live_grep", "live grep" }, + b = { "Telescope buffers", "find buffer" }, + }, }, { prefix = "" }) require("neogit").setup({ - disable_commit_confirmation = true, + disable_commit_confirmation = true, }) wk.register({ - g = { "Neogit", "git" }, + g = { "Neogit", "git" }, }, { prefix = "" }) require("nvim-treesitter.configs").setup({ - sync_install = false, - auto_install = false, - highlight = { - enable = true, - additional_vim_regex_highlighting = true, - }, + sync_install = false, + auto_install = false, + highlight = { + enable = true, + additional_vim_regex_highlighting = true, + }, }) local cmp = require("cmp") local luasnip = require("luasnip") cmp.setup({ - snippet = { - -- REQUIRED - you must specify a snippet engine - expand = function(args) - require("luasnip").lsp_expand(args.body) - end, - }, - mapping = cmp.mapping.preset.insert({ - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.scroll_docs(4), - [""] = cmp.mapping.complete(), - [""] = cmp.mapping.abort(), - [""] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items. - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_next_item() - elseif luasnip.expand_or_jumpable() then - luasnip.expand_or_jump() - else - fallback() - end - end, { "i", "s" }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item() - elseif luasnip.jumpable(-1) then - luasnip.jump(-1) - else - fallback() - end - end, { "i", "s" }), - }), - sources = { - { name = "nvim_lsp" }, - { name = "luasnip" }, - { name = "buffer" }, - }, + snippet = { + -- REQUIRED - you must specify a snippet engine + expand = function(args) + require("luasnip").lsp_expand(args.body) + end, + }, + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.abort(), + [""] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items. + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + else + fallback() + end + end, { "i", "s" }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { "i", "s" }), + }), + sources = { + { name = "nvim_lsp" }, + { name = "luasnip" }, + { name = "buffer" }, + }, }) -- The nvim-cmp almost supports LSP's capabilities so You should advertise it to LSP servers.. @@ -135,99 +135,132 @@ local capabilities = require("cmp_nvim_lsp").default_capabilities() local lspconfig = require("lspconfig") local on_attach_def = function(_, bufnr) - wk.register({ - K = { vim.lsp.buf.hover, "show info" }, - ["l"] = { - name = "lsp", - d = { vim.diagnostic.open_float, "open diagnostic window" }, - n = { vim.diagnostic.goto_next, "next error" }, - p = { vim.diagnostic.goto_prev, "prev error" }, - c = { vim.lsp.buf.code_action, "code action" }, - r = { vim.lsp.buf.rename, "rename" }, - f = { - function() - vim.lsp.buf.format({ async = true }) - end, - "format", - }, - }, - g = { - name = "goto", - r = { vim.lsp.buf.references, "references" }, - d = { vim.lsp.buf.definition, "definition" }, - D = { vim.lsp.buf.declaration, "declaration" }, - i = { vim.lsp.buf.implementation, "implementation" }, - t = { vim.lsp.buf.type_definition, "type defininition" }, - }, - }, { noremap = true, silent = true, buffer = bufnr }) + wk.register({ + K = { vim.lsp.buf.hover, "show info" }, + ["l"] = { + name = "lsp", + d = { vim.diagnostic.open_float, "open diagnostic window" }, + n = { vim.diagnostic.goto_next, "next error" }, + p = { vim.diagnostic.goto_prev, "prev error" }, + c = { vim.lsp.buf.code_action, "code action" }, + r = { vim.lsp.buf.rename, "rename" }, + f = { + function() + vim.lsp.buf.format({ async = true }) + end, + "format", + }, + }, + g = { + name = "goto", + r = { vim.lsp.buf.references, "references" }, + d = { vim.lsp.buf.definition, "definition" }, + D = { vim.lsp.buf.declaration, "declaration" }, + i = { vim.lsp.buf.implementation, "implementation" }, + t = { vim.lsp.buf.type_definition, "type defininition" }, + }, + }, { noremap = true, silent = true, buffer = bufnr }) +end + +---merge tables +---@param ... table[] +---@return table +local function table_merge(...) + local tables_to_merge = { ... } + assert(#tables_to_merge > 1, "There should be at least two tables to merge them") + + for k, t in ipairs(tables_to_merge) do + assert(type(t) == "table", string.format("Expected a table as function parameter %d", k)) + end + + local result = tables_to_merge[1] + + for i = 2, #tables_to_merge do + local from = tables_to_merge[i] + for k, v in pairs(from) do + if type(v) == "table" then + result[k] = result[k] or {} + result[k] = table_merge(result[k], v) + else + result[k] = v + end + end + end + + return result +end + +local lspconfig_default_options = { + on_attach = on_attach_def, + capabilities = capabilities, + flags = { + debounce_text_changes = 100, + }, +} + +---function to add default options to lspconfig +---@param lsp string +---@param options table +---@return nil +local function lspconfig_setup(lsp, options) + local final_options = table_merge(lspconfig_default_options, options) + lspconfig[lsp].setup(final_options) end local servers = { "nil_ls", "pylsp" } for _, lsp in ipairs(servers) do - lspconfig[lsp].setup({ - on_attach = on_attach_def, - capabilities = capabilities, - flags = { - debounce_text_changes = 100, - }, - }) + lspconfig_setup(lsp, {}) end -lspconfig.sumneko_lua.setup({ - on_attach = on_attach_def, - capabilities = capabilities, - settings = { - Lua = { - runtime = { - -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim) - version = "LuaJIT", - }, - diagnostics = { - -- Get the language server to recognize the `vim` global - globals = { "vim" }, - }, - workspace = { - -- Make the server aware of Neovim runtime files - library = vim.api.nvim_get_runtime_file("", true), - checkThirdParty = false, - }, - -- Do not send telemetry data containing a randomized but unique identifier - telemetry = { - enable = false, - }, - format = { - enable = true, - -- Put format options here - -- NOTE: the value should be STRING!! - defaultConfig = { - indent_style = "space", - indent_size = "2", - }, - }, - }, - }, +lspconfig_setup("lua_ls", { + on_attach = on_attach_def, + capabilities = capabilities, + settings = { + Lua = { + runtime = { + -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim) + version = "LuaJIT", + }, + diagnostics = { + -- Get the language server to recognize the `vim` global + globals = { "vim" }, + }, + workspace = { + -- Make the server aware of Neovim runtime files + library = vim.api.nvim_get_runtime_file("", true), + checkThirdParty = false, + }, + -- Do not send telemetry data containing a randomized but unique identifier + telemetry = { + enable = false, + }, + format = { + enable = false, + }, + }, + }, }) local lsp_lines = require("lsp_lines") lsp_lines.setup() -- Disable virtual_text since it's redundant due to lsp_lines. vim.diagnostic.config({ - virtual_text = false, + virtual_text = false, }) wk.register({ - t = { - name = "toggle", - l = { lsp_lines.toggle, "lsp lines" }, - }, - { prefix = "" }, + t = { + name = "toggle", + l = { lsp_lines.toggle, "lsp lines" }, + }, + { prefix = "" }, }) require("dashboard").setup({ - theme = "hyper", - config = { - packages = { enable = true }, - week_header = { - enable = true, - }, - }, + theme = "hyper", + config = { + packages = { enable = true }, + week_header = { + enable = true, + }, + }, })