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