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