From aff61966710b129fe043d3ae0ccad6ea4d14c60b Mon Sep 17 00:00:00 2001 From: Kalle Struik Date: Wed, 1 Nov 2023 16:27:35 +0100 Subject: [PATCH] Initial vim config --- flake.lock | 36 ++++++++- flake.nix | 10 +++ home-manager/kalle-pc/kalle.nix | 26 ++++--- nvim/default.nix | 129 +++++++++++++++++++++++++++++--- nvim/init.lua | 0 nvim/keymaps.lua | 44 +++++++++++ nvim/options.lua | 41 ++++++++++ nvim/plugin/cmp.lua | 93 +++++++++++++++++++++++ nvim/plugin/lsp.lua | 115 ++++++++++++++++++++++++++++ nvim/plugin/treesitter.lua | 9 +++ overlays/default.nix | 20 +++++ 11 files changed, 504 insertions(+), 19 deletions(-) delete mode 100644 nvim/init.lua create mode 100644 nvim/keymaps.lua create mode 100644 nvim/options.lua create mode 100644 nvim/plugin/cmp.lua create mode 100644 nvim/plugin/lsp.lua create mode 100644 nvim/plugin/treesitter.lua create mode 100644 overlays/default.nix diff --git a/flake.lock b/flake.lock index 96f66a2..a148efa 100644 --- a/flake.lock +++ b/flake.lock @@ -37,10 +37,44 @@ "type": "github" } }, + "plugin-rainbow-delimiters-nvim": { + "flake": false, + "locked": { + "lastModified": 1698573782, + "narHash": "sha256-rJOWVz1cplThmx9HY7RqYSxUgKKq1yjzhS4Pb2ebFQ4=", + "owner": "HiPhish", + "repo": "rainbow-delimiters.nvim", + "rev": "df8cdf68234fbf056202a9684931c3dfa89988c1", + "type": "gitlab" + }, + "original": { + "owner": "HiPhish", + "repo": "rainbow-delimiters.nvim", + "type": "gitlab" + } + }, + "plugin-undotree-nvim": { + "flake": false, + "locked": { + "lastModified": 1695641489, + "narHash": "sha256-1d7OMaWsf0MW6w6Yzev9b3qF6Va4y8VNciSEdWq+VxY=", + "owner": "jiaoshijie", + "repo": "undotree", + "rev": "41f56b30cc774ad26c4945c7e10673453893e7ad", + "type": "github" + }, + "original": { + "owner": "jiaoshijie", + "repo": "undotree", + "type": "github" + } + }, "root": { "inputs": { "home-manager": "home-manager", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "plugin-rainbow-delimiters-nvim": "plugin-rainbow-delimiters-nvim", + "plugin-undotree-nvim": "plugin-undotree-nvim" } } }, diff --git a/flake.nix b/flake.nix index af3198a..8715727 100644 --- a/flake.nix +++ b/flake.nix @@ -8,6 +8,14 @@ # Home manager home-manager.url = "github:nix-community/home-manager/release-23.05"; home-manager.inputs.nixpkgs.follows = "nixpkgs"; + + + # Neovim plugins not in nixpkgs + plugin-rainbow-delimiters-nvim.url = "gitlab:HiPhish/rainbow-delimiters.nvim"; + plugin-rainbow-delimiters-nvim.flake = false; + + plugin-undotree-nvim.url = "github:jiaoshijie/undotree"; + plugin-undotree-nvim.flake = false; }; outputs = { @@ -18,6 +26,8 @@ } @ inputs : let inherit (self) outputs; in { + overlays = import ./overlays {inherit inputs;}; + nixosConfigurations = { "kalle-pc" = nixpkgs.lib.nixosSystem { specialArgs = {inherit inputs outputs;}; diff --git a/home-manager/kalle-pc/kalle.nix b/home-manager/kalle-pc/kalle.nix index f608008..2cfcea5 100644 --- a/home-manager/kalle-pc/kalle.nix +++ b/home-manager/kalle-pc/kalle.nix @@ -1,9 +1,9 @@ -{ - inputs, - lib, - config, - pkgs, - ... +{ inputs +, outputs +, lib +, config +, pkgs +, ... }: { @@ -16,8 +16,16 @@ ../../nvim ]; - nixpkgs.config.allowUnfree = true; - nixpkgs.config.allowUnfreePredicate = _: true; + nixpkgs = { + overlays = with outputs.overlays; [ + nvim-plugins + ]; + + config = { + allowUnfree = true; + allowUnfreePredicate = _: true; + }; + }; # The home.packages option allows you to install Nix packages into your # environment. @@ -25,9 +33,9 @@ discord firefox httpie - neovim kate kitty + rustup # # It is sometimes useful to fine-tune packages, for example, by applying # # overrides. You can do that directly here, just don't forget the diff --git a/nvim/default.nix b/nvim/default.nix index 6991646..4958b84 100644 --- a/nvim/default.nix +++ b/nvim/default.nix @@ -1,13 +1,124 @@ -{ - inputs, - lib, - config, - pkgs, - ... +{ inputs +, lib +, config +, pkgs +, ... }: { - xdg.configFile = { - "nvim/init.lua".source = ./init.lua; - }; + programs.neovim = + let + toLua = str: "lua << EOF\n${str}\nEOF\n"; + toLuaFile = file: "lua << EOF\n${builtins.readFile file}\nEOF\n"; + in + { + enable = true; + + viAlias = true; + vimAlias = true; + vimdiffAlias = true; + + extraPackages = with pkgs; [ + lua-language-server + rnix-lsp + + ripgrep + wl-clipboard + ]; + + plugins = with pkgs.vimPlugins; [ + { + plugin = which-key-nvim; + config = toLua "require('which-key').setup()"; + } + + neodev-nvim + plenary-nvim + + telescope-nvim + telescope-ui-select-nvim + + FTerm-nvim + + neogit + + harpoon + + { + plugin = undotree-nvim; + config = toLua "require('undotree').setup()"; + } + + { + plugin = comment-nvim; + config = toLua "require('Comment').setup()"; + } + { + plugin = todo-comments-nvim; + config = toLua "require('todo-comments').setup()"; + } + + { + plugin = neoconf-nvim; + config = toLua "require('neoconf').setup()"; + } + { + plugin = catppuccin-nvim; + config = "colorscheme catppuccin-mocha"; + } + + cmp-nvim-lsp + cmp-nvim-lsp-signature-help + cmp-buffer + cmp-path + cmp-cmdline + cmp-git + cmp-calc + cmp_luasnip + luasnip + friendly-snippets + { + plugin = nvim-cmp; + config = toLuaFile ./plugin/cmp.lua; + } + + + { + plugin = nvim-lspconfig; + config = toLuaFile ./plugin/lsp.lua; + } + rust-tools-nvim + { + plugin = fidget-nvim; + config = toLua "require('fidget').setup({})"; + } + + rainbow-delimiters-nvim + + { + plugin = (nvim-treesitter.withPlugins (p: [ + p.tree-sitter-nix + p.tree-sitter-vim + p.tree-sitter-bash + p.tree-sitter-lua + p.tree-sitter-python + p.tree-sitter-json + p.tree-sitter-yaml + p.tree-sitter-rust + p.tree-sitter-javascript + p.tree-sitter-typescript + p.tree-sitter-c + p.tree-sitter-cpp + ])); + config = toLuaFile ./plugin/treesitter.lua; + } + + ]; + + extraLuaConfig = '' + ${builtins.readFile ./options.lua} + ${builtins.readFile ./keymaps.lua} + ''; + + }; } diff --git a/nvim/init.lua b/nvim/init.lua deleted file mode 100644 index e69de29..0000000 diff --git a/nvim/keymaps.lua b/nvim/keymaps.lua new file mode 100644 index 0000000..9493b37 --- /dev/null +++ b/nvim/keymaps.lua @@ -0,0 +1,44 @@ +---@diagnostic disable: redefined-local + +local function map(mode, keys, func, desc, silent) + local silent = silent == nil and true or silent + vim.keymap.set(mode, keys, func, { desc = desc, silent = silent }) +end + +-- Movement between windows +map('n', 'h', function() vim.cmd.wincmd('h') end, "Window Left") +map('n', 'j', function() vim.cmd.wincmd('j') end, "Window Down") +map('n', 'k', function() vim.cmd.wincmd('k') end, "Window Up") +map('n', 'l', function() vim.cmd.wincmd('l') end, "Window Right") + +-- Harpoon keybinds +map('n', 'mm', require('harpoon.mark').add_file, "[M]ark file in harpoon") +map('n', 'mh', require('harpoon.ui').toggle_quick_menu, "[M]enu [H]arpoon") +map('n', '1', function() require('harpoon.ui').nav_file(1) end, "Harpoon [1]") +map('n', '2', function() require('harpoon.ui').nav_file(2) end, "Harpoon [2]") +map('n', '3', function() require('harpoon.ui').nav_file(3) end, "Harpoon [3]") +map('n', '4', function() require('harpoon.ui').nav_file(4) end, "Harpoon [4]") +map('n', '5', function() require('harpoon.ui').nav_file(5) end, "Harpoon [5]") +map('n', '6', function() require('harpoon.ui').nav_file(6) end, "Harpoon [6]") +map('n', '7', function() require('harpoon.ui').nav_file(7) end, "Harpoon [7]") +map('n', '8', function() require('harpoon.ui').nav_file(8) end, "Harpoon [8]") +map('n', '9', function() require('harpoon.ui').nav_file(9) end, "Harpoon [9]") + +map('n', 'tg', vim.cmd.Neogit, '[T]oggle [G]it view') +map('n', 'tu', require('undotree').toggle, '[T]oggle [U]ndo tree') + +map('n', '[d', vim.diagnostic.goto_prev, 'Goto Previous Diagnostic') +map('n', ']d', vim.diagnostic.goto_next, 'Goto Next Diagnostic') +map('n', 'e', vim.diagnostic.open_float, 'Show [E]rrors') +map('n', 'q', vim.diagnostic.setloclist, 'Errors to [Q]uickfix') + + +map('n', '?', require('telescope.builtin').oldfiles, '[?] Find recently opened files') +map('n', '', require('telescope.builtin').find_files, '[ ]Search Files') +map('n', 'sb', require('telescope.builtin').buffers, '[S]earch [B]uffers') +map('n', 'sh', require('telescope.builtin').help_tags, '[S]earch [H]elp') +map('n', 'sw', require('telescope.builtin').grep_string, '[S]earch current [W]ord') +map('n', 'sg', require('telescope.builtin').live_grep, '[S]earch by [G]rep') +map('n', 'sd', require('telescope.builtin').diagnostics, '[S]earch [D]iagnostics') + +map({ 'n', 't' }, '', require("FTerm").toggle, 'Toggle Terminal') diff --git a/nvim/options.lua b/nvim/options.lua new file mode 100644 index 0000000..2ee098c --- /dev/null +++ b/nvim/options.lua @@ -0,0 +1,41 @@ +vim.opt.termguicolors = true +vim.opt.clipboard = 'unnamed,unnamedplus' +vim.opt.timeoutlen = 300 +vim.opt.mouse = 'a' +vim.opt.listchars = 'tab:▸ ,extends:❯,precedes:❮' + +vim.opt.swapfile = false +vim.opt.backup = false +vim.opt.undodir = vim.fn.expand('~/.cache/vim/undo') +vim.opt.undofile = true + +vim.opt.number = true +vim.opt.relativenumber = true +vim.opt.list = true + +vim.opt.wrap = false + +vim.opt.scrolloff = 8 + +vim.opt.autoindent = true +vim.opt.expandtab = true +vim.opt.softtabstop = 4 +vim.opt.shiftwidth = 4 +vim.opt.tabstop = 4 +vim.opt.smartindent = true +vim.opt.modeline = true + +vim.opt.spell = true + +vim.g.mapleader = ' ' + +vim.opt.hlsearch = false +vim.opt.incsearch = true +vim.opt.signcolumn = 'yes' + +vim.opt.updatetime = 50 +vim.opt.completeopt = { 'menuone', 'noselect', 'noinsert' } +vim.opt.shortmess = vim.opt.shortmess + { c = true } + +-- Autoformat on save +vim.cmd [[autocmd BufWritePre * lua vim.lsp.buf.format()]] diff --git a/nvim/plugin/cmp.lua b/nvim/plugin/cmp.lua new file mode 100644 index 0000000..25a6012 --- /dev/null +++ b/nvim/plugin/cmp.lua @@ -0,0 +1,93 @@ +local cmp = require 'cmp' +local luasnip = require 'luasnip' + +cmp.setup({ + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + mapping = cmp.mapping.preset.insert({ + [''] = cmp.mapping.select_prev_item(), + [''] = cmp.mapping.select_next_item(), + -- Add tab support + [''] = 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' }), + [''] = 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.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + [''] = cmp.mapping.complete(), + [''] = cmp.mapping.close(), + [''] = cmp.mapping.confirm({ + behavior = cmp.ConfirmBehavior.Insert, + select = true, + }) + }), + sources = cmp.config.sources({ + { name = 'path' }, -- file paths + { name = 'nvim_lsp' }, -- from language server + { name = 'nvim_lsp_signature_help' }, -- display function signatures with current parameter emphasized + { name = 'luasnip' }, + { name = 'nvim_lua' }, -- complete neovim's Lua runtime API such vim.lsp.* + { name = 'buffer' }, -- source current buffer + { name = 'calc' }, -- source for math calculation + }), + window = { + completion = cmp.config.window.bordered(), + documentation = cmp.config.window.bordered(), + }, + formatting = { + fields = { 'menu', 'abbr', 'kind' }, + format = function(entry, item) + local menu_icon = { + nvim_lsp = 'λ', + vsnip = '⋗', + buffer = 'Ω', + path = '🖫', + } + item.menu = menu_icon[entry.source.name] + return item + end, + }, +}) + +cmp.setup.filetype('gitcommit', { + sources = cmp.config.sources({ + { name = 'cmp_git' }, -- You can specify the `cmp_git` source if you were installed it. + }, { + { name = 'buffer' }, + }) +}) + +-- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore). +cmp.setup.cmdline('/', { + mapping = cmp.mapping.preset.cmdline(), + sources = { + { name = 'buffer' } + } +}) + +-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore). +cmp.setup.cmdline(':', { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ + { name = 'path' } + }, { + { name = 'cmdline' } + }) +}) diff --git a/nvim/plugin/lsp.lua b/nvim/plugin/lsp.lua new file mode 100644 index 0000000..d69a896 --- /dev/null +++ b/nvim/plugin/lsp.lua @@ -0,0 +1,115 @@ +local on_attach = function(_, bufnr) + local nmap = function(keys, func, desc) + if desc then + desc = 'LSP: ' .. desc + end + + vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc }) + end + + nmap('rn', vim.lsp.buf.rename, '[R]e[n]ame') + nmap('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') + + nmap('gd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition') + nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') + nmap('gI', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation') + nmap('D', require('telescope.builtin').lsp_type_definitions, 'Type [D]efinition') + nmap('ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols') + nmap('ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') + + -- See `:help K` for why this keymap + nmap('K', vim.lsp.buf.hover, 'Hover Documentation') + nmap('', vim.lsp.buf.signature_help, 'Signature Documentation') + + -- Lesser used LSP functionality + nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + nmap('wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder') + nmap('wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder') + nmap('wl', function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, '[W]orkspace [L]ist Folders') + + -- Create a command `:Format` local to the LSP buffer + vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_) + if vim.lsp.buf.format then + vim.lsp.buf.format() + elseif vim.lsp.buf.formatting then + vim.lsp.buf.formatting() + end + end, { desc = 'Format current buffer with LSP' }) +end + +-- LSP Diagnostics Options Setup +local sign = function(opts) + vim.fn.sign_define(opts.name, { + texthl = opts.name, + text = opts.text, + numhl = '' + }) +end + +sign({ name = 'DiagnosticSignError', text = '' }) +sign({ name = 'DiagnosticSignWarn', text = '' }) +sign({ name = 'DiagnosticSignHint', text = '' }) +sign({ name = 'DiagnosticSignInfo', text = '' }) + +vim.diagnostic.config({ + virtual_text = false, + signs = true, + update_in_insert = true, + underline = true, + severity_sort = false, + float = { + border = 'rounded', + source = 'always', + header = '', + prefix = '', + }, +}) + +-- LSP Configuration + +local capabilities = vim.lsp.protocol.make_client_capabilities() +capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) + +require('neodev').setup({ + override = function(root_dir, library) + if root_dir:find("/home/kalle/.dots", 1, true) == 1 then + library.enabled = true + library.plugins = true + end + end, +}) + +require('lspconfig').lua_ls.setup { + on_attach = on_attach, + capabilities = capabilities, + root_dir = function() + return vim.loop.cwd() + end, + cmd = { "lua-language-server" }, + settings = { + Lua = { + workspace = { checkThirdParty = false }, + telemetry = { enable = false }, + }, + } +} + +require('lspconfig').rnix.setup { + on_attach = on_attach, + capabilities = capabilities, +} + +require('rust-tools').setup({ + server = { + on_attach = on_attach, + settings = { + ["rust-analyzer"] = { + checkOnSave = { + command = "clippy" + }, + }, + } + }, +}) diff --git a/nvim/plugin/treesitter.lua b/nvim/plugin/treesitter.lua new file mode 100644 index 0000000..2edb953 --- /dev/null +++ b/nvim/plugin/treesitter.lua @@ -0,0 +1,9 @@ +require('nvim-treesitter.configs').setup { + ensure_installed = {}, + + auto_install = false, + + highlight = { enable = true }, + + indent = { enable = true }, +} diff --git a/overlays/default.nix b/overlays/default.nix new file mode 100644 index 0000000..b4956f3 --- /dev/null +++ b/overlays/default.nix @@ -0,0 +1,20 @@ +{ + inputs, + ... +}: + +{ + nvim-plugins = final: prev: { + vimPlugins = prev.vimPlugins // { + rainbow-delimiters-nvim = prev.vimUtils.buildVimPlugin { + name = "raindow-delimiters.nvim"; + src = inputs.plugin-rainbow-delimiters-nvim; + }; + + undotree-nvim = prev.vimUtils.buildVimPlugin { + name = "undotree.nvim"; + src = inputs.plugin-undotree-nvim; + }; + }; + }; +}