diff --git a/flake.nix b/flake.nix index a0f8e30..ba74e54 100644 --- a/flake.nix +++ b/flake.nix @@ -250,8 +250,8 @@ system, }: { default = pkgs.mkShell { - buildInputs = with pkgs; [ - just + buildInputs = [ + pkgs.just self.packages.${system}.nvim ]; QEMU_OPTS_WL = "--enable-kvm -smp 4 -device virtio-gpu-rutabaga,gfxstream-vulkan=on,cross-domain=on,hostmem=2G,wsi=headless"; diff --git a/nvim/augroups.nix b/nvim/augroups.nix index 9c7a73f..50b857d 100644 --- a/nvim/augroups.nix +++ b/nvim/augroups.nix @@ -1,94 +1,87 @@ -{ - lib, - config, - helpers, - ... -}: let +{helpers, ...}: let inherit (helpers) mkRaw; - cfg = config.jhome.nvim; -in - lib.mkIf cfg.enable { - autoGroups = { - "highlightOnYank" = {}; - "lspConfig" = {}; - "restoreCursorPosition" = {}; - }; - autoCmd = [ - { - group = "highlightOnYank"; - event = "TextYankPost"; - pattern = "*"; - callback = mkRaw '' - function() - vim.highlight.on_yank { - higroup = ( - vim.fn['hlexists'] 'HighlightedyankRegion' > 0 and 'HighlightedyankRegion' or 'IncSearch' - ), - timeout = 200, - } +in { + autoGroups = { + "highlightOnYank" = {}; + "lspConfig" = {}; + "restoreCursorPosition" = {}; + }; + autoCmd = [ + { + group = "highlightOnYank"; + event = "TextYankPost"; + pattern = "*"; + callback = mkRaw '' + function() + vim.highlight.on_yank { + higroup = ( + vim.fn['hlexists'] 'HighlightedyankRegion' > 0 and 'HighlightedyankRegion' or 'IncSearch' + ), + timeout = 200, + } + end + ''; + } + { + group = "restoreCursorPosition"; + event = "BufReadPost"; + pattern = "*"; + callback = mkRaw '' + function() + if vim.fn.line '\'"' > 0 and vim.fn.line '\'"' <= vim.fn.line '$' then + vim.cmd [[execute "normal! g'\""]] + end + end + ''; + } + { + group = "lspConfig"; + event = "LspAttach"; + pattern = "*"; + callback = let + opts = "noremap = true, buffer = bufnr"; + in + mkRaw '' + function(opts) + local bufnr = opts.buf + local client = vim.lsp.get_client_by_id(opts.data.client_id) + local capabilities = client.server_capabilities + -- Set Omnifunc if supported + if capabilities.completionProvider then + vim.bo[bufnr].omnifunc = "v:lua.vim.lsp.omnifunc" + end + -- Enable inlay hints if supported + if capabilities.inlayHintProvider then + vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) + end + -- Some Lsp servers do not advertise inlay hints properly so enable this keybinding regardless + vim.keymap.set('n', 'ht', function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({bufnr = 0}), { bufnr = 0 }) + end, + { desc = '[H]ints [T]oggle', ${opts} } + ) + -- Enable hover if supported + if capabilities.hoverProvider then + vim.keymap.set('n', 'K', vim.lsp.buf.hover, { desc = 'Hover Documentation', ${opts} }) + end + -- Enable rename if supported + if capabilities.renameProvider then + vim.keymap.set('n', 'r', vim.lsp.buf.rename, { desc = '[R]ename', ${opts} }) + end + -- Enable code actions if supported + if capabilities.codeActionProvider then + vim.keymap.set({ 'n', 'v' }, 'fa', vim.lsp.buf.code_action, { desc = '[F]ind Code [A]ctions', ${opts} }) + end + -- Enable formatting if supported + if capabilities.documentFormattingProvider then + vim.keymap.set('n', 'w', function() require("conform").format({ lsp_fallback = true }) end, { desc = 'Format Buffer', ${opts} }) + end + -- Other keybinds + vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { desc = '[G]o to [D]efinition', ${opts} }) + vim.keymap.set('n', 'gt', vim.lsp.buf.type_definition, { desc = '[G]o to [T]ype Definition', ${opts} }) + vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, { desc = '[G]o to [I]mplementation', ${opts} }) end ''; - } - { - group = "restoreCursorPosition"; - event = "BufReadPost"; - pattern = "*"; - callback = mkRaw '' - function() - if vim.fn.line '\'"' > 0 and vim.fn.line '\'"' <= vim.fn.line '$' then - vim.cmd [[execute "normal! g'\""]] - end - end - ''; - } - { - group = "lspConfig"; - event = "LspAttach"; - pattern = "*"; - callback = let - opts = "noremap = true, buffer = bufnr"; - in - mkRaw '' - function(opts) - local bufnr = opts.buf - local client = vim.lsp.get_client_by_id(opts.data.client_id) - local capabilities = client.server_capabilities - -- Set Omnifunc if supported - if capabilities.completionProvider then - vim.bo[bufnr].omnifunc = "v:lua.vim.lsp.omnifunc" - end - -- Enable inlay hints if supported - if capabilities.inlayHintProvider then - vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) - end - -- Some Lsp servers do not advertise inlay hints properly so enable this keybinding regardless - vim.keymap.set('n', 'ht', function() - vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({bufnr = 0}), { bufnr = 0 }) - end, - { desc = '[H]ints [T]oggle', ${opts} } - ) - -- Enable hover if supported - if capabilities.hoverProvider then - vim.keymap.set('n', 'K', vim.lsp.buf.hover, { desc = 'Hover Documentation', ${opts} }) - end - -- Enable rename if supported - if capabilities.renameProvider then - vim.keymap.set('n', 'r', vim.lsp.buf.rename, { desc = '[R]ename', ${opts} }) - end - -- Enable code actions if supported - if capabilities.codeActionProvider then - vim.keymap.set({ 'n', 'v' }, 'fa', vim.lsp.buf.code_action, { desc = '[F]ind Code [A]ctions', ${opts} }) - end - -- Enable formatting if supported - if capabilities.documentFormattingProvider then - vim.keymap.set('n', 'w', function() require("conform").format({ lsp_fallback = true }) end, { desc = 'Format Buffer', ${opts} }) - end - -- Other keybinds - vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { desc = '[G]o to [D]efinition', ${opts} }) - vim.keymap.set('n', 'gt', vim.lsp.buf.type_definition, { desc = '[G]o to [T]ype Definition', ${opts} }) - vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, { desc = '[G]o to [I]mplementation', ${opts} }) - end - ''; - } - ]; - } + } + ]; +} diff --git a/nvim/default.nix b/nvim/default.nix index 0ee923e..0cefbb5 100644 --- a/nvim/default.nix +++ b/nvim/default.nix @@ -1,5 +1,14 @@ -{pkgs, ...} @ opts: { +{ + lib, + pkgs, + config, + helpers, + ... +}: let + # Force inputs to be included + nixvim = import ./nixvim.nix {inherit lib pkgs config helpers;}; +in { imports = [./options.nix]; - config.programs.nixvim = (import ./nixvim.nix opts).config; + config.programs.nixvim = nixvim.config; } diff --git a/nvim/mappings.nix b/nvim/mappings.nix index 84000c0..ed8e1bb 100644 --- a/nvim/mappings.nix +++ b/nvim/mappings.nix @@ -1,158 +1,148 @@ -{ - lib, - config, - helpers, - ... -}: let +{helpers, ...}: let inherit (helpers) mkRaw; - - cfg = config.jhome.nvim; -in - lib.mkIf cfg.enable { - keymaps = [ - # Quickfix - { - mode = "n"; - key = "qo"; - action = "Copen"; - options.desc = "Quickfix Open"; - } - { - mode = "n"; - key = "qq"; - action = "cclose"; - options.desc = "Quickfix Quit"; - } - { - mode = "n"; - key = "qj"; - action = "cnext"; - options.desc = "Quickfix next [J]"; - } - { - mode = "n"; - key = "qk"; - action = "cprev"; - options.desc = "Quickfix previous [K]"; - } - # Open or create file - { - mode = "n"; - key = "gf"; - action = "e "; - options.desc = "Go to File"; - } - # Keep Selection when indenting - { - mode = "x"; - key = ">"; - action = ">gv"; - options.desc = "Indent Selection"; - } - { - mode = "x"; - key = "<"; - action = ""] = function(fallback) - if cmp.visible() then - cmp.select_next_item() - elseif require("luasnip").expand_or_jumpable() then - require("luasnip").expand_or_jump() - elseif has_words_before() then - cmp.complete() - else - fallback() - end - end, - [""] = function(fallback) - if cmp.visible() then - cmp.select_prev_item() - elseif require("luasnip").jumpable(-1) then - require("luasnip").jump(-1) - else - fallback() - end - end, - [""] = cmp.mapping(function(fallback) - if require("luasnip").choice_active() then - require("luasnip").next_choice() - else - fallback() - end - end), - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.scroll_docs(4), - [""] = cmp.mapping.complete { }, - [""] = cmp.mapping.close(), - [""] = cmp.mapping.confirm { select = true }, - }) - ''; - }; - }; - # FIXME: doesn't include formatters - conform-nvim = { - enable = true; - formattersByFt = { - "_" = ["trim_whitespace"]; - c = ["clang_format"]; - cpp = ["clang_format"]; - lua = ["stylua"]; - nix = ["alejandra"]; - rust = ["rustfmt"]; - sh = ["shfmt"]; - toml = ["taplo"]; - yaml = ["yamlfmt"]; - zig = ["zigfmt"]; - }; - }; - gitsigns.enable = true; - lint = { - enable = true; - lintersByFt = { - rust = ["typos"]; - latex = ["chktex" "typos"]; - markdown = ["typos"]; - nix = ["statix"]; - sh = ["dash"]; - zsh = ["zsh"]; - }; - }; - lsp = { - enable = true; - servers = { - bashls.enable = true; - bashls.package = pkgs.unstable.bash-language-server; - # clangd.enable = true; # Adds ~2GiB - html.enable = true; - jsonls.enable = true; - marksman.enable = true; - nixd.enable = true; - nil-ls = { - enable = true; - settings.nix.flake = { - autoArchive = true; - autoEvalInputs = true; - }; - }; - ruff-lsp.enable = true; - taplo.enable = true; - # texlab.enable = true; # Not writing TeX rn - typos-lsp.enable = true; - typst-lsp.enable = true; - }; - }; - lspkind = { - enable = true; - mode = "symbol"; - extraOptions.maxwidth = 50; - }; - lualine = { - enable = true; - theme = lib.mkForce "gruvbox"; - }; - luasnip = { - enable = true; - extraConfig = { - update_events = "TextChanged,TextChangedI"; - }; - }; - noice = { - enable = true; - lsp.override = { - "vim.lsp.util.convert_input_to_markdown_lines" = true; - "vim.lsp.util.stylize_markdown" = true; - "cmp.entry.get_documentation" = true; - }; - presets = { - # use a classic bottom cmdline for search - bottom_search = true; - # position the cmdline and popupmenu together - command_palette = false; - # long messages will be sent to a split - long_message_to_split = true; - # enables an input dialog for inc-rename.nvim - inc_rename = false; - # add a border to hover docs and signature help - lsp_doc_border = true; - }; - }; - notify = { - enable = true; - backgroundColour = "#000000"; - }; - nvim-colorizer = { - enable = true; - userDefaultOptions = { - names = false; # disable named colors (i.e. red) - mode = "virtualtext"; - }; - }; - rustaceanvim = { - enable = true; - # Install through rustup - rustAnalyzerPackage = null; - }; - telescope = { - enable = true; - extensions = { - ui-select.enable = true; - fzy-native.enable = true; - }; - }; - treesitter = { - enable = true; - indent = true; - incrementalSelection.enable = true; - }; - trouble = { - enable = true; - settings.auto_close = true; + ":" = { + mapping = mkRaw "cmp.mapping.preset.cmdline()"; + sources = [ + {name = "path";} + {name = "cmdline";} + ]; }; }; - } + settings = { + # Snippets + snippet.expand = "function(args) require('luasnip').lsp_expand(args.body) end"; + # Completion Sources + sources = [ + { + name = "buffer"; + groupIndex = 3; + } + { + name = "calc"; + groupIndex = 2; + } + { + name = "conventionalcommits"; + groupIndex = 1; + } + { + name = "crates"; + groupIndex = 1; + } + { + name = "luasnip"; + groupIndex = 1; + } + { + name = "nvim_lsp"; + groupIndex = 1; + } + { + name = "nvim_lsp_document_symbol"; + groupIndex = 1; + } + { + name = "nvim_lsp_signature_help"; + groupIndex = 1; + } + { + name = "path"; + groupIndex = 2; + } + { + name = "spell"; + groupIndex = 2; + } + { + name = "treesitter"; + groupIndex = 2; + } + { + name = "zsh"; + groupIndex = 1; + } + ]; + mapping = mkRaw '' + cmp.mapping.preset.insert({ + [""] = function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif require("luasnip").expand_or_jumpable() then + require("luasnip").expand_or_jump() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, + [""] = function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif require("luasnip").jumpable(-1) then + require("luasnip").jump(-1) + else + fallback() + end + end, + [""] = cmp.mapping(function(fallback) + if require("luasnip").choice_active() then + require("luasnip").next_choice() + else + fallback() + end + end), + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete { }, + [""] = cmp.mapping.close(), + [""] = cmp.mapping.confirm { select = true }, + }) + ''; + }; + }; + # FIXME: doesn't include formatters + conform-nvim = { + enable = true; + formattersByFt = { + "_" = ["trim_whitespace"]; + c = ["clang_format"]; + cpp = ["clang_format"]; + lua = ["stylua"]; + nix = ["alejandra"]; + rust = ["rustfmt"]; + sh = ["shfmt"]; + toml = ["taplo"]; + yaml = ["yamlfmt"]; + zig = ["zigfmt"]; + }; + }; + gitsigns.enable = true; + lint = { + enable = true; + lintersByFt = { + rust = ["typos"]; + latex = ["chktex" "typos"]; + markdown = ["typos"]; + nix = ["statix"]; + sh = ["dash"]; + zsh = ["zsh"]; + }; + }; + lsp = { + enable = true; + servers = { + bashls.enable = true; + bashls.package = pkgs.unstable.bash-language-server; + # clangd.enable = true; # Adds ~2GiB + html.enable = true; + jsonls.enable = true; + marksman.enable = true; + nixd.enable = true; + nil-ls = { + enable = true; + settings.nix.flake = { + autoArchive = true; + autoEvalInputs = true; + }; + }; + ruff-lsp.enable = true; + taplo.enable = true; + # texlab.enable = true; # Not writing TeX rn + typos-lsp.enable = true; + typst-lsp.enable = true; + }; + }; + lspkind = { + enable = true; + mode = "symbol"; + extraOptions.maxwidth = 50; + }; + lualine = { + enable = true; + theme = lib.mkForce "gruvbox"; + }; + luasnip = { + enable = true; + extraConfig = { + update_events = "TextChanged,TextChangedI"; + }; + }; + noice = { + enable = true; + lsp.override = { + "vim.lsp.util.convert_input_to_markdown_lines" = true; + "vim.lsp.util.stylize_markdown" = true; + "cmp.entry.get_documentation" = true; + }; + presets = { + # use a classic bottom cmdline for search + bottom_search = true; + # position the cmdline and popupmenu together + command_palette = false; + # long messages will be sent to a split + long_message_to_split = true; + # enables an input dialog for inc-rename.nvim + inc_rename = false; + # add a border to hover docs and signature help + lsp_doc_border = true; + }; + }; + notify = { + enable = true; + backgroundColour = "#000000"; + }; + nvim-colorizer = { + enable = true; + userDefaultOptions = { + names = false; # disable named colors (i.e. red) + mode = "virtualtext"; + }; + }; + rustaceanvim = { + enable = true; + # Install through rustup + rustAnalyzerPackage = null; + }; + telescope = { + enable = true; + extensions = { + ui-select.enable = true; + fzy-native.enable = true; + }; + }; + treesitter = { + enable = true; + indent = true; + incrementalSelection.enable = true; + }; + trouble = { + enable = true; + settings.auto_close = true; + }; +}