Flake for my NixOS devices
at droid 939 lines 26 kB view raw
1{inputs, ...}: { 2 pkgs, 3 config, 4 lib, 5 ... 6}: { 7 imports = [inputs.nixvim.homeModules.nixvim]; 8 9 options.cow.neovim.enable = lib.mkEnableOption "Neovim + Nixvim + Customizations"; 10 11 config = lib.mkIf config.cow.neovim.enable { 12 cow.imperm.keep = [".local/share/nvim"]; 13 14 home.packages = with pkgs; [ 15 ripgrep 16 fd 17 ]; 18 19 home.sessionVariables.EDITOR = "nvim"; 20 21 programs.neovide = lib.mkIf config.cow.gdi.enable { 22 enable = true; 23 settings = { 24 fork = true; 25 font = { 26 normal = [{family = "monospace";}]; 27 size = 18.0; 28 }; 29 title-hidden = false; 30 }; 31 }; 32 33 programs.nixvim = { 34 enable = true; 35 enableMan = false; 36 defaultEditor = true; 37 viAlias = true; 38 vimAlias = true; 39 40 nixpkgs.pkgs = pkgs; 41 clipboard.providers.wl-copy.enable = config.cow.gdi.enable; 42 43 globals.mapleader = " "; 44 45 colorschemes.catppuccin = lib.mkIf config.cow.cat.enable { 46 enable = true; 47 settings = { 48 inherit (config.catppuccin) flavor; 49 no_underline = false; 50 no_bold = false; 51 no_italics = false; 52 term_colors = true; 53 # transparent_background = true; 54 integrations = { 55 alpha = true; 56 dropbar.enabled = true; 57 fidget = true; 58 markdown = true; 59 dap = true; 60 ufo = true; 61 rainbow_delimiters = true; 62 lsp_trouble = true; 63 which_key = true; 64 telescope.enabled = true; 65 treesitter = true; 66 lsp_saga = true; 67 illuminate = { 68 enabled = true; 69 lsp = true; 70 }; 71 neotree = true; 72 native_lsp = { 73 enabled = true; 74 inlay_hints = { 75 background = true; 76 }; 77 virtual_text = { 78 errors = ["italic"]; 79 hints = ["italic"]; 80 information = ["italic"]; 81 warnings = ["italic"]; 82 ok = ["italic"]; 83 }; 84 underlines = { 85 errors = ["underline"]; 86 hints = ["underline"]; 87 information = ["underline"]; 88 warnings = ["underline"]; 89 }; 90 }; 91 }; 92 }; 93 }; 94 95 extraConfigLua = '' 96 vim.diagnostic.config({ 97 signs = { 98 text = { 99 [vim.diagnostic.severity.ERROR] = "", 100 [vim.diagnostic.severity.WARN] = "", 101 }, 102 }, 103 }) 104 vim.g.neovide_cursor_vfx_mode = "pixiedust" 105 106 -- require("satellite").setup({}) 107 ''; 108 109 autoGroups = { 110 restore_cursor = {}; 111 open_neotree = {}; 112 }; 113 114 filetype.extension = { 115 mdx = "mdx"; 116 }; 117 118 opts = { 119 number = true; 120 relativenumber = true; 121 smartindent = true; 122 cursorline = true; 123 showtabline = 2; 124 tabstop = 2; 125 shiftwidth = 2; 126 breakindent = true; 127 fillchars.__raw = ''[[eob: ,fold: ,foldopen:,foldsep: ,foldclose:]]''; 128 foldcolumn = "1"; 129 foldlevel = 10; 130 foldlevelstart = 10; 131 foldenable = true; 132 mouse = ""; 133 }; 134 135 autoCmd = [ 136 { 137 group = "restore_cursor"; 138 event = ["BufReadPost"]; 139 pattern = "*"; 140 callback.__raw = '' 141 function() 142 if 143 vim.fn.line "'\"" > 1 144 and vim.fn.line "'\"" <= vim.fn.line "$" 145 and vim.bo.filetype ~= "commit" 146 and vim.fn.index({ "xxd", "gitrebase" }, vim.bo.filetype) == -1 147 then 148 vim.cmd "normal! g`\"" 149 end 150 end 151 ''; 152 } 153 { 154 group = "open_neotree"; 155 event = ["BufRead"]; 156 pattern = "*"; 157 once = true; 158 callback.__raw = '' 159 function() 160 if 161 vim.bo.filetype ~= "alpha" 162 and (not vim.g.neotree_opened) 163 then 164 vim.cmd "Neotree show" 165 vim.g.neotree_opened = true 166 end 167 end 168 ''; 169 } 170 ]; 171 172 performance = { 173 byteCompileLua = { 174 enable = true; 175 nvimRuntime = true; 176 plugins = true; 177 }; 178 combinePlugins = { 179 enable = true; 180 }; 181 }; 182 183 keymaps = let 184 prefixMap = pre: maps: 185 builtins.map (k: { 186 action = "<cmd>${k.action}<cr>"; 187 key = "${pre}${k.key}"; 188 options = k.options; 189 }) 190 maps; 191 in 192 lib.lists.flatten ( 193 builtins.map (g: 194 if builtins.hasAttr "group" g 195 then prefixMap g.prefix g.keys 196 else g) [ 197 { 198 action = ''"+p''; 199 key = "<C-S-V>"; 200 options.desc = "Paste from system clipboard"; 201 } 202 { 203 action = ''"+y''; 204 key = "<C-S-C>"; 205 options.desc = "Copy to system clipboard"; 206 } 207 { 208 action = ''"+x''; 209 key = "<C-S-X>"; 210 options.desc = "Cut to system clipboard"; 211 } 212 { 213 action = ''<cmd>Format<cr>''; 214 key = "<C-S-I>"; 215 options.desc = "Format Buffer"; 216 } 217 { 218 group = "Tab Navigation"; 219 prefix = "<Tab>"; 220 keys = [ 221 { 222 action = "BufferLineCycleNext"; 223 key = "e"; 224 options.desc = "Next Tab"; 225 } 226 { 227 action = "BufferLineCyclePrev"; 228 key = "q"; 229 options.desc = "Previous Tab"; 230 } 231 { 232 action = "Neotree toggle"; 233 key = "t"; 234 options.desc = "Toggle Neotree"; 235 } 236 ]; 237 } 238 { 239 group = "Tab Closing"; 240 prefix = "<Tab><Tab>"; 241 keys = [ 242 { 243 action = "BufferLineCloseLeft"; 244 key = "q"; 245 options.desc = "Close Tab Left"; 246 } 247 { 248 action = "BufferLineCloseRight"; 249 key = "e"; 250 options.desc = "Close Tab Right"; 251 } 252 { 253 action = "BufferLinePickClose"; 254 key = "<Tab>"; 255 options.desc = "Pick Tab and Close"; 256 } 257 { 258 action = "BufferLineCloseOthers"; 259 key = "w"; 260 options.desc = "Close Other Tabs"; 261 } 262 ]; 263 } 264 { 265 action = "<cmd>Bdelete<cr>"; 266 key = "<C-q>"; 267 options.desc = "Close Current Buffer"; 268 } 269 { 270 group = "LSP Actions"; 271 prefix = "<C-.>"; 272 keys = [ 273 { 274 action = "Lspsaga code_action code_action"; 275 key = "a"; 276 options.desc = "Code Actions"; 277 } 278 { 279 action = "Lspsaga rename"; 280 key = "r"; 281 options.desc = "LSP Rename"; 282 } 283 { 284 action = "Lspsaga diagnostic_jump_next"; 285 key = "e"; 286 options.desc = "Next Diagnostic"; 287 } 288 { 289 action = "Lspsaga diagnostic_jump_previous"; 290 key = "E"; 291 options.desc = "Previous Diagnostic"; 292 } 293 { 294 action = "Lspsaga goto_definition"; 295 key = "d"; 296 options.desc = "Jump to Definition"; 297 } 298 { 299 action = "Lspsaga peek_definition"; 300 key = "D"; 301 options.desc = "Peek Definition"; 302 } 303 { 304 action = "Lspsaga finder ref"; 305 key = "fr"; 306 options.desc = "Find References"; 307 } 308 { 309 action = "Lspsaga finder imp"; 310 key = "fi"; 311 options.desc = "Find Implementations"; 312 } 313 { 314 action = "Lspsaga finder def"; 315 key = "fd"; 316 options.desc = "Find Definitions"; 317 } 318 { 319 action = "Lspsaga finder"; 320 key = "ff"; 321 options.desc = "Finder"; 322 } 323 { 324 action = "Lspsaga hover_doc"; 325 key = "h"; 326 options.desc = "Hover Doc"; 327 } 328 ]; 329 } 330 { 331 action = "<cmd>Telescope<cr>"; 332 key = "<leader><leader>"; 333 options.desc = "Telescope Launch"; 334 } 335 { 336 action.__raw = "[[<C-\\><C-n><C-w>]]"; 337 mode = ["t"]; 338 key = "<C-w>"; 339 } 340 { 341 action.__raw = "[[<C-\\><C-n>]]"; 342 mode = ["t"]; 343 key = "<esc>"; 344 } 345 { 346 action = "<cmd>WhichKey<cr>"; 347 key = "<C-/>"; 348 } 349 ] 350 ); 351 352 extraPlugins = with pkgs.vimPlugins; 353 (lib.optional config.cow.dev.web {plugin = pkgs.nvim-mdx;}) 354 ++ [ 355 {plugin = satellite-nvim;} 356 {plugin = flatten-nvim;} 357 {plugin = tiny-devicons-auto-colors-nvim;} 358 ]; 359 360 plugins = { 361 telescope = { 362 enable = true; 363 settings.defaults = { 364 layout_config.prompt_position = "top"; 365 }; 366 extensions = { 367 file-browser.enable = true; 368 ui-select.enable = true; 369 undo.enable = true; 370 }; 371 keymaps = lib.fix (self: { 372 "<leader>u" = { 373 action = "undo"; 374 options.desc = "Undo Tree"; 375 }; 376 "<leader>c" = { 377 action = "commands"; 378 options.desc = "Browse Commands"; 379 }; 380 "<leader>w" = { 381 action = "spell_suggest"; 382 options.desc = "Spell Suggest"; 383 }; 384 "<leader>s" = { 385 action = "lsp_document_symbols"; 386 options.desc = "LSP Symbols"; 387 }; 388 "<leader>t" = { 389 action = "treesitter"; 390 options.desc = "Treesitter Symbols"; 391 }; 392 "<leader>f" = { 393 action = "find_files"; 394 options.desc = "Files"; 395 }; 396 "<leader>gs" = { 397 action = "git_status"; 398 options.desc = "Git Status"; 399 }; 400 "<leader>gb" = { 401 action = "git_branches"; 402 options.desc = "Git Branches"; 403 }; 404 "<leader>gc" = { 405 action = "git_commits"; 406 options.desc = "Git Commits"; 407 }; 408 "<leader>r" = { 409 action = "oldfiles"; 410 options.desc = "Recent Files"; 411 }; 412 "<leader>l" = self."<C-S-F>"; 413 "<C-S-F>" = { 414 action = "live_grep"; 415 options.desc = "Live Grep"; 416 }; 417 }); 418 }; 419 420 alpha = { 421 enable = true; 422 settings.opts = { 423 position = "center"; 424 }; 425 settings.layout = let 426 o = { 427 position = "center"; 428 }; 429 txt = s: { 430 type = "text"; 431 val = s; 432 opts = 433 { 434 hl = "Keyword"; 435 } 436 // o; 437 }; 438 grp = g: { 439 type = "group"; 440 val = g; 441 opts.spacing = 1; 442 }; 443 btn = { 444 val, 445 onClick, 446 ... 447 }: { 448 type = "button"; 449 inherit val; 450 opts = o; 451 on_press.__raw = "function() vim.cmd[[${onClick}]] end"; 452 }; 453 cmd = { 454 command, 455 width, 456 height, 457 }: { 458 type = "terminal"; 459 inherit command width height; 460 opts = o; 461 }; 462 pad = { 463 type = "padding"; 464 val = 2; 465 }; 466 in 467 [ 468 pad 469 pad 470 ] 471 ++ (lib.intersperse pad [ 472 (cmd { 473 command = '' 474 ${pkgs.toilet}/bin/toilet " NIXVIM " -f mono12 -F border | ${pkgs.lolcat}/bin/lolcat -f 475 ''; 476 # Hardcoding to prevent IFD 477 width = 83; # (builtins.stringLength (lib.trim (builtins.elemAt (lib.splitString "\n" bannerText) 1))) - 3; 478 height = 12; # (builtins.length (lib.splitString "\n" bannerText)) - 1; 479 }) 480 (grp [ 481 (btn { 482 val = " Terminal"; 483 onClick = "ToggleTerm"; 484 }) 485 (btn { 486 val = "󰅙 Quit"; 487 onClick = "q"; 488 }) 489 ]) 490 (grp [ 491 (txt " Neovim Version ${pkgs.neovim.version}") 492 (txt " NixVim Rev ${builtins.substring 0 5 inputs.nixvim.rev}") 493 ]) 494 ]) 495 ++ [pad]; 496 }; 497 498 trouble = { 499 enable = true; 500 }; 501 502 toggleterm = { 503 enable = true; 504 luaConfig.post = '' 505 local flatten = require('flatten') 506 507 ---@type Terminal? 508 local saved_terminal 509 510 flatten.setup({ 511 hooks = { 512 should_block = function(argv) 513 return vim.tbl_contains(argv, "-b") 514 end, 515 pre_open = function() 516 local term = require("toggleterm.terminal") 517 local termid = term.get_focused_id() 518 saved_terminal = term.get(termid) 519 end, 520 post_open = function(opts) 521 if saved_terminal then 522 saved_terminal:close() 523 else 524 vim.api.nvim_set_current_win(opts.winnr) 525 end 526 527 if opts.filetype == "gitcommit" or opts.filetype == "gitrebase" then 528 vim.api.nvim_create_autocmd("BufWritePost", { 529 buffer = opts.bufnr, 530 once = true, 531 callback = vim.schedule_wrap(function() 532 require('bufdelete').bufdelete(opts.bufnr, true) 533 end), 534 }) 535 end 536 end, 537 block_end = function() 538 vim.schedule(function() 539 if saved_terminal then 540 saved_terminal:open() 541 saved_terminal = nil 542 end 543 end) 544 end, 545 }, 546 window = { 547 open = "alternate", 548 }, 549 }) 550 ''; 551 settings = { 552 size = 20; 553 open_mapping = "[[<C-x>]]"; 554 direction = "horizontal"; 555 start_in_insert = true; 556 insert_mappings = true; 557 terminal_mappings = true; 558 }; 559 }; 560 561 treesitter = { 562 enable = true; 563 luaConfig.post = lib.mkIf config.cow.dev.web '' 564 require('mdx').setup() 565 ''; 566 settings = { 567 highlight.enable = true; 568 }; 569 }; 570 571 illuminate.enable = true; 572 cursorline.enable = true; 573 574 # neocord = { 575 # enable = true; 576 # settings.logo = "https://raw.githubusercontent.com/IogaMaster/neovim/main/.github/assets/nixvim-dark.webp"; 577 # }; 578 579 bufdelete.enable = true; 580 581 bufferline = { 582 enable = true; 583 settings.highlights.__raw = '' 584 require("catppuccin.special.bufferline").get_theme() 585 ''; 586 settings.options = { 587 indicator.style = "none"; 588 show_buffer_close_icons = false; 589 show_close_icon = false; 590 offsets = [ 591 { 592 filetype = "neo-tree"; 593 highlight = "String"; 594 text = " Neovim"; 595 text_align = "center"; 596 # separator = true; 597 } 598 ]; 599 separator_style = "slant"; 600 close_command.__raw = ''require('bufdelete').bufdelete''; 601 hover = { 602 enabled = true; 603 delay = 150; 604 reveal = ["close"]; 605 }; 606 sort_by = "insert_at_end"; 607 diagnostics = "nvim_lsp"; 608 diagnostics_indicator.__raw = '' 609 function(count, level, diagnostics_dict, context) 610 local icon = level:match("error") and " " or " " 611 return " " .. icon .. count 612 end 613 ''; 614 }; 615 }; 616 617 statuscol = { 618 enable = true; 619 settings.segments = let 620 dispCond = { 621 __raw = '' 622 function(ln) 623 return vim.bo.filetype ~= "neo-tree" 624 end 625 ''; 626 }; 627 in [ 628 { 629 click = "v:lua.ScSa"; 630 condition = [ 631 dispCond 632 ]; 633 text = [ 634 "%s" 635 ]; 636 } 637 { 638 click = "v:lua.ScLa"; 639 condition = [dispCond]; 640 text = [ 641 { 642 __raw = "require('statuscol.builtin').lnumfunc"; 643 } 644 ]; 645 } 646 { 647 click = "v:lua.ScFa"; 648 condition = [ 649 dispCond 650 { 651 __raw = "require('statuscol.builtin').not_empty"; 652 } 653 ]; 654 text = [ 655 { 656 __raw = "require('statuscol.builtin').foldfunc"; 657 } 658 " " 659 ]; 660 } 661 ]; 662 }; 663 664 dropbar = { 665 enable = true; 666 settings = { 667 bar.padding.right = 5; 668 bar.padding.left = 1; 669 }; 670 }; 671 672 nvim-ufo = { 673 enable = true; 674 }; 675 676 # gitgutter = { 677 # enable = true; 678 # settings = { 679 # 680 # }; 681 # }; 682 683 # TODO: Broken in nixpkgs rn, hash mismatch, #464773 684 lualine = { 685 enable = true; 686 settings = { 687 extensions = [ 688 "trouble" 689 "toggleterm" 690 ]; 691 692 options = { 693 theme = "catppuccin"; 694 disabled_filetypes = ["neo-tree"]; 695 ignore_focus = ["neo-tree"]; 696 }; 697 }; 698 }; 699 700 nix-develop = { 701 enable = true; 702 package = pkgs.vimPlugins.nix-develop-nvim.overrideAttrs ( 703 prev: next: { 704 src = pkgs.fetchFromGitHub { 705 owner = "Bwc9876"; 706 repo = "nix-develop.nvim"; 707 rev = "089cd52191ccbb3726594e21cd96567af6088dd5"; 708 sha256 = "sha256-EIEJk8/IAuG+UICUJ2F8QakgRpFrQ1ezDSJ79NAVuD8="; 709 }; 710 } 711 ); 712 }; 713 714 neo-tree = { 715 enable = true; 716 settings = { 717 hide_root_node = false; 718 add_blank_line_at_top = true; 719 default_component_configs = { 720 container.right_padding = 2; 721 name.trailing_slash = true; 722 indent = { 723 indent_size = 2; 724 with_expanders = true; 725 }; 726 }; 727 window.width = 40; 728 auto_clean_after_session_restore = true; 729 close_if_last_window = true; 730 filesystem.components.name.__raw = '' 731 function(config, node, state) 732 local components = require('neo-tree.sources.common.components') 733 local name = components.name(config, node, state) 734 if node:get_depth() == 1 then 735 name.text = vim.fs.basename(vim.loop.cwd() or "") .. "/" 736 end 737 return name 738 end 739 ''; 740 }; 741 }; 742 743 image = { 744 luaConfig = { 745 pre = "if not vim.g.neovide then"; 746 post = "end"; 747 }; 748 enable = true; 749 }; 750 web-devicons.enable = true; 751 752 indent-o-matic.enable = true; 753 intellitab.enable = true; 754 755 which-key = { 756 enable = true; 757 settings = { 758 show_help = true; 759 preset = "modern"; 760 win.wo.winblend = 8; 761 }; 762 }; 763 764 fidget = { 765 enable = true; 766 settings.notification = { 767 override_vim_notify = true; 768 window = { 769 y_padding = 2; 770 x_padding = 2; 771 zindex = 50; 772 align = "top"; 773 winblend = 0; 774 }; 775 }; 776 }; 777 778 # none-ls = { 779 # enable = true; 780 # sources.formatting = { 781 # prettier = { 782 # enable = true; 783 # disableTsServerFormatter = true; 784 # }; 785 # yamlfmt.enable = true; 786 # typstyle.enable = true; 787 # markdownlint.enable = true; 788 # }; 789 # sources.diagnostics = { 790 # markdownlint.enable = true; 791 # }; 792 # }; 793 794 cmp = { 795 enable = true; 796 settings = { 797 sources = map (name: {inherit name;}) [ 798 "nvim_lsp" 799 "nvim_lsp_signature_help" 800 "path" 801 "buffer" 802 ]; 803 mapping = { 804 "<Esc>" = "cmp.mapping.abort()"; 805 "<Tab>" = "cmp.mapping.confirm({ select = true })"; 806 "<Up>" = "cmp.mapping(cmp.mapping.select_prev_item(), {'i', 's'})"; 807 "<Down>" = "cmp.mapping(cmp.mapping.select_next_item(), {'i', 's'})"; 808 }; 809 }; 810 }; 811 812 cmp-nvim-lsp.enable = true; 813 cmp-nvim-lsp-document-symbol.enable = true; 814 cmp-spell.enable = true; 815 816 rainbow-delimiters.enable = true; 817 preview.enable = true; 818 819 # jupytext.enable = true; 820 821 # Broken 822 # hex = { 823 # enable = true; 824 # settings = { 825 # assemble_cmd = "xxd -r"; 826 # dump_cmd = "xxd -g 1 -u"; 827 # }; 828 # }; 829 830 conform-nvim = { 831 enable = true; 832 settings.default_format_opts = { 833 lsp_format = "prefer"; 834 }; 835 # Taken from https://github.com/stevearc/conform.nvim/blob/master/doc/recipes.md#format-command 836 luaConfig.post = '' 837 vim.api.nvim_create_user_command("Format", function(args) 838 local range = nil 839 if args.count ~= -1 then 840 local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1] 841 range = { 842 start = { args.line1, 0 }, 843 ["end"] = { args.line2, end_line:len() }, 844 } 845 end 846 require("conform").format({ async = true, lsp_format = "fallback", range = range }) 847 end, { range = true }) 848 ''; 849 }; 850 851 lspconfig.enable = true; 852 853 lspsaga = { 854 enable = true; 855 settings = { 856 symbol_in_winbar.enable = false; 857 implement.enable = false; 858 lightbulb.enable = false; 859 ui = { 860 code_action = "󰛨"; 861 actionfix = "󰖷"; 862 }; 863 hover = { 864 openCmd = "!xdg-open"; 865 openLink = "<leader>o"; 866 maxWidth = 0.5; 867 maxHeight = 0.4; 868 }; 869 rename.autoSave = true; 870 finder = { 871 keys.close = "<ESC>"; 872 }; 873 codeAction.keys.quit = "<ESC>"; 874 }; 875 }; 876 877 crates.enable = true; 878 879 numbertoggle.enable = true; 880 881 # rustaceanvim.enable = true; 882 vim-css-color.enable = true; 883 }; 884 885 lsp = { 886 inlayHints.enable = true; 887 888 servers = let 889 inherit 890 (config.cow.dev) 891 dotnet 892 python 893 haskell 894 rust 895 web 896 c 897 ; 898 in { 899 clangd.enable = c; 900 astro.enable = web; 901 hls = lib.mkIf haskell { 902 enable = true; 903 # ghcPackage = pkgs.haskell.compiler.ghc912; 904 package = pkgs.haskell.packages.ghc912.haskell-language-server; 905 }; 906 sqls.enable = web; 907 mdx_analyzer = lib.mkIf web { 908 enable = true; 909 package = pkgs.mdx-language-server; 910 }; 911 # denols.enable = true; 912 ts_ls.enable = web; 913 html.enable = web; 914 marksman.enable = web; 915 cssls.enable = web; 916 tailwindcss.enable = web; 917 jsonls.enable = web; 918 yamlls.enable = web; 919 ruff.enable = python; 920 csharp_ls.enable = dotnet; 921 svelte.enable = web; 922 nil_ls.enable = true; 923 bashls.enable = true; 924 nushell.enable = config.cow.nushell.enable; 925 taplo.enable = rust; 926 typos_lsp.enable = true; 927 rust_analyzer = lib.mkIf rust { 928 enable = true; 929 package = pkgs.rust-analyzer-nightly; 930 packageFallback = true; 931 }; 932 lemminx.enable = web; 933 eslint.enable = web; 934 just.enable = true; 935 }; 936 }; 937 }; 938 }; 939}