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