{ config, lib, pkgs, inputs, ... }: let cfg = config.modules.editor.vim; in { options.modules.editor.vim = { enable = lib.my.mkBoolOpt false; }; config = lib.mkIf cfg.enable { home-manager.users.${config.user.name} = { imports = [ inputs.nixvim.homeManagerModules.nixvim ]; programs.neovim = { enable = true; package = pkgs.neovim-unwrapped; vimAlias = true; vimdiffAlias = true; withNodeJs = true; plugins = ( with pkgs.vimPlugins; [ # base distro LazyVim conform-nvim nvim-lint markdown-preview-nvim render-markdown-nvim # theme gruvbox-nvim # UI bufferline-nvim gitsigns-nvim neogit diffview-nvim edgy-nvim dashboard-nvim toggleterm-nvim trouble-nvim lualine-nvim which-key-nvim nvim-web-devicons mini-nvim mini-ai mini-comment mini-icons mini-pairs noice-nvim nui-nvim nvim-notify nvim-lsp-notify neo-tree-nvim nvim-navic dressing-nvim aerial-nvim snacks-nvim # project management project-nvim neoconf-nvim persistence-nvim # smart typing indent-blankline-nvim guess-indent-nvim vim-illuminate # LSP nvim-lspconfig nvim-lightbulb # lightbulb for quick actions # nvim-code-action-menu # code action menu neodev-nvim SchemaStore-nvim # load known formats for json and yaml nvim-metals # cmp plugins nvim-cmp # completion plugin cmp-buffer # buffer completions cmp-path # path completions cmp_luasnip # snipper completions cmp-nvim-lsp # LSP completions # snippets luasnip # snippet engine nvim-snippets friendly-snippets # a bunch of snippets to use # search functionality plenary-nvim telescope-nvim telescope-fzf-native-nvim grug-far-nvim flash-nvim # treesitter nvim-treesitter-context nvim-ts-autotag nvim-treesitter-textobjects nvim-treesitter.withAllGrammars # comments ts-comments-nvim nvim-ts-context-commentstring todo-comments-nvim # leap vim-repeat leap-nvim flit-nvim # DAP nvim-dap nvim-dap-ui nvim-dap-virtual-text one-small-step-for-vimkind # neotest neotest neotest-rust # SQL vim-dadbod vim-dadbod-ui vim-dadbod-completion lazy-nvim lazydev-nvim vim-startuptime yazi-nvim ] ); extraPackages = with pkgs; [ gcc # needed for nvim-treesitter # HTML, CSS, JSON vscode-langservers-extracted # Nix nixd statix nixfmt-rfc-style # SQL sqlfluff # LazyVim defaults stylua shfmt # Markdown extra markdownlint-cli2 marksman # Docker extra nodePackages.dockerfile-language-server-nodejs hadolint docker-compose-language-service # JSON and YAML extras nodePackages.yaml-language-server # Custom editorconfig-checker shellcheck ]; extraLuaConfig = # lua '' require("gruvbox").setup({ overrides = { Include = { ["link"] = "GruvboxRed" }, ["@constructor"] = { ["link"] = "GruvboxYellow" }, ["@function.builtin"] = { ["link"] = "GruvboxFg1" }, ["@function.call"] = { ["link"] = "GruvboxFg1" }, ["@function.macro"] = { ["link"] = "GruvboxFg1" }, ["@function.method.call.scala"] = { ["link"] = "GruvboxFg1" }, ["@method.call"] = { ["link"] = "GruvboxFg1" }, ["@variable.member.scala"] = { ["link"] = "GruvboxFg1" }, ["@lsp.type.type.scala"] = { ["link"] = "" }, ["@lsp.type.method.scala"] = { ["link"] = "" }, ["@lsp.type.modifier.scala"] = { ["link"] = "GruvboxOrange" }, ["@lsp.type.typeParameter.scala"] = { ["link"] = "GruvboxAqua" }, ["@lsp.type.type.nix"] = { ["link"] = "" }, ["@lsp.type.method.nix"] = { ["link"] = "" }, ["@lsp.type.macro.nix"] = { ["link"] = "" }, ["@lsp.type.interface.nix"] = { ["link"] = "" }, }, }) require("lazy").setup({ spec = { { "LazyVim/LazyVim", import = "lazyvim.plugins" }, -- import any extras modules here { import = "lazyvim.plugins.extras.dap.core" }, { import = "lazyvim.plugins.extras.dap.nlua" }, { import = "lazyvim.plugins.extras.ui.edgy" }, { import = "lazyvim.plugins.extras.coding.mini-comment" }, { import = "lazyvim.plugins.extras.editor.aerial" }, { import = "lazyvim.plugins.extras.editor.leap" }, { import = "lazyvim.plugins.extras.editor.navic" }, { import = "lazyvim.plugins.extras.lang.docker" }, { import = "lazyvim.plugins.extras.lang.json" }, { import = "lazyvim.plugins.extras.lang.markdown" }, { import = "lazyvim.plugins.extras.lang.sql" }, { import = "lazyvim.plugins.extras.lang.yaml" }, { import = "lazyvim.plugins.extras.lang.scala" }, { import = "lazyvim.plugins.extras.test.core" }, -- import/override with your plugins { import = "plugins" }, }, defaults = { -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup. -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default. lazy = false, -- It's recommended to leave version=false for now, since a lot the plugin that support versioning, -- have outdated releases, which may break your Neovim install. version = false, -- always use the latest git commit -- version = "*", -- try installing the latest stable version for plugins that support semver }, performance = { -- Used for NixOS reset_packpath = false, rtp = { reset = false, -- disable some rtp plugins disabled_plugins = { "gzip", -- "matchit", -- "matchparen", -- "netrwPlugin", "tarPlugin", "tohtml", "tutor", "zipPlugin", }, } }, dev = { path = "${ pkgs.vimUtils.packDir config.home-manager.users.${config.user.name}.programs.neovim.finalPackage.passthru.packpathDirs }/pack/myNeovimPackages/start", patterns = {"folke", "nvim-telescope", "hrsh7th", "akinsho", "stevearc", "LazyVim", "catppuccin", "saadparwaiz1", "nvimdev", "rafamadriz", "lewis6991", "lukas-reineke", "nvim-lualine", "L3MON4D3", "williamboman", "echasnovski", "nvim-neo-tree", "MunifTanjim", "mfussenegger", "rcarriga", "neovim", "nvim-pack", "nvim-treesitter", "windwp", "JoosepAlviste", "nvim-tree", "nvim-lua", "RRethy", "dstein64", "Saecki", "ggandor", "iamcco", "nvim-neotest", "rouge8", "theHamsta", "SmiteshP", "jbyuki", "simrat39", "b0o", "tpope", "kosayoda", "ellisonleao", "NeogitOrg", "sindrets", "scalameta", "garymjr", "mikavilpas","kristijanhusak","MagicDuck","MeanderingProgrammer"}, }, install = { missing = false, }, }) ''; }; xdg.configFile."nvim/lua" = { recursive = true; source = ./lua; }; programs.nixvim = { enable = false; package = pkgs.neovim-unwrapped; vimAlias = true; keymaps = [ # Search { key = "cx"; action = "Telescope diagnostics layout_strategy=vertical"; options.desc = "Search diagnostics"; } # Project { key = "ps"; action = "wa"; options.desc = "Save all buffers"; } ]; plugins = { lazy = { enable = true; plugins = [ { pkg = pkgs.vimPlugins.gitsigns-nvim; opts.__raw = # lua '' { on_attach = function(buffer) local gs = package.loaded.gitsigns local function map(mode, l ,r, desc) vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc}) end map("n", "g;", function() if vim.wo.diff then vim.cmd.normal({ "]c", bang = true }) else gs.nav_hunk("next") end end, "Next Hunk") map("n", "g,", function() if vim.wo.diff then vim.cmd.normal({ "[c", bang = true }) else gs.nav_hunk("prev") end end, "Prev Hunk") map({ "n", "v" }, "gs", gs.stage_hunk, "Stage Hunk") map({ "n", "v" }, "gr", gs.reset_hunk, "Reset Hunk") map("n", "gS", gs.stage_buffer, "Stage Buffer") map("n", "gu", gs.undo_stage_hunk, "Undo Stage Hunk") map("n", "gR", gs.reset_buffer, "Reset Buffer") map("n", "gp", gs.preview_hunk_inline, "Preview Hunk Inline") map("n", "gb", function() gs.blame_line({ full = true }) end, "Blame Line") map("n", "gd", gs.diffthis, "Diff This") map("n", "gD", function() gs.diffthis("~") end, "Diff This ~") map('n', 'tb', gs.toggle_current_line_blame, "Toggle current line blame") map({ "o", "x" }, "ih", ":Gitsigns select_hunk", "GitSigns Select Hunk") end, } ''; } { pkg = pkgs.vimPlugins.which-key-nvim; event = "VimEnter"; config = # lua '' function () require('which-key').setup() require('which-key').register { ['b'] = { name = 'Buffer', _ = 'which_key_ignore' }, ['c'] = { name = 'Code', _ = 'which_key_ignore' }, ['d'] = { name = 'Document', _ = 'which_key_ignore' }, ['f'] = { name = 'File', _ = 'which_key_ignore' }, ['g'] = { name = 'Git', _ = 'which_key_ignore' }, ['o'] = { name = 'Org', _ = 'which_key_ignore' }, ['n'] = { name = 'Org-roam', _ = 'which_key_ignore' }, ['p'] = { name = 'Project', _ = 'which_key_ignore' }, ['r'] = { name = 'Rename', _ = 'which_key_ignore' }, ['s'] = { name = 'Search', _ = 'which_key_ignore' }, ['w'] = { name = 'Window', _ = 'which_key_ignore' }, ['t'] = { name = 'Toggle', _ = 'which_key_ignore' }, ['q'] = { name = 'Quit/Session', _ = 'which_key_ignore' }, } end ''; } { pkg = pkgs.vimPlugins.nvim-lspconfig; config = # lua '' function () vim.api.nvim_create_autocmd('LspAttach', { group = vim.api.nvim_create_augroup('lsp-attach', { clear = true }), callback = function(event) local map = function(keys, func, desc) vim.keymap.set('n', keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) end map('gd', require('telescope.builtin').lsp_definitions, 'Go to definition') map('gr', require('telescope.builtin').lsp_references, 'Go to references') map('gI', require('telescope.builtin').lsp_implementations, 'Goto implementation') map('gD', vim.lsp.buf.declaration, 'Go to declaration') map('gT', require('telescope.builtin').lsp_type_definitions, 'Type definition') map('cD', require('telescope.builtin').lsp_document_symbols, 'Document symbols') map('cw', require('telescope.builtin').lsp_dynamic_workspace_symbols, 'Workspace symbols ') map('cd', vim.diagnostic.open_float, 'Line diagnostics') map('c,', vim.diagnostic.goto_prev, 'Previous diagnostics') map('c;', vim.diagnostic.goto_next, 'Next diagnostics') map('cr', vim.lsp.buf.rename, 'Rename') map('ca', vim.lsp.buf.code_action, 'Code action') map('K', vim.lsp.buf.hover, 'Hover Documentation') end }) local has_cmp, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") local capabilities = vim.tbl_deep_extend( "force", {}, vim.lsp.protocol.make_client_capabilities(), has_cmp and cmp_nvim_lsp.default_capabilities() or {} ) local function setup(server, server_opts) local server_opts_with_caps = vim.tbl_deep_extend("force", { capabilities = vim.deepcopy(capabilities), }, server_opts) require("lspconfig")[server].setup(server_opts_with_caps) end setup("yamlls", {}) setup("typos_lsp", { init_options = { diagnosticSeverity = "Hint" } }) setup("tsserver", {}) setup("terraformls", {}) setup("marksman", {}) setup("lua_ls", {}) setup("jsonls", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-json-language-server", "--stdio" } }) setup("html", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-html-language-server", "--stdio" } }) setup("eslint", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-eslint-language-server", "--stdio" } }) setup("dockerls", { cmd = { "${pkgs.dockerfile-language-server-nodejs}/bin/docker-langserver", "--stdio" } }) setup("docker_compose_language_service", {}) setup("cssls", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-css-language-server", "--stdio" } }) setup("bashls", {}) setup("ansiblels", { cmd = { "${pkgs.ansible-language-server}/bin/ansible-language-server", "--stdio" } }) end ''; } { pkg = pkgs.vimPlugins.nvim-cmp; event = "InsertEnter"; dependencies = [ pkgs.vimPlugins.cmp-nvim-lsp pkgs.vimPlugins.cmp-path pkgs.vimPlugins.cmp-buffer ]; opts.__raw = # lua '' function() local cmp = require("cmp") return { mapping = { [""] = cmp.mapping.complete(), [""] = cmp.mapping.scroll_docs(-4), [""] = cmp.mapping.close(), [""] = cmp.mapping.scroll_docs(4), [""] = cmp.mapping.confirm({ select = true }), [""] = cmp.mapping.confirm({ select = true }), [""] = cmp.mapping(cmp.mapping.select_prev_item(), { "i", "s" }), [""] = cmp.mapping(cmp.mapping.select_next_item(), { "i", "s" }), }, sources = { { name = "nvim_lsp" }, { name = "path" }, { name = "buffer" }, { name = "orgmode" }, }, } end ''; } # Disabled for now as it tries to write org grammar to its own directory in the nix store # https://github.com/nvim-orgmode/orgmode/blob/95fb795a422f0455e03d13a3f83525f1d00793ad/lua/orgmode/utils/treesitter/install.lua#L9 # { # pkg = pkgs.vimPlugins.orgmode; # event = "VeryLazy"; # ft = [ "org" ]; # config = /*lua*/ '' # function () # require('orgmode').setup({ # org_agend_files = '~/Nextcloud/Org/**/*', # org_default_notes_file = '~/Nextcloud/Org/refile.org', # }) # end # ''; # } # { # pkg = (pkgs.vimUtils.buildVimPlugin { # name = "org-roam.nvim"; # src = inputs.vim-org-roam; # }); # dependencies = [ pkgs.vimPlugins.orgmode ]; # event = "VeryLazy"; # ft = [ "org" ]; # config = /*lua*/ '' # function () # require('org-roam').setup({ # directory = '~/Nextcloud/OrgRoam', # }) # end # ''; # } ]; }; }; }; home.packages = with pkgs; [ ripgrep fd nodejs opentofu coursier # LSP yaml-language-server typos-lsp nodePackages.typescript-language-server terraform-ls sqls nixd marksman lua-language-server docker-compose-language-service bash-language-server ]; }; }; }