1{ 2 pkgs, 3 config, 4 lib, 5 ... 6}: 7 8let 9 ltex-ls-nvim = pkgs.vimUtils.buildVimPlugin { 10 pname = "ltex-ls.nvim"; 11 version = "2.6.0"; 12 src = pkgs.fetchFromGitHub { 13 owner = "vigoux"; 14 repo = "ltex-ls.nvim"; 15 rev = "c8139ea6b7f3d71adcff121e16ee8726037ffebd"; 16 sha256 = "sha256-jY3ALr6h88xnWN2QdKe3R0vvRcSNhFWDW56b2NvnTCs="; 17 }; 18 }; 19 cmp-spell = pkgs.vimUtils.buildVimPlugin { 20 pname = "cmp-spell"; 21 version = "2024-05-07"; 22 src = pkgs.fetchFromGitHub { 23 owner = "f3fora"; 24 repo = "cmp-spell"; 25 rev = "694a4e50809d6d645c1ea29015dad0c293f019d6"; 26 sha256 = "Gf7HSocvHmTleVQytNYmmN+fFX7kl5sYHQSpUJc0CGI="; 27 }; 28 meta.homepage = "https://github.com/f3fora/cmp-spell/"; 29 }; 30 vim-ledger-2024-07-15 = pkgs.vimUtils.buildVimPlugin { 31 pname = "vim-ledger"; 32 version = "2024-07-15"; 33 src = pkgs.fetchFromGitHub { 34 owner = "ledger"; 35 repo = "vim-ledger"; 36 rev = "dbc683e24bd5338b8c12540227a58b2d247e097a"; 37 sha256 = "sha256-y2f0s0aAieXtj4mSnJdH7UxQlMqJqABNVPoGLlLc57A="; 38 }; 39 meta.homepage = "https://github.com/ledger/vim-ledger/"; 40 }; 41 calendar-nvim = pkgs.vimUtils.buildVimPlugin { 42 pname = "calendar-nvim"; 43 version = "2024-07-23"; 44 src = pkgs.fetchFromGitHub { 45 owner = "RyanGibb"; 46 repo = "calendar.nvim"; 47 rev = "e1ebd87eb953a91de5cba2c6eff04b127c6a894b"; 48 sha256 = "sha256-0iiW6dAvdS5UDbjJvXWKTDqvo/4yoFkYfDind+RuTmE="; 49 }; 50 meta.homepage = "https://github.com/RyanGibb/calendar.nvim/"; 51 }; 52 cfg = config.custom; 53in 54{ 55 options.custom.nvim-lsps = lib.mkEnableOption "nvim-lsps"; 56 57 config = { 58 xdg.configFile = { 59 "ftplugin/mail.vim".text = '' 60 setlocal tw=72 61 set formatoptions+=w 62 ''; 63 }; 64 programs.neovim = { 65 enable = true; 66 viAlias = true; 67 vimAlias = true; 68 extraPackages = 69 with pkgs; 70 [ 71 ripgrep 72 nixd 73 ] 74 ++ lib.lists.optionals cfg.nvim-lsps [ 75 nixfmt-rfc-style 76 # stop complaining when launching but a devshell is better 77 ocamlPackages.ocaml-lsp 78 ocamlPackages.ocamlformat 79 lua-language-server 80 pyright 81 black 82 ltex-ls 83 jdt-language-server 84 nodejs_18 85 clang-tools 86 typst-lsp 87 ]; 88 extraLuaConfig = builtins.readFile ./init.lua; 89 # undo transparent background 90 # + "colorscheme gruvbox"; 91 plugins = 92 with pkgs.vimPlugins; 93 [ 94 { 95 plugin = gruvbox-nvim; 96 type = "lua"; 97 # TODO is there a better place to put this? 98 runtime = 99 let 100 ml-style = '' 101 setlocal expandtab 102 setlocal shiftwidth=2 103 setlocal tabstop=2 104 setlocal softtabstop=2 105 ''; 106 in 107 { 108 "ftplugin/nix.vim".text = ml-style; 109 "ftplugin/ocaml.vim".text = ml-style; 110 "ftplugin/ledger.vim".text = '' 111 setlocal foldmethod=syntax 112 ''; 113 }; 114 } 115 116 { 117 plugin = telescope-nvim; 118 type = "lua"; 119 config = builtins.readFile ./telescope-nvim.lua; 120 } 121 telescope-fzf-native-nvim 122 telescope-undo-nvim 123 telescope-file-browser-nvim 124 125 { 126 plugin = trouble-nvim; 127 type = "lua"; 128 config = '' 129 require('trouble').setup { 130 icons = false, 131 } 132 vim.keymap.set('n', '<leader>xx', function() require('trouble').toggle() end, { desc = 'Trouble toggle' }) 133 vim.keymap.set('n', '<leader>xw', function() require('trouble').toggle('workspace_diagnostics') end, { desc = 'Trouble workspace' }) 134 vim.keymap.set('n', '<leader>xd', function() require('trouble').toggle('document_diagnostics') end, { desc = 'Trouble document' }) 135 vim.keymap.set('n', '<leader>xq', function() require('trouble').toggle('quickfix') end, { desc = 'Trouble quickfix' }) 136 vim.keymap.set('n', '<leader>xl', function() require('trouble').toggle('loclist') end, { desc = 'Trouble loclist' }) 137 vim.keymap.set('n', '<leader>xr', function() require('trouble').toggle('lsp_references') end, { desc = 'Trouble LSP references' }) 138 ''; 139 } 140 { 141 plugin = gitsigns-nvim; 142 type = "lua"; 143 config = '' 144 require('gitsigns').setup{ 145 on_attach = function(bufnr) 146 local gitsigns = require('gitsigns') 147 148 local function map(mode, l, r, opts) 149 opts = opts or {} 150 opts.buffer = bufnr 151 vim.keymap.set(mode, l, r, opts) 152 end 153 154 map('n', ']c', function() 155 if vim.wo.diff then 156 vim.cmd.normal({']c', bang = true}) 157 else 158 gitsigns.nav_hunk('next') 159 end 160 end, { desc = 'Git next hunk' }) 161 162 map('n', '[c', function() 163 if vim.wo.diff then 164 vim.cmd.normal({'[c', bang = true}) 165 else 166 gitsigns.nav_hunk('prev') 167 end 168 end, { desc = 'Git prev hunk' }) 169 170 map('n', '<leader>gs', gitsigns.stage_hunk, { desc = 'Git stage hunk' }) 171 map('n', '<leader>gr', gitsigns.reset_hunk, { desc = 'Git reset hunk' }) 172 map('v', '<leader>gs', function() gitsigns.stage_hunk {vim.fn.line('.'), vim.fn.line('v')} end, { desc = 'Git stage hunk' }) 173 map('v', '<leader>gr', function() gitsigns.reset_hunk {vim.fn.line('.'), vim.fn.line('v')} end, { desc = 'Git reset hunk' }) 174 map('n', '<leader>gS', gitsigns.stage_buffer, { desc = 'Git stage buffer' }) 175 map('n', '<leader>gu', gitsigns.undo_stage_hunk, { desc = 'Git unstage hunk' }) 176 map('n', '<leader>gR', gitsigns.reset_buffer, { desc = 'Git reset buffer' }) 177 map('n', '<leader>gp', gitsigns.preview_hunk, { desc = 'Git preview hunk' }) 178 map('n', '<leader>gb', function() gitsigns.blame_line{full=true} end, { desc = 'Git blame' }) 179 map('n', '<leader>gtb', gitsigns.toggle_current_line_blame, { desc = 'Git toggle line blame' }) 180 map('n', '<leader>gd', gitsigns.diffthis, { desc = 'Git diff index' }) 181 map('n', '<leader>gD', function() gitsigns.diffthis('~') end, { desc = 'Git diff last' }) 182 map('n', '<leader>gtd', gitsigns.toggle_deleted, { desc = 'Git toggle deleted' }) 183 184 -- vih 185 map({'o', 'x'}, 'ih', ':<C-U>Git select_hunk<CR>', { desc = 'Gitsigns select hunk' }) 186 end 187 } 188 ''; 189 } 190 { 191 plugin = pkgs.overlay-unstable.vimPlugins.neogit; 192 type = "lua"; 193 config = '' 194 local neogit = require('neogit') 195 neogit.setup {} 196 ''; 197 } 198 199 plenary-nvim 200 pkgs.ripgrep 201 202 { 203 plugin = nvim-cmp; 204 type = "lua"; 205 config = builtins.readFile ./nvim-cmp.lua; 206 } 207 cmp-path 208 cmp-buffer 209 cmp-cmdline 210 cmp-spell 211 { 212 plugin = cmp-dictionary; 213 type = "lua"; 214 config = '' 215 require("cmp_dictionary").setup({ 216 paths = { "${pkgs.scowl}/share/dict/words.txt" }, 217 exact_length = 2, 218 first_case_insensitive = true, 219 }) 220 ''; 221 } 222 223 { 224 plugin = luasnip; 225 type = "lua"; 226 config = builtins.readFile ./luasnip.lua; 227 } 228 cmp_luasnip 229 pkgs.overlay-unstable.vimPlugins.friendly-snippets 230 231 { 232 plugin = nvim-treesitter.withAllGrammars; 233 type = "lua"; 234 config = '' 235 require'nvim-treesitter.configs'.setup { 236 highlight = { 237 enable = true, 238 -- :h vimtex-faq-treesitter 239 disable = { "latex" }, 240 }, 241 } 242 vim.opt.foldmethod = "expr" 243 vim.opt.foldexpr = "v:lua.vim.treesitter.foldexpr()" 244 vim.opt.foldenable = false 245 ''; 246 } 247 { 248 plugin = nvim-treesitter-textobjects; 249 type = "lua"; 250 config = '' 251 require'nvim-treesitter.configs'.setup { 252 textobjects = { 253 select = { 254 enable = true, 255 lookahead = true, 256 keymaps = { 257 ["af"] = "@function.outer", 258 ["if"] = "@function.inner", 259 ["ac"] = "@conditional.outer", 260 ["ic"] = "@conditional.inner", 261 ["al"] = "@loop.outer", 262 ["il"] = "@loop.inner", 263 }, 264 include_surrounding_whitespace = true, 265 }, 266 swap = { 267 enable = true, 268 swap_next = { 269 ["<leader>a"] = "@parameter.inner", 270 }, 271 swap_previous = { 272 ["<leader>A"] = "@parameter.inner", 273 }, 274 }, 275 move = { 276 enable = true, 277 set_jumps = true, 278 goto_next_start = { 279 ["]m"] = "@function.outer", 280 }, 281 goto_next_end = { 282 ["]M"] = "@function.outer", 283 }, 284 goto_previous_start = { 285 ["[m"] = "@function.outer", 286 }, 287 goto_previous_end = { 288 ["[M"] = "@function.outer", 289 }, 290 }, 291 }, 292 } 293 -- could use some tweaking 294 vim.treesitter.query.set("ocaml", "textobjects", [[ 295 ((value_definition (let_binding)) @function.outer) 296 ((let_binding body: (_) @function.inner)) 297 ]]) 298 ''; 299 } 300 301 { 302 plugin = vimtex; 303 type = "lua"; 304 config = '' 305 vim.cmd("filetype plugin indent on") 306 vim.cmd("syntax enable") 307 vim.g.vimtex_quickfix_mode = 0 308 vim.g.vimtex_view_general_viewer = 'evince' 309 ''; 310 } 311 { 312 plugin = sved; 313 type = "lua"; 314 config = '' 315 vim.keymap.set('n', '<leader>lv', ':call SVED_Sync()<CR>') 316 ''; 317 } 318 cmp-omni 319 320 { 321 plugin = nvim-surround; 322 type = "lua"; 323 config = '' 324 require('nvim-surround').setup({}) 325 ''; 326 } 327 { 328 plugin = comment-nvim; 329 type = "lua"; 330 config = '' 331 require('Comment').setup() 332 ''; 333 } 334 { 335 plugin = undotree; 336 type = "lua"; 337 config = '' 338 vim.keymap.set('n', '<leader>u', vim.cmd.UndotreeToggle, { desc = 'Undotree toggle' }) 339 ''; 340 } 341 { 342 plugin = leap-nvim; 343 type = "lua"; 344 config = '' 345 vim.keymap.set({'n', 'x', 'o'}, 's', '<Plug>(leap-forward)', { desc = "Leap forward"} ) 346 vim.keymap.set({'n', 'x', 'o'}, 'S', '<Plug>(leap-backward)', { desc = "Leap backward"} ) 347 vim.keymap.set({'n', 'x', 'o'}, 'gs', '<Plug>(leap-from-window)', { desc = "Leap from window"} ) 348 ''; 349 } 350 { 351 plugin = pkgs.overlay-unstable.vimPlugins.which-key-nvim; 352 type = "lua"; 353 config = '' 354 local wk = require('which-key') 355 wk.setup({ 356 plugins = { 357 spelling = { 358 enabled = false 359 }, 360 }, 361 icons = { mappings = false }, 362 triggers = { 363 { "<leader>", mode = { "n", "v" } }, 364 { "<auto>", mode = "nixsotc" }, 365 }, 366 delay = 1000, 367 }) 368 wk.add({ 369 { "<leader>f", group = 'Find' }, 370 { "<leader>l", group = 'LSP' }, 371 { "<leader>;", group = 'DAP' }, 372 { "<leader>s", group = 'Session' }, 373 { "<leader>t", group = 'Tab' }, 374 { "<leader>h", group = 'Hunk' }, 375 { "<leader>x", group = 'Trouble' }, 376 { "<leader>g", group = 'Git' }, 377 { "<leader>i", group = 'Insert' }, 378 }) 379 ''; 380 } 381 382 { 383 plugin = pkgs.notmuch; 384 runtime = 385 let 386 notmuch-style = '' 387 let g:notmuch_date_format = '%Y-%m-%d' 388 let g:notmuch_datetime_format = '%Y-%m-%d %I:%M%p' 389 ''; 390 in 391 { 392 "ftplugin/notmuch-folders.vim".text = notmuch-style; 393 "ftplugin/notmuch-search.vim".text = notmuch-style; 394 "ftplugin/notmuch-show.vim".text = notmuch-style; 395 "ftplugin/notmuch-compose.vim".text = notmuch-style; 396 }; 397 } 398 399 { 400 plugin = vim-ledger-2024-07-15; 401 type = "lua"; 402 config = '' 403 vim.g.ledger_fuzzy_account_completion = true 404 vim.g.ledger_extra_options = '--pedantic' 405 vim.g.ledger_align_at = 50 406 vim.g.ledger_accounts_cmd = 'ledger accounts --add-budget' 407 408 vim.g.ledger_date_format = '%Y-%m-%d' 409 410 vim.cmd([[ 411 autocmd FileType ledger nnoremap <buffer> <leader>e :call ledger#entry()<CR> 412 ]]) 413 ''; 414 } 415 { 416 plugin = obsidian-nvim; 417 type = "lua"; 418 config = builtins.readFile ./obsidian.lua; 419 } 420 421 { 422 plugin = calendar-nvim; 423 type = "lua"; 424 config = '' 425 require('calendar') 426 ''; 427 } 428 ] 429 ++ lib.lists.optionals cfg.nvim-lsps [ 430 { 431 plugin = nvim-lspconfig; 432 type = "lua"; 433 config = builtins.readFile ./lsp.lua; 434 runtime = { 435 "ftplugin/java.lua".text = '' 436 local project_name = vim.fn.fnamemodify(vim.fn.getcwd(), ':p:h:t') 437 local workspace_dir = '~/.cache/jdt/' .. project_name 438 require('jdtls').start_or_attach { 439 on_attach = On_attach, 440 capabilities = Capabilities, 441 cmd = { 'jdt-language-server', '-data', workspace_dir, }, 442 root_dir = vim.fs.dirname(vim.fs.find({'gradlew', '.git', 'mvnw'}, { upward = true })[1]), 443 } 444 ''; 445 }; 446 } 447 { 448 plugin = nvim-dap; 449 type = "lua"; 450 config = builtins.readFile ./dap.lua; 451 } 452 cmp-nvim-lsp 453 cmp-nvim-lsp-signature-help 454 ltex-ls-nvim 455 nvim-jdtls 456 ]; 457 }; 458 }; 459}