diff --git a/modules/neovim/default.nix b/modules/neovim/default.nix index 80bd3a1..734dd03 100644 --- a/modules/neovim/default.nix +++ b/modules/neovim/default.nix @@ -6,8 +6,9 @@ }: { imports = [ - ./options.nix ./formatter.nix + ./keybind.nix + ./options.nix ]; # based on default options from upstream: # https://github.com/NotAShelf/nvf/blob/main/configuration.nix @@ -18,6 +19,10 @@ # override level 999 is used to not conflict with mkDefault as used by nvf. # which allows user configurations to disable/override anything here. config.vim = lib.mkOverride 999 { + extraLuaFiles = [ + ./lib.lua + ]; + theme = { enable = true; }; @@ -60,8 +65,8 @@ listReferences = "gr"; goToType = "gy"; hover = "K"; - nextDiagnostic = "d"; - openDiagnosticFloat = "df"; + nextDiagnostic = null; # ]d + openDiagnosticFloat = "d"; renameSymbol = "rn"; documentHighlight = null; listDocumentSymbols = null; @@ -78,11 +83,9 @@ enable = true; addDefaultGrammars = true; }; - debugger = { - nvim-dap = { - enable = true; - ui.enable = true; - }; + debugger.nvim-dap = { + enable = true; + ui.enable = true; }; languages = { enableFormat = true; @@ -96,36 +99,58 @@ clang.enable = true; css.enable = true; html.enable = true; + lua.enable = true; markdown.enable = true; + nix.enable = true; python.enable = true; rust.crates.enable = true; rust.enable = true; ts.enable = true; zig.enable = true; - lua.enable = true; # sort-lines: off - - nix = { - enable = true; - format.type = "nixfmt"; # looks so much nicer + }; + filetree.neo-tree = { + enable = true; + setupOpts = { + enable_cursor_hijack = true; + git_status_async = true; }; }; - filetree = { - neo-tree = { - enable = false; + fzf-lua = { + enable = true; + setupOpts = { + fzf_colors = true; }; }; - tabline = { - nvimBufferline.enable = true; - }; - autocomplete = { - blink-cmp = { - enable = true; - sourcePlugins = { - ripgrep.enable = true; + autocomplete.blink-cmp = { + enable = true; + mappings = { + close = null; + complete = null; + confirm = null; + next = null; + previous = null; + scrollDocsDown = null; + scrollDocsUp = null; + }; + setupOpts = { + keymap = { + preset = "super-tab"; }; - friendly-snippets.enable = true; + completion = { + ghost_text.enabled = false; + list.selection.preselect = true; + trigger = { + show_in_snippet = true; + }; + accept.auto_brackets.enabled = true; + }; + signature.enabled = true; }; + sourcePlugins = { + ripgrep.enable = true; + }; + friendly-snippets.enable = true; }; statusline = { lualine = { @@ -137,71 +162,6 @@ }; }; }; - - utility = { - snacks-nvim = { - enable = true; - setupOpts = { - bigfile.enable = true; - dashboard = { - preset.keys = [ - { - icon = " "; - key = "n"; - desc = "New File"; - action = ":ene | startinsert"; - } - { - icon = " "; - key = "r"; - desc = "Recent Files"; - action = ":lua Snacks.dashboard.pick('oldfiles')"; - } - ]; - sections = [ - { section = "header"; } - { - section = "keys"; - indent = 2; - padding = 1; - } - { - icon = " "; - title = "Projects"; - section = "projects"; - indent = 2; - padding = 1; - } - { - icon = " "; - title = "Git"; - section = "terminal"; - enabled = lib.options.literalExpression '' - function() - return Snacks.git.get_root() ~= nil - end - ''; - cmd = "git status --short --branch --renames"; - height = 10; - padding = 1; - ttl = 5 * 60; - indent = 3; - } - ]; - }; - image = { - enable = true; - math.enabled = false; - }; - notifier.timeout = 3000; - picker = { - enable = true; - sources = { - }; - }; - }; - }; - }; binds = { whichKey.enable = true; cheatsheet.enable = true; diff --git a/modules/neovim/keybind.nix b/modules/neovim/keybind.nix new file mode 100644 index 0000000..f5b2d0f --- /dev/null +++ b/modules/neovim/keybind.nix @@ -0,0 +1,83 @@ +# this file implements a keybind system, which is a higher level system +# to configure vim.keymaps (note the different name bind vs map) +{ + pkgs, + lib, + config, + ... +}: +let + keyRemap = mode: key: action: { inherit mode key action; }; + keyCmd = + mode: key: cmd: + keyRemap mode key ":${cmd}"; +in +{ + # default binds + config.vim.keybinds = { + search-commands = keyCmd "n" "?" "FzfLua keymaps"; + + # user interface + toggle-explorer = keyCmd "n" "e" "Neotree toggle"; + reveal-active-file = keyCmd "n" "E" "Neotree reveal:Neotree focus"; + lazygit = keyCmd "n" "gg" "FullscreenTerm ${pkgs.lazygit}/bin/lazygit"; + + # pickers + pick-file = keyCmd "n" "" "FzfLua files"; + pick-mark = keyCmd "n" "'" "FzfLua marks"; + #pick-buffer = keyCmd "n" "b" "FzfLua buffers"; + pick-grep = keyCmd "n" "ff" "FzfLua grep_project"; + pick-recent-command = keyCmd "n" "fc" "FzfLua command_history"; + pick-other = keyCmd "n" "f?" "FzfLua builtin"; # picker of Fzf pickers + + # lsp + code-action = + keyCmd "n" "ca" + "FzfLua lsp_code_actions winopts.height=15 winopts.backdrop=100 winopts.title=false winopts.preview.title=false winopts.row=1"; + + # subtle nice features + visual-dedent = keyRemap "v" "<" "" ">gv"; # keep selection + clear-search-highlights = keyRemap "n" ""; + }; + + # implementation + options.vim.keybinds = lib.mkOption { + type = lib.types.attrsOf ( + lib.types.nullOr ( + lib.types.submodule { + options = { + mode = lib.mkOption { type = lib.types.str; }; + key = lib.mkOption { type = lib.types.str; }; + action = lib.mkOption { type = lib.types.str; }; + }; + } + ) + ); + default = { }; + }; + config.vim.keymaps = + let + titleCase = + str: + lib.concatStringsSep " " ( + map ( + word: + lib.strings.toUpper (builtins.substring 0 1 word) + + builtins.substring 1 (builtins.stringLength word) word + ) (lib.splitString "-" str) + ); + in + builtins.filter (f: f != null) ( + lib.attrsets.mapAttrsToList ( + desc: bind: + if bind != null then + { + desc = titleCase desc; + inherit (bind) mode key action; + } + else + null + ) config.vim.keybinds + ); +} diff --git a/modules/neovim/lib.lua b/modules/neovim/lib.lua new file mode 100644 index 0000000..4daeb6b --- /dev/null +++ b/modules/neovim/lib.lua @@ -0,0 +1,27 @@ +-- Ported from https://www.reddit.com/r/neovim/comments/vemydn +vim.api.nvim_create_user_command("FullscreenTerm", function(opts) + vim.cmd("tab terminal " .. opts.args) + local laststatus = vim.o.laststatus + local showtabline = vim.o.showtabline + local cmdheight = vim.o.cmdheight + vim.o.laststatus = 0 + vim.o.cmdheight = 0 + vim.o.showtabline = 0 + vim.wo.signcolumn = "no" + vim.wo.relativenumber = false + vim.wo.number = false + vim.cmd( + "autocmd! TermClose " + .. "if !v:event.status" + .. " | exec 'bd! '..expand('')" + .. " | endif" + .. " | checktime" + .. " | set laststatus=" + .. laststatus + .. " | set cmdheight=" + .. cmdheight + .. " | set showtabline=" + .. showtabline + ) + vim.cmd("startinsert") +end, { nargs = "*" })