From 21fcace3ed9d0ee5fb9077248115241996fe322e Mon Sep 17 00:00:00 2001 From: Ching Pei Yang <59727193+horriblename@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:50:50 +0100 Subject: [PATCH] treewide: implement lazy loading via lz.n for selected plugins (#407) * flake: add lz.n and lzn-auto-require * lazy: init module * lzn-auto-require: add init lua code * wrapper: fix opt plugin format * lib.binds: add lz.n variant of bind functions * telescope: lazy load * nvim-tree: lazy load * dapui: lazy load * trouble: lazy load * toggleterm: lazy load * cheatsheet: lazy load * diffview: lazy load * icon-picker: lazy load * leap: lazy load * fidget: lazy load * docs: add section on lazy plugins * lazy: support lazy.enable=false * comment-nvim: lazy load * surround-nvim: lazy load * neo-tree: lazy load * fixup! lazy: init module * dap: appease the nix gods (fix statix lint) * flake.lock: fix merge mistake * doc: update release note * fixup! doc: update release note * neo-tree: fix duplicate neo-tree install * lazy: use attrsOf for lazy.plugins * treewide: update lazy.plugins syntax * docs: update lazy.plugins syntax * lazy: cleanup * Update docs/manual/hacking/additional-plugins.md Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com> * formatting nitpick Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com> * typo tee hee :3 Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com> * typo tee hee :4 Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com> * flake: update lz.n * lazy: update lz.n plugin spec * lazy: allow lines in place of str for lua code * copilot: lazy load * cmp: lazy load this moves cmp itself to lazy.plugins but other plugins that call cmp are not yet lazy so cmp is technically not yet lazy * luasnip: lazy load * flake: add rtp.nvim * cmp: actually lazy load source * fixup! cmp: actually lazy load source * format * docs: fix broken link * cmp-nvim-lsp: lazy load * lazy: allow key mode of str type * cmp: install sourcess via cmp.sourcePlugins * Update docs/manual/hacking/additional-plugins.md Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com> * lazy: refactor common var * nvim-dap-ui: add setupOpts * refactor: re-order plugin and lz.n configs lazy: make lzn-auto-require togglable * docs: update dag-entries * trouble: remove redundant import * lazy: remove unused module arg * toggleterm: make lazygit keybind optional * toggleterm: use toLuaObject for clarity * surround: rework keymap config * remove stale FIXME * lsp: use cmp_nvim_lsp capabilities * cmp: deduplicate attr key * theme: ensure themes load before lazy plugins * doc: update description of `theme` dag entry * lsp: avoid loading cmp on startup * doc: update configuration docs on custom plugins * cmp: skip trigger_load if lazy disabled * treesitter: remove redundant code * lsp: mark hack as HACK * comment: remove redundant plugin * Squash merge v0.7 into feature/lzn --------- Co-authored-by: raf Co-authored-by: diniamo <55629891+diniamo@users.noreply.github.com> --- docs/manual/configuring/custom-plugins.md | 5 +- .../configuring/custom-plugins/configuring.md | 36 ++- .../configuring/custom-plugins/lazy-method.md | 40 +++ .../{old-method.md => legacy-method.md} | 2 +- .../{new-method.md => non-lazy-method.md} | 2 +- docs/manual/configuring/dag-entries.md | 14 +- docs/manual/hacking/additional-plugins.md | 58 +++++ docs/release-notes/rl-0.7.md | 4 + flake.lock | 52 ++++ flake.nix | 16 ++ lib/binds.nix | 24 ++ modules/default.nix | 5 +- modules/modules.nix | 1 + modules/plugins/assistant/copilot/config.nix | 116 ++++----- .../comments/comment-nvim/comment-nvim.nix | 8 + .../plugins/comments/comment-nvim/config.nix | 62 ++--- .../plugins/completion/nvim-cmp/config.nix | 163 +++++++----- .../plugins/completion/nvim-cmp/nvim-cmp.nix | 10 +- modules/plugins/debugger/nvim-dap/config.nix | 31 ++- .../plugins/debugger/nvim-dap/nvim-dap.nix | 4 + modules/plugins/filetree/neo-tree/config.nix | 16 +- modules/plugins/filetree/nvimtree/config.nix | 132 +++++----- modules/plugins/lsp/config.nix | 63 ++++- modules/plugins/lsp/trouble/config.nix | 37 ++- modules/plugins/lsp/trouble/trouble.nix | 3 + modules/plugins/snippets/luasnip/config.nix | 15 +- .../plugins/terminal/toggleterm/config.nix | 54 ++-- modules/plugins/theme/theme.nix | 2 +- modules/plugins/treesitter/config.nix | 11 +- .../utility/binds/cheatsheet/config.nix | 13 +- modules/plugins/utility/diffview/config.nix | 13 +- modules/plugins/utility/diffview/diffview.nix | 2 + .../plugins/utility/icon-picker/config.nix | 20 +- .../plugins/utility/motion/leap/config.nix | 110 ++++---- modules/plugins/utility/surround/config.nix | 47 +++- modules/plugins/utility/surround/surround.nix | 49 +++- modules/plugins/utility/telescope/config.nix | 118 ++++----- modules/plugins/visuals/fidget/config.nix | 13 +- modules/wrapper/lazy/config.nix | 108 ++++++++ modules/wrapper/lazy/default.nix | 6 + modules/wrapper/lazy/lazy.nix | 237 ++++++++++++++++++ modules/wrapper/rc/config.nix | 5 +- 42 files changed, 1226 insertions(+), 501 deletions(-) create mode 100644 docs/manual/configuring/custom-plugins/lazy-method.md rename docs/manual/configuring/custom-plugins/{old-method.md => legacy-method.md} (96%) rename docs/manual/configuring/custom-plugins/{new-method.md => non-lazy-method.md} (93%) create mode 100644 modules/wrapper/lazy/config.nix create mode 100644 modules/wrapper/lazy/default.nix create mode 100644 modules/wrapper/lazy/lazy.nix diff --git a/docs/manual/configuring/custom-plugins.md b/docs/manual/configuring/custom-plugins.md index c58c4973..76b32ea4 100644 --- a/docs/manual/configuring/custom-plugins.md +++ b/docs/manual/configuring/custom-plugins.md @@ -20,6 +20,7 @@ custom plugins that you might have added to your configuration. ```{=include=} sections custom-plugins/configuring.md -custom-plugins/new-method.md -custom-plugins/old-method.md +custom-plugins/lazy-method.md +custom-plugins/non-lazy-method.md +custom-plugins/legacy-method.md ``` diff --git a/docs/manual/configuring/custom-plugins/configuring.md b/docs/manual/configuring/custom-plugins/configuring.md index 5e837ce1..71ce9b8f 100644 --- a/docs/manual/configuring/custom-plugins/configuring.md +++ b/docs/manual/configuring/custom-plugins/configuring.md @@ -1,12 +1,32 @@ # Configuring {#sec-configuring-plugins} -Just making the plugin to your Neovim configuration available might not always -be enough. In that case, you can write custom lua config using either -`config.vim.extraPlugins` (which has the `setup` field) or -`config.vim.luaConfigRC`. The first option uses an attribute set, which maps DAG -section names to a custom type, which has the fields `package`, `after`, -`setup`. They allow you to set the package of the plugin, the sections its setup -code should be after (note that the `extraPlugins` option has its own DAG +Just making the plugin to your Neovim configuration available might not always be enough. In that +case, you can write custom lua config using either `config.vim.lazy.plugins.*.setupOpts` +`config.vim.extraPlugins.*.setup` or `config.vim.luaConfigRC`. + +The first option uses an extended version of `lz.n`'s PluginSpec. `setupModule` and `setupOpt` can +be used if the plugin uses a `require('module').setup(...)` pattern. Otherwise, the `before` and +`after` hooks should do what you need. + +```nix +{ + config.vim.lazy.plugins = { + aerial-nvim = { + # ^^^^^^^^^ this name should match the package.pname or package.name + package = aerial-nvim; + + setupModule = "aerial"; + setupOpts = {option_name = false;}; + + after = "print('aerial loaded')"; + }; + }; +} +``` + +The second option uses an attribute set, which maps DAG section names to a custom type, which has +the fields `package`, `after`, `setup`. They allow you to set the package of the plugin, the +sections its setup code should be after (note that the `extraPlugins` option has its own DAG scope), and the its setup code respectively. For example: ```nix @@ -24,7 +44,7 @@ config.vim.extraPlugins = with pkgs.vimPlugins; { } ``` -The second option also uses an attribute set, but this one is resolved as a DAG +The third option also uses an attribute set, but this one is resolved as a DAG directly. The attribute names denote the section names, and the values lua code. For example: diff --git a/docs/manual/configuring/custom-plugins/lazy-method.md b/docs/manual/configuring/custom-plugins/lazy-method.md new file mode 100644 index 00000000..77b77d5d --- /dev/null +++ b/docs/manual/configuring/custom-plugins/lazy-method.md @@ -0,0 +1,40 @@ +# Lazy Method {#sec-lazy-method} + +As of version **0.7**, we exposed an API for configuring lazy-loaded plugins via +`lz.n` and `lzn-auto-require`. + +```nix +{ + config.vim.lazy.plugins = { + aerial = { + package = pkgs.vimPlugins.aerial-nvim; + setupModule = aerial; + setupOpts = { + option_name = true; + }; + after = '' + -- custom lua code to run after plugin is loaded + print('aerial loaded') + ''; + + # Explicitly mark plugin as lazy. You don't need this if you define one of + # the trigger "events" below + lazy = true; + + # load on command + cmd = ["AerialOpen"]; + + # load on event + event = ["BufEnter"]; + + # load on keymap + keys = [ + { + key = "a"; + action = ":AerialToggle"; + } + ]; + }; + }; +} +``` diff --git a/docs/manual/configuring/custom-plugins/old-method.md b/docs/manual/configuring/custom-plugins/legacy-method.md similarity index 96% rename from docs/manual/configuring/custom-plugins/old-method.md rename to docs/manual/configuring/custom-plugins/legacy-method.md index 3b9d090e..0a6b3775 100644 --- a/docs/manual/configuring/custom-plugins/old-method.md +++ b/docs/manual/configuring/custom-plugins/legacy-method.md @@ -1,4 +1,4 @@ -# Old Method {#sec-old-method} +# Legacy Method {#sec-legacy-method} Prior to version 0.5, the method of adding new plugins was adding the plugin package to `vim.startPlugins` and add its configuration as a DAG under one of diff --git a/docs/manual/configuring/custom-plugins/new-method.md b/docs/manual/configuring/custom-plugins/non-lazy-method.md similarity index 93% rename from docs/manual/configuring/custom-plugins/new-method.md rename to docs/manual/configuring/custom-plugins/non-lazy-method.md index 200ba5e7..351af2eb 100644 --- a/docs/manual/configuring/custom-plugins/new-method.md +++ b/docs/manual/configuring/custom-plugins/non-lazy-method.md @@ -1,4 +1,4 @@ -# New Method {#sec-new-method} +# Non-lazy Method {#sec-non-lazy-method} As of version **0.5**, we have a more extensive API for configuring plugins, under `vim.extraPlugins`. Instead of using DAGs exposed by the library, you may diff --git a/docs/manual/configuring/dag-entries.md b/docs/manual/configuring/dag-entries.md index 402cde66..ff5d5c72 100644 --- a/docs/manual/configuring/dag-entries.md +++ b/docs/manual/configuring/dag-entries.md @@ -12,12 +12,14 @@ entries in nvf: 2. `globalsScript` - used to set globals defined in `vim.globals` 3. `basic` - used to set basic configuration options 4. `optionsScript` - used to set options defined in `vim.o` -5. `theme` (this is simply placed before `pluginConfigs`, meaning that - surrounding entries don't depend on it) - used to set up the theme, which has - to be done before other plugins -6. `pluginConfigs` - the result of the nested `vim.pluginRC` (internal option, +5. `theme` (this is simply placed before `pluginConfigs` and `lazyConfigs`, meaning that + surrounding entries don't depend on it) - used to set up the theme, which has to be done before + other plugins +6. `lazyConfigs` - `lz.n` and `lzn-auto-require` configs. If `vim.lazy.enable` + is false, this will contain each plugin's config instead. +7. `pluginConfigs` - the result of the nested `vim.pluginRC` (internal option, see the [Custom Plugins](/index.xhtml#ch-custom-plugins) page for adding your own plugins) DAG, used to set up internal plugins -7. `extraPluginConfigs` - the result of `vim.extraPlugins`, which is not a +8. `extraPluginConfigs` - the result of `vim.extraPlugins`, which is not a direct DAG, but is converted to, and resolved as one internally -8. `mappings` - the result of `vim.maps` +9. `mappings` - the result of `vim.maps` diff --git a/docs/manual/hacking/additional-plugins.md b/docs/manual/hacking/additional-plugins.md index 7c802154..8531aa98 100644 --- a/docs/manual/hacking/additional-plugins.md +++ b/docs/manual/hacking/additional-plugins.md @@ -124,3 +124,61 @@ vim.your-plugin.setupOpts = { ''; } ``` + +## Lazy plugins {#sec-lazy-plugins} + +If the plugin can be lazy-loaded, `vim.lazy.plugins` should be used to add it. Lazy +plugins are managed by `lz.n`. + +```nix +# in modules/.../your-plugin/config.nix +{lib, config, ...}: +let + cfg = config.vim.your-plugin; +in { + vim.lazy.plugins.your-plugin = { + # instead of vim.startPlugins, use this: + package = "your-plugin"; + + # if your plugin uses the `require('your-plugin').setup{...}` pattern + setupModule = "your-plugin"; + inherit (cfg) setupOpts; + + # events that trigger this plugin to be loaded + event = ["DirChanged"]; + cmd = ["YourPluginCommand"]; + + # keymaps + keys = [ + # we'll cover this in detail in the keymaps section + { + key = "d"; + mode = "n"; + action = ":YourPluginCommand"; + } + ]; + }; +; +} +``` + +This results in the following lua code: +```lua +require('lz.n').load({ + { + "name-of-your-plugin", + after = function() + require('your-plugin').setup({--[[ your setupOpts ]]}) + end, + + event = {"DirChanged"}, + cmd = {"YourPluginCommand"}, + keys = { + {"d", ":YourPluginCommand", mode = {"n"}}, + }, + } +}) +``` + +A full list of options can be found +[here](https://notashelf.github.io/nvf/options.html#opt-vim.lazy.plugins diff --git a/docs/release-notes/rl-0.7.md b/docs/release-notes/rl-0.7.md index 87df91e7..bfd08b1b 100644 --- a/docs/release-notes/rl-0.7.md +++ b/docs/release-notes/rl-0.7.md @@ -123,6 +123,10 @@ To migrate to `nixfmt`, simply change `vim.languages.nix.format.type` to recommended to go through rustacean.nvim's README to take a closer look at its features and usage +- Add [lz.n] support and lazy-load some builtin plugins. + +[lz.n]: https://github.com/mrcjkb/lz.n + [jacekpoz](https://jacekpoz.pl): [ocaml-lsp]: https://github.com/ocaml/ocaml-lsp diff --git a/flake.lock b/flake.lock index 4e5ec65c..f387d4ad 100644 --- a/flake.lock +++ b/flake.lock @@ -892,6 +892,39 @@ "type": "github" } }, + "plugin-lz-n": { + "flake": false, + "locked": { + "lastModified": 1729525284, + "narHash": "sha256-fk+ejqcqqOQz3q4D3VB2Q+U/6wCpCDk1tiDMp2YrPNE=", + "owner": "nvim-neorocks", + "repo": "lz.n", + "rev": "ffd9991400ba7137f4fa8560ff50bccd7f8fb3ee", + "type": "github" + }, + "original": { + "owner": "nvim-neorocks", + "repo": "lz.n", + "type": "github" + } + }, + "plugin-lzn-auto-require": { + "flake": false, + "locked": { + "lastModified": 1727636949, + "narHash": "sha256-BAOzN+XOrFAJwHmsF8JtZ2EyjP9283FD/I2TbFqGSEw=", + "owner": "horriblename", + "repo": "lzn-auto-require", + "rev": "55ecd60831dac8c01d6f3dcb63a30a63a1690eb8", + "type": "github" + }, + "original": { + "owner": "horriblename", + "ref": "require-rewrite", + "repo": "lzn-auto-require", + "type": "github" + } + }, "plugin-mind-nvim": { "flake": false, "locked": { @@ -1629,6 +1662,22 @@ "type": "github" } }, + "plugin-rtp-nvim": { + "flake": false, + "locked": { + "lastModified": 1724409589, + "narHash": "sha256-lmJbiD7I7MTEEpukESs67uAmLyn+p66hrUKLbEHp0Kw=", + "owner": "nvim-neorocks", + "repo": "rtp.nvim", + "rev": "494ddfc888bb466555d90ace731856de1320fe45", + "type": "github" + }, + "original": { + "owner": "nvim-neorocks", + "repo": "rtp.nvim", + "type": "github" + } + }, "plugin-rustaceanvim": { "flake": false, "locked": { @@ -1991,6 +2040,8 @@ "plugin-lua-utils-nvim": "plugin-lua-utils-nvim", "plugin-lualine": "plugin-lualine", "plugin-luasnip": "plugin-luasnip", + "plugin-lz-n": "plugin-lz-n", + "plugin-lzn-auto-require": "plugin-lzn-auto-require", "plugin-mind-nvim": "plugin-mind-nvim", "plugin-minimap-vim": "plugin-minimap-vim", "plugin-modes-nvim": "plugin-modes-nvim", @@ -2037,6 +2088,7 @@ "plugin-project-nvim": "plugin-project-nvim", "plugin-registers": "plugin-registers", "plugin-rose-pine": "plugin-rose-pine", + "plugin-rtp-nvim": "plugin-rtp-nvim", "plugin-rustaceanvim": "plugin-rustaceanvim", "plugin-scrollbar-nvim": "plugin-scrollbar-nvim", "plugin-smartcolumn": "plugin-smartcolumn", diff --git a/flake.nix b/flake.nix index 00b56c51..d8efa3b8 100644 --- a/flake.nix +++ b/flake.nix @@ -113,6 +113,22 @@ }; ## Plugins + # Lazy loading + plugin-lz-n = { + url = "github:nvim-neorocks/lz.n"; + flake = false; + }; + + plugin-lzn-auto-require = { + url = "github:horriblename/lzn-auto-require/require-rewrite"; + flake = false; + }; + + plugin-rtp-nvim = { + url = "github:nvim-neorocks/rtp.nvim"; + flake = false; + }; + # LSP plugins plugin-nvim-lspconfig = { url = "github:neovim/nvim-lspconfig"; diff --git a/lib/binds.nix b/lib/binds.nix index 8c9e9a62..298cd30a 100644 --- a/lib/binds.nix +++ b/lib/binds.nix @@ -67,6 +67,30 @@ mkLuaBinding binding.value action binding.description; pushDownDefault = attr: mapAttrs (_: mkDefault) attr; + + mkLznBinding = mode: key: action: desc: { + inherit mode desc key action; + }; + + mkLznExprBinding = mode: key: action: desc: { + inherit mode desc key action; + lua = true; + silent = true; + expr = true; + }; + + mkSetLznBinding = binding: action: { + inherit action; + key = binding.value; + desc = binding.description; + }; + + mkSetLuaLznBinding = binding: action: { + inherit action; + key = binding.value; + lua = true; + desc = binding.description; + }; }; in binds diff --git a/modules/default.nix b/modules/default.nix index 6a950802..6306da9a 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -84,10 +84,7 @@ # built (or "normalized") plugins that are modified builtStartPlugins = buildConfigPlugins vimOptions.startPlugins; - builtOptPlugins = map (package: { - plugin = package; - optional = true; - }) (buildConfigPlugins vimOptions.optPlugins); + builtOptPlugins = map (package: package // {optional = true;}) (buildConfigPlugins vimOptions.optPlugins); # additional Lua and Python3 packages, mapped to their respective functions # to conform to the format mnw expects. end user should diff --git a/modules/modules.nix b/modules/modules.nix index 1204e43f..784c413e 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -50,6 +50,7 @@ "build" "rc" "warnings" + "lazy" ]; # Extra modules, such as deprecation warnings diff --git a/modules/plugins/assistant/copilot/config.nix b/modules/plugins/assistant/copilot/config.nix index 923a0c6d..9f92d14a 100644 --- a/modules/plugins/assistant/copilot/config.nix +++ b/modules/plugins/assistant/copilot/config.nix @@ -4,11 +4,8 @@ ... }: let inherit (builtins) toJSON; - inherit (lib.nvim.lua) toLuaObject; - inherit (lib.modules) mkIf mkMerge; - inherit (lib.nvim.dag) entryAnywhere; - inherit (lib.lists) optionals; - inherit (lib.nvim.binds) mkLuaBinding; + inherit (lib.modules) mkIf; + inherit (lib.strings) optionalString; cfg = config.vim.assistant.copilot; @@ -23,65 +20,68 @@ end end ''; + + mkLuaKeymap = mode: key: action: desc: opts: + opts + // { + inherit mode key action desc; + lua = true; + }; in { config = mkIf cfg.enable { - vim.startPlugins = - [ - "copilot-lua" - # cfg.copilotNodePackage - ] - ++ optionals cfg.cmp.enable [ - "copilot-cmp" - ]; + vim = { + lazy.plugins = { + copilot-lua = { + package = "copilot-lua"; + setupModule = "copilot"; + inherit (cfg) setupOpts; + after = mkIf cfg.cmp.enable "require('copilot_cmp').setup()"; - vim.autocomplete.nvim-cmp.sources = {copilot = "[Copilot]";}; + cmd = ["Copilot" "CopilotAuth" "CopilotDetach" "CopilotPanel" "CopilotStop"]; + keys = [ + (mkLuaKeymap ["n"] cfg.mappings.panel.accept (wrapPanelBinding ''require("copilot.panel").accept'' cfg.mappings.panel.accept) "[copilot] Accept suggestion" {}) + (mkLuaKeymap ["n"] cfg.mappings.panel.jumpNext (wrapPanelBinding "require(\"copilot.panel\").jump_next" cfg.mappings.panel.jumpNext) "[copilot] Accept suggestion" {}) + (mkLuaKeymap ["n"] cfg.mappings.panel.jumpPrev (wrapPanelBinding "require(\"copilot.panel\").jump_prev" cfg.mappings.panel.jumpPrev) "[copilot] Accept suggestion" {}) + (mkLuaKeymap ["n"] cfg.mappings.panel.refresh (wrapPanelBinding "require(\"copilot.panel\").refresh" cfg.mappings.panel.refresh) "[copilot] Accept suggestion" {}) + (mkLuaKeymap ["n"] cfg.mappings.panel.open (wrapPanelBinding '' + function() require("copilot.panel").open({ position = "${cfg.setupOpts.panel.layout.position}", ratio = ${toString cfg.setupOpts.panel.layout.ratio}, }) end + '' + cfg.mappings.panel.open) "[copilot] Accept suggestion" {}) - vim.pluginRC.copilot = entryAnywhere '' - require("copilot").setup(${toLuaObject cfg.setupOpts}) - - ${lib.optionalString cfg.cmp.enable '' - require("copilot_cmp").setup() - ''} - ''; - - # Disable plugin handled keymaps. - # Setting it here so that it doesn't show up in user docs - vim.assistant.copilot.setupOpts = { - panel.keymap = { - jump_prev = lib.mkDefault false; - jump_next = lib.mkDefault false; - accept = lib.mkDefault false; - refresh = lib.mkDefault false; - open = lib.mkDefault false; + (mkLuaKeymap ["i"] cfg.mappings.suggestion.accept "function() require('copilot.suggestion').accept() end" "[copilot] Accept suggestion" {}) + (mkLuaKeymap ["i"] cfg.mappings.suggestion.acceptLine "function() require('copilot.suggestion').accept_line() end" "[copilot] Accept suggestion (line)" {}) + (mkLuaKeymap ["i"] cfg.mappings.suggestion.acceptWord "function() require('copilot.suggestion').accept_word() end" "[copilot] Accept suggestion (word)" {}) + (mkLuaKeymap ["i"] cfg.mappings.suggestion.dismiss "function() require('copilot.suggestion').dismiss() end" "[copilot] dismiss suggestion" {}) + (mkLuaKeymap ["i"] cfg.mappings.suggestion.next "function() require('copilot.suggestion').next() end" "[copilot] next suggestion" {}) + (mkLuaKeymap ["i"] cfg.mappings.suggestion.prev "function() require('copilot.suggestion').prev() end" "[copilot] previous suggestion" {}) + ]; + }; }; - suggestion.keymap = { - accept = lib.mkDefault false; - accept_word = lib.mkDefault false; - accept_line = lib.mkDefault false; - next = lib.mkDefault false; - prev = lib.mkDefault false; - dismiss = lib.mkDefault false; + + autocomplete.nvim-cmp = { + sources = {copilot = "[Copilot]";}; + sourcePlugins = ["copilot-cmp"]; + }; + + # Disable plugin handled keymaps. + # Setting it here so that it doesn't show up in user docs + assistant.copilot.setupOpts = { + panel.keymap = { + jump_prev = lib.mkDefault false; + jump_next = lib.mkDefault false; + accept = lib.mkDefault false; + refresh = lib.mkDefault false; + open = lib.mkDefault false; + }; + suggestion.keymap = { + accept = lib.mkDefault false; + accept_word = lib.mkDefault false; + accept_line = lib.mkDefault false; + next = lib.mkDefault false; + prev = lib.mkDefault false; + dismiss = lib.mkDefault false; + }; }; }; - - vim.maps.normal = mkMerge [ - (mkLuaBinding cfg.mappings.panel.jumpPrev (wrapPanelBinding "require(\"copilot.panel\").jump_prev" cfg.mappings.panel.jumpPrev) "[copilot] Accept suggestion") - (mkLuaBinding cfg.mappings.panel.jumpNext (wrapPanelBinding "require(\"copilot.panel\").jump_next" cfg.mappings.panel.jumpNext) "[copilot] Accept suggestion") - (mkLuaBinding cfg.mappings.panel.accept (wrapPanelBinding ''require("copilot.panel").accept'' cfg.mappings.panel.accept) "[copilot] Accept suggestion") - (mkLuaBinding cfg.mappings.panel.refresh (wrapPanelBinding "require(\"copilot.panel\").refresh" cfg.mappings.panel.refresh) "[copilot] Accept suggestion") - (mkLuaBinding cfg.mappings.panel.open (wrapPanelBinding '' - function() require("copilot.panel").open({ position = "${cfg.setupOpts.panel.layout.position}", ratio = ${toString cfg.setupOpts.panel.layout.ratio}, }) end - '' - cfg.mappings.panel.open) "[copilot] Accept suggestion") - ]; - - vim.maps.insert = mkMerge [ - (mkLuaBinding cfg.mappings.suggestion.accept "require(\"copilot.suggestion\").accept" "[copilot] Accept suggestion") - (mkLuaBinding cfg.mappings.suggestion.acceptLine "require(\"copilot.suggestion\").accept_line" "[copilot] Accept suggestion (line)") - (mkLuaBinding cfg.mappings.suggestion.acceptWord "require(\"copilot.suggestion\").accept_word" "[copilot] Accept suggestion (word)") - (mkLuaBinding cfg.mappings.suggestion.next "require(\"copilot.suggestion\").next" "[copilot] next suggestion") - (mkLuaBinding cfg.mappings.suggestion.prev "require(\"copilot.suggestion\").prev" "[copilot] previous suggestion") - (mkLuaBinding cfg.mappings.suggestion.dismiss "require(\"copilot.suggestion\").dismiss" "[copilot] dismiss suggestion") - ]; }; } diff --git a/modules/plugins/comments/comment-nvim/comment-nvim.nix b/modules/plugins/comments/comment-nvim/comment-nvim.nix index 61a91715..76fd8131 100644 --- a/modules/plugins/comments/comment-nvim/comment-nvim.nix +++ b/modules/plugins/comments/comment-nvim/comment-nvim.nix @@ -1,6 +1,7 @@ {lib, ...}: let inherit (lib.options) mkEnableOption; inherit (lib.nvim.binds) mkMappingOption; + inherit (lib.nvim.types) mkPluginSetupOption; in { options.vim.comments.comment-nvim = { enable = mkEnableOption "smart and powerful comment plugin for neovim comment-nvim"; @@ -15,5 +16,12 @@ in { toggleSelectedLine = mkMappingOption "Toggle selected comment" "gc"; toggleSelectedBlock = mkMappingOption "Toggle selected block" "gb"; }; + + setupOpts = mkPluginSetupOption "Comment-nvim" { + mappings = { + basic = mkEnableOption "basic mappings"; + extra = mkEnableOption "extra mappings"; + }; + }; }; } diff --git a/modules/plugins/comments/comment-nvim/config.nix b/modules/plugins/comments/comment-nvim/config.nix index e228d92c..c2c1a7e2 100644 --- a/modules/plugins/comments/comment-nvim/config.nix +++ b/modules/plugins/comments/comment-nvim/config.nix @@ -3,46 +3,38 @@ lib, ... }: let - inherit (lib.modules) mkIf mkMerge; - inherit (lib.nvim.binds) mkExprBinding mkBinding; - inherit (lib.nvim.dag) entryAnywhere; + inherit (lib.modules) mkIf; + inherit (lib.nvim.binds) mkLznExprBinding mkLznBinding; cfg = config.vim.comments.comment-nvim; self = import ./comment-nvim.nix {inherit lib;}; inherit (self.options.vim.comments.comment-nvim) mappings; in { config = mkIf cfg.enable { - vim.startPlugins = ["comment-nvim"]; - - vim.maps.normal = mkMerge [ - (mkBinding cfg.mappings.toggleOpLeaderLine "(comment_toggle_linewise)" mappings.toggleOpLeaderLine.description) - (mkBinding cfg.mappings.toggleOpLeaderBlock "(comment_toggle_blockwise)" mappings.toggleOpLeaderBlock.description) - - (mkExprBinding cfg.mappings.toggleCurrentLine '' - function() - return vim.api.nvim_get_vvar('count') == 0 and '(comment_toggle_linewise_current)' - or '(comment_toggle_linewise_count)' - end - '' - mappings.toggleCurrentLine.description) - (mkExprBinding cfg.mappings.toggleCurrentBlock '' - function() - return vim.api.nvim_get_vvar('count') == 0 and '(comment_toggle_blockwise_current)' - or '(comment_toggle_blockwise_count)' - end - '' - mappings.toggleCurrentBlock.description) - ]; - - vim.maps.visual = mkMerge [ - (mkBinding cfg.mappings.toggleSelectedLine "(comment_toggle_linewise_visual)" mappings.toggleSelectedLine.description) - (mkBinding cfg.mappings.toggleSelectedBlock "(comment_toggle_blockwise_visual)" mappings.toggleSelectedBlock.description) - ]; - - vim.pluginRC.comment-nvim = entryAnywhere '' - require('Comment').setup({ - mappings = { basic = false, extra = false, }, - }) - ''; + vim.lazy.plugins.comment-nvim = { + package = "comment-nvim"; + setupModule = "Comment"; + inherit (cfg) setupOpts; + keys = [ + (mkLznBinding ["n"] cfg.mappings.toggleOpLeaderLine "(comment_toggle_linewise)" mappings.toggleOpLeaderLine.description) + (mkLznBinding ["n"] cfg.mappings.toggleOpLeaderBlock "(comment_toggle_blockwise)" mappings.toggleOpLeaderBlock.description) + (mkLznExprBinding ["n"] cfg.mappings.toggleCurrentLine '' + function() + return vim.api.nvim_get_vvar('count') == 0 and '(comment_toggle_linewise_current)' + or '(comment_toggle_linewise_count)' + end + '' + mappings.toggleCurrentLine.description) + (mkLznExprBinding ["n"] cfg.mappings.toggleCurrentBlock '' + function() + return vim.api.nvim_get_vvar('count') == 0 and '(comment_toggle_blockwise_current)' + or '(comment_toggle_blockwise_count)' + end + '' + mappings.toggleCurrentBlock.description) + (mkLznBinding ["x"] cfg.mappings.toggleSelectedLine "(comment_toggle_linewise_visual)" mappings.toggleSelectedLine.description) + (mkLznBinding ["x"] cfg.mappings.toggleSelectedBlock "(comment_toggle_blockwise_visual)" mappings.toggleSelectedBlock.description) + ]; + }; }; } diff --git a/modules/plugins/completion/nvim-cmp/config.nix b/modules/plugins/completion/nvim-cmp/config.nix index 5d20242d..54670ace 100644 --- a/modules/plugins/completion/nvim-cmp/config.nix +++ b/modules/plugins/completion/nvim-cmp/config.nix @@ -3,91 +3,122 @@ config, ... }: let - inherit (lib.modules) mkIf; + inherit (lib.modules) mkIf mkMerge; inherit (lib.strings) optionalString; inherit (lib.generators) mkLuaInline; - inherit (lib.nvim.dag) entryAfter; inherit (lib.nvim.lua) toLuaObject; - inherit (builtins) attrNames; + inherit (lib.nvim.attrsets) mapListToAttrs; + inherit (builtins) attrNames typeOf tryEval concatStringsSep; cfg = config.vim.autocomplete.nvim-cmp; luasnipEnable = config.vim.snippets.luasnip.enable; + getPluginName = plugin: + if typeOf plugin == "string" + then plugin + else if (plugin ? pname && (tryEval plugin.pname).success) + then plugin.pname + else plugin.name; inherit (cfg) mappings; in { config = mkIf cfg.enable { vim = { - startPlugins = [ - "nvim-cmp" - "cmp-buffer" - "cmp-path" + startPlugins = ["rtp-nvim"]; + lazy.plugins = mkMerge [ + (mapListToAttrs (package: { + name = getPluginName package; + value = { + inherit package; + lazy = true; + after = '' + local path = vim.fn.globpath(vim.o.packpath, 'pack/*/opt/${getPluginName package}') + require("rtp_nvim").source_after_plugin_dir(path) + ''; + }; + }) + cfg.sourcePlugins) + { + nvim-cmp = { + package = "nvim-cmp"; + after = '' + ${optionalString luasnipEnable "local luasnip = require('luasnip')"} + local cmp = require("cmp") + cmp.setup(${toLuaObject cfg.setupOpts}) + + ${optionalString config.vim.lazy.enable + (concatStringsSep "\n" (map + (package: "require('lz.n').trigger_load(${toLuaObject (getPluginName package)})") + cfg.sourcePlugins))} + ''; + + event = ["InsertEnter" "CmdlineEnter"]; + }; + } ]; - autocomplete.nvim-cmp.sources = { - nvim-cmp = null; - buffer = "[Buffer]"; - path = "[Path]"; - }; - - autocomplete.nvim-cmp.setupOpts = { - sources = map (s: {name = s;}) (attrNames cfg.sources); - - # TODO: try to get nvim-cmp to follow global border style - window = mkIf config.vim.ui.borders.enable { - completion = mkLuaInline "cmp.config.window.bordered()"; - documentation = mkLuaInline "cmp.config.window.bordered()"; + autocomplete.nvim-cmp = { + sources = { + nvim-cmp = null; + buffer = "[Buffer]"; + path = "[Path]"; }; - formatting.format = cfg.format; - }; + sourcePlugins = ["cmp-buffer" "cmp-path"]; - pluginRC.nvim-cmp = mkIf cfg.enable (entryAfter ["autopairs" "luasnip"] '' - ${optionalString luasnipEnable "local luasnip = require('luasnip')"} - local cmp = require("cmp") - cmp.setup(${toLuaObject cfg.setupOpts}) - ''); + setupOpts = { + sources = map (s: {name = s;}) (attrNames cfg.sources); - # `cmp` and `luasnip` are defined above, in the `nvim-cmp` section - autocomplete.nvim-cmp.setupOpts.mapping = { - ${mappings.complete} = mkLuaInline "cmp.mapping.complete()"; - ${mappings.close} = mkLuaInline "cmp.mapping.abort()"; - ${mappings.scrollDocsUp} = mkLuaInline "cmp.mapping.scroll_docs(-4)"; - ${mappings.scrollDocsDown} = mkLuaInline "cmp.mapping.scroll_docs(4)"; - ${mappings.confirm} = mkLuaInline "cmp.mapping.confirm({ select = true })"; + # TODO: try to get nvim-cmp to follow global border style + window = mkIf config.vim.ui.borders.enable { + completion = mkLuaInline "cmp.config.window.bordered()"; + documentation = mkLuaInline "cmp.config.window.bordered()"; + }; - ${mappings.next} = mkLuaInline '' - cmp.mapping(function(fallback) - local has_words_before = function() - local line, col = unpack(vim.api.nvim_win_get_cursor(0)) - return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil - end + formatting.format = cfg.format; - if cmp.visible() then - cmp.select_next_item() - ${optionalString luasnipEnable '' - elseif luasnip.locally_jumpable(1) then - luasnip.jump(1) - ''} - elseif has_words_before() then - cmp.complete() - else - fallback() - end - end) - ''; + # `cmp` and `luasnip` are defined above, in the `nvim-cmp` section + mapping = { + ${mappings.complete} = mkLuaInline "cmp.mapping.complete()"; + ${mappings.close} = mkLuaInline "cmp.mapping.abort()"; + ${mappings.scrollDocsUp} = mkLuaInline "cmp.mapping.scroll_docs(-4)"; + ${mappings.scrollDocsDown} = mkLuaInline "cmp.mapping.scroll_docs(4)"; + ${mappings.confirm} = mkLuaInline "cmp.mapping.confirm({ select = true })"; - ${mappings.previous} = mkLuaInline '' - cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item() - ${optionalString luasnipEnable '' - elseif luasnip.locally_jumpable(-1) then - luasnip.jump(-1) - ''} - else - fallback() - end - end) - ''; + ${mappings.next} = mkLuaInline '' + cmp.mapping(function(fallback) + local has_words_before = function() + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil + end + + if cmp.visible() then + cmp.select_next_item() + ${optionalString luasnipEnable '' + elseif luasnip.locally_jumpable(1) then + luasnip.jump(1) + ''} + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end) + ''; + + ${mappings.previous} = mkLuaInline '' + cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + ${optionalString luasnipEnable '' + elseif luasnip.locally_jumpable(-1) then + luasnip.jump(-1) + ''} + else + fallback() + end + end) + ''; + }; + }; }; }; }; diff --git a/modules/plugins/completion/nvim-cmp/nvim-cmp.nix b/modules/plugins/completion/nvim-cmp/nvim-cmp.nix index 860a1c3f..8246e710 100644 --- a/modules/plugins/completion/nvim-cmp/nvim-cmp.nix +++ b/modules/plugins/completion/nvim-cmp/nvim-cmp.nix @@ -4,10 +4,10 @@ ... }: let inherit (lib.options) mkEnableOption mkOption literalExpression literalMD; - inherit (lib.types) str attrsOf nullOr either; + inherit (lib.types) str attrsOf nullOr either listOf; inherit (lib.generators) mkLuaInline; inherit (lib.nvim.binds) mkMappingOption; - inherit (lib.nvim.types) mkPluginSetupOption luaInline mergelessListOf; + inherit (lib.nvim.types) mkPluginSetupOption luaInline mergelessListOf pluginType; inherit (lib.nvim.lua) toLuaObject; inherit (builtins) isString; @@ -99,5 +99,11 @@ in { } ''; }; + + sourcePlugins = mkOption { + type = listOf pluginType; + default = []; + description = "List of source plugins used by nvim-cmp."; + }; }; } diff --git a/modules/plugins/debugger/nvim-dap/config.nix b/modules/plugins/debugger/nvim-dap/config.nix index 358d7c86..7e9e8f76 100644 --- a/modules/plugins/debugger/nvim-dap/config.nix +++ b/modules/plugins/debugger/nvim-dap/config.nix @@ -6,7 +6,7 @@ inherit (lib.strings) optionalString; inherit (lib.modules) mkIf mkMerge; inherit (lib.attrsets) mapAttrs; - inherit (lib.nvim.binds) addDescriptionsToMappings mkSetLuaBinding; + inherit (lib.nvim.binds) addDescriptionsToMappings mkSetLuaBinding mkSetLuaLznBinding; inherit (lib.nvim.dag) entryAnywhere entryAfter; cfg = config.vim.debugger.nvim-dap; @@ -52,24 +52,31 @@ in { }) (mkIf (cfg.enable && cfg.ui.enable) { vim = { - startPlugins = ["nvim-dap-ui" "nvim-nio"]; + startPlugins = ["nvim-nio"]; - pluginRC.nvim-dap-ui = entryAfter ["nvim-dap"] ('' - local dapui = require("dapui") - dapui.setup() - '' - + optionalString cfg.ui.autoStart '' + lazy.plugins.nvim-dap-ui = { + package = "nvim-dap-ui"; + setupModule = "dapui"; + inherit (cfg.ui) setupOpts; + + keys = [ + (mkSetLuaLznBinding mappings.toggleDapUI "function() require('dapui').toggle() end") + ]; + }; + + pluginRC.nvim-dap-ui = entryAfter ["nvim-dap"] ( + optionalString cfg.ui.autoStart '' dap.listeners.after.event_initialized["dapui_config"] = function() - dapui.open() + require("dapui").open() end dap.listeners.before.event_terminated["dapui_config"] = function() - dapui.close() + require("dapui").close() end dap.listeners.before.event_exited["dapui_config"] = function() - dapui.close() + require("dapui").close() end - ''); - maps.normal = mkSetLuaBinding mappings.toggleDapUI "require('dapui').toggle"; + '' + ); }; }) ]; diff --git a/modules/plugins/debugger/nvim-dap/nvim-dap.nix b/modules/plugins/debugger/nvim-dap/nvim-dap.nix index 3fab33ae..5a699491 100644 --- a/modules/plugins/debugger/nvim-dap/nvim-dap.nix +++ b/modules/plugins/debugger/nvim-dap/nvim-dap.nix @@ -2,12 +2,16 @@ inherit (lib.options) mkEnableOption mkOption; inherit (lib.types) bool attrsOf str; inherit (lib.nvim.binds) mkMappingOption; + inherit (lib.nvim.types) mkPluginSetupOption; in { options.vim.debugger.nvim-dap = { enable = mkEnableOption "debugging via nvim-dap"; ui = { enable = mkEnableOption "UI extension for nvim-dap"; + + setupOpts = mkPluginSetupOption "nvim-dap-ui" {}; + autoStart = mkOption { type = bool; default = true; diff --git a/modules/plugins/filetree/neo-tree/config.nix b/modules/plugins/filetree/neo-tree/config.nix index be67df1e..13da0354 100644 --- a/modules/plugins/filetree/neo-tree/config.nix +++ b/modules/plugins/filetree/neo-tree/config.nix @@ -4,8 +4,6 @@ ... }: let inherit (lib.modules) mkIf; - inherit (lib.nvim.dag) entryAnywhere; - inherit (lib.nvim.lua) toLuaObject; cfg = config.vim.filetree.neo-tree; in { @@ -16,15 +14,17 @@ in { "plenary-nvim" # commons library "image-nvim" # optional for image previews "nui-nvim" # ui library - # neotree - "neo-tree-nvim" ]; - visuals.nvimWebDevicons.enable = true; + lazy.plugins.neo-tree-nvim = { + package = "neo-tree-nvim"; + setupModule = "neo-tree"; + inherit (cfg) setupOpts; - pluginRC.neo-tree = entryAnywhere '' - require("neo-tree").setup(${toLuaObject cfg.setupOpts}) - ''; + cmd = ["Neotree"]; + }; + + visuals.nvimWebDevicons.enable = true; }; }; } diff --git a/modules/plugins/filetree/nvimtree/config.nix b/modules/plugins/filetree/nvimtree/config.nix index b97b1e45..30cc680b 100644 --- a/modules/plugins/filetree/nvimtree/config.nix +++ b/modules/plugins/filetree/nvimtree/config.nix @@ -5,10 +5,9 @@ ... }: let inherit (lib.strings) optionalString; - inherit (lib.modules) mkIf mkMerge; - inherit (lib.nvim.binds) mkBinding; + inherit (lib.modules) mkIf; + inherit (lib.nvim.binds) mkLznBinding; inherit (lib.nvim.dag) entryAnywhere; - inherit (lib.nvim.lua) toLuaObject; inherit (lib.nvim.binds) pushDownDefault; cfg = config.vim.filetree.nvimTree; @@ -16,69 +15,74 @@ inherit (self.options.vim.filetree.nvimTree) mappings; in { config = mkIf cfg.enable { - vim.startPlugins = ["nvim-tree-lua"]; + vim = { + binds.whichKey.register = pushDownDefault { + "t" = "+NvimTree"; + }; - vim.maps.normal = mkMerge [ - (mkBinding cfg.mappings.toggle ":NvimTreeToggle" mappings.toggle.description) - (mkBinding cfg.mappings.refresh ":NvimTreeRefresh" mappings.refresh.description) - (mkBinding cfg.mappings.findFile ":NvimTreeFindFile" mappings.findFile.description) - (mkBinding cfg.mappings.focus ":NvimTreeFocus" mappings.focus.description) - ]; + lazy.plugins.nvim-tree-lua = { + package = "nvim-tree-lua"; + setupModule = "nvim-tree"; + inherit (cfg) setupOpts; + cmd = ["NvimTreeClipboard" "NvimTreeClose" "NvimTreeCollapse" "NvimTreeCollapseKeepBuffers" "NvimTreeFindFile" "NvimTreeFindFileToggle" "NvimTreeFocus" "NvimTreeHiTest" "NvimTreeOpen" "NvimTreeRefresh" "NvimTreeResize" "NvimTreeToggle"]; + keys = [ + (mkLznBinding ["n"] cfg.mappings.toggle ":NvimTreeToggle" mappings.toggle.description) + (mkLznBinding ["n"] cfg.mappings.refresh ":NvimTreeRefresh" mappings.refresh.description) + (mkLznBinding ["n"] cfg.mappings.findFile ":NvimTreeFindFile" mappings.findFile.description) + (mkLznBinding ["n"] cfg.mappings.focus ":NvimTreeFocus" mappings.focus.description) + ]; + }; - vim.binds.whichKey.register = pushDownDefault { - "t" = "+NvimTree"; + pluginRC.nvimtreelua = entryAnywhere '' + ${ + optionalString cfg.setupOpts.disable_netrw '' + -- disable netrew completely + vim.g.loaded_netrw = 1 + vim.g.loaded_netrwPlugin = 1 + '' + } + + ${ + optionalString cfg.openOnSetup '' + ${optionalString config.vim.lazy.enable ''require('lz.n').trigger_load("nvim-tree-lua")''} + -- autostart behaviour + -- Open on startup has been deprecated + -- see https://github.com/nvim-tree/nvim-tree.lua/wiki/Open-At-Startup + + -- use a nix eval to dynamically insert the open on startup function + local function open_nvim_tree(data) + local IGNORED_FT = { + "markdown", + } + + -- buffer is a real file on the disk + local real_file = vim.fn.filereadable(data.file) == 1 + + -- buffer is a [No Name] + local no_name = data.file == "" and vim.bo[data.buf].buftype == "" + + -- &ft + local filetype = vim.bo[data.buf].ft + + -- only files please + if not real_file and not no_name then + return + end + + -- skip ignored filetypes + if vim.tbl_contains(IGNORED_FT, filetype) then + return + end + + -- open the tree but don't focus it + require("nvim-tree.api").tree.toggle({ focus = false }) + end + + -- function to automatically open the tree on VimEnter + vim.api.nvim_create_autocmd({ "VimEnter" }, { callback = open_nvim_tree }) + '' + } + ''; }; - - vim.pluginRC.nvimtreelua = entryAnywhere '' - ${ - optionalString cfg.setupOpts.disable_netrw '' - -- disable netrew completely - vim.g.loaded_netrw = 1 - vim.g.loaded_netrwPlugin = 1 - '' - } - - require'nvim-tree'.setup(${toLuaObject cfg.setupOpts}) - - ${ - optionalString cfg.openOnSetup '' - -- autostart behaviour - -- Open on startup has been deprecated - -- see https://github.com/nvim-tree/nvim-tree.lua/wiki/Open-At-Startup - - -- use a nix eval to dynamically insert the open on startup function - local function open_nvim_tree(data) - local IGNORED_FT = { - "markdown", - } - - -- buffer is a real file on the disk - local real_file = vim.fn.filereadable(data.file) == 1 - - -- buffer is a [No Name] - local no_name = data.file == "" and vim.bo[data.buf].buftype == "" - - -- &ft - local filetype = vim.bo[data.buf].ft - - -- only files please - if not real_file and not no_name then - return - end - - -- skip ignored filetypes - if vim.tbl_contains(IGNORED_FT, filetype) then - return - end - - -- open the tree but don't focus it - require("nvim-tree.api").tree.toggle({ focus = false }) - end - - -- function to automatically open the tree on VimEnter - vim.api.nvim_create_autocmd({ "VimEnter" }, { callback = open_nvim_tree }) - '' - } - ''; }; } diff --git a/modules/plugins/lsp/config.nix b/modules/plugins/lsp/config.nix index dbf6cdbd..e73a5387 100644 --- a/modules/plugins/lsp/config.nix +++ b/modules/plugins/lsp/config.nix @@ -5,7 +5,6 @@ ... }: let inherit (lib.modules) mkIf; - inherit (lib.lists) optional; inherit (lib.strings) optionalString; inherit (lib.trivial) boolToString; inherit (lib.nvim.binds) addDescriptionsToMappings; @@ -23,9 +22,10 @@ in { config = mkIf cfg.enable { vim = { - startPlugins = optional usingNvimCmp "cmp-nvim-lsp"; - - autocomplete.nvim-cmp.sources = {nvim_lsp = "[LSP]";}; + autocomplete.nvim-cmp = { + sources = {nvim_lsp = "[LSP]";}; + sourcePlugins = ["cmp-nvim-lsp"]; + }; pluginRC.lsp-setup = '' vim.g.formatsave = ${boolToString cfg.formatOnSave}; @@ -116,7 +116,60 @@ in { end local capabilities = vim.lsp.protocol.make_client_capabilities() - ${optionalString usingNvimCmp "capabilities = require('cmp_nvim_lsp').default_capabilities()"} + ${optionalString usingNvimCmp '' + -- HACK: copied from cmp-nvim-lsp. If we ever lazy load lspconfig we + -- should re-evaluate whether we can just use `default_capabilities` + capabilities = { + textDocument = { + completion = { + dynamicRegistration = false, + completionItem = { + snippetSupport = true, + commitCharactersSupport = true, + deprecatedSupport = true, + preselectSupport = true, + tagSupport = { + valueSet = { + 1, -- Deprecated + } + }, + insertReplaceSupport = true, + resolveSupport = { + properties = { + "documentation", + "detail", + "additionalTextEdits", + "sortText", + "filterText", + "insertText", + "textEdit", + "insertTextFormat", + "insertTextMode", + }, + }, + insertTextModeSupport = { + valueSet = { + 1, -- asIs + 2, -- adjustIndentation + } + }, + labelDetailsSupport = true, + }, + contextSupport = true, + insertTextMode = 1, + completionList = { + itemDefaults = { + 'commitCharacters', + 'editRange', + 'insertTextFormat', + 'insertTextMode', + 'data', + } + } + }, + }, + } + ''} ''; }; }; diff --git a/modules/plugins/lsp/trouble/config.nix b/modules/plugins/lsp/trouble/config.nix index dd853e30..cae0c7ad 100644 --- a/modules/plugins/lsp/trouble/config.nix +++ b/modules/plugins/lsp/trouble/config.nix @@ -1,41 +1,40 @@ { config, lib, + options, ... }: let - inherit (lib.modules) mkIf mkMerge; - inherit (lib.nvim.dag) entryAnywhere; - inherit (lib.nvim.binds) addDescriptionsToMappings mkSetBinding pushDownDefault; + inherit (lib.modules) mkIf; + inherit (lib.nvim.binds) addDescriptionsToMappings mkSetLznBinding pushDownDefault; cfg = config.vim.lsp; - self = import ./trouble.nix {inherit lib;}; - mappingDefinitions = self.options.vim.lsp.trouble.mappings; + mappingDefinitions = options.vim.lsp.trouble.mappings; mappings = addDescriptionsToMappings cfg.trouble.mappings mappingDefinitions; in { config = mkIf (cfg.enable && cfg.trouble.enable) { vim = { - startPlugins = ["trouble"]; + lazy.plugins.trouble = { + package = "trouble"; + setupModule = "trouble"; + inherit (cfg.trouble) setupOpts; - maps.normal = mkMerge [ - (mkSetBinding mappings.toggle "TroubleToggle") - (mkSetBinding mappings.workspaceDiagnostics "TroubleToggle workspace_diagnostics") - (mkSetBinding mappings.documentDiagnostics "TroubleToggle document_diagnostics") - (mkSetBinding mappings.lspReferences "TroubleToggle lsp_references") - (mkSetBinding mappings.quickfix "TroubleToggle quickfix") - (mkSetBinding mappings.locList "TroubleToggle loclist") - ]; + cmd = "Trouble"; + keys = [ + (mkSetLznBinding mappings.toggle "TroubleToggle") + (mkSetLznBinding mappings.workspaceDiagnostics "TroubleToggle workspace_diagnostics") + (mkSetLznBinding mappings.documentDiagnostics "TroubleToggle document_diagnostics") + (mkSetLznBinding mappings.lspReferences "TroubleToggle lsp_references") + (mkSetLznBinding mappings.quickfix "TroubleToggle quickfix") + (mkSetLznBinding mappings.locList "TroubleToggle loclist") + ]; + }; binds.whichKey.register = pushDownDefault { "l" = "Trouble"; "x" = "+Trouble"; "lw" = "Workspace"; }; - - pluginRC.trouble = entryAnywhere '' - -- Enable trouble diagnostics viewer - require("trouble").setup {} - ''; }; }; } diff --git a/modules/plugins/lsp/trouble/trouble.nix b/modules/plugins/lsp/trouble/trouble.nix index bd16c67e..04bd5068 100644 --- a/modules/plugins/lsp/trouble/trouble.nix +++ b/modules/plugins/lsp/trouble/trouble.nix @@ -1,11 +1,14 @@ {lib, ...}: let inherit (lib.options) mkEnableOption; inherit (lib.nvim.binds) mkMappingOption; + inherit (lib.nvim.types) mkPluginSetupOption; in { options.vim.lsp = { trouble = { enable = mkEnableOption "trouble diagnostics viewer"; + setupOpts = mkPluginSetupOption "Trouble" {}; + mappings = { toggle = mkMappingOption "Toggle trouble [trouble]" "xx"; workspaceDiagnostics = mkMappingOption "Workspace diagnostics [trouble]" "lwd"; diff --git a/modules/plugins/snippets/luasnip/config.nix b/modules/plugins/snippets/luasnip/config.nix index 541fd0fd..927b21fd 100644 --- a/modules/plugins/snippets/luasnip/config.nix +++ b/modules/plugins/snippets/luasnip/config.nix @@ -9,9 +9,18 @@ in { config = mkIf cfg.enable { vim = { - startPlugins = ["luasnip" "cmp-luasnip"] ++ cfg.providers; - autocomplete.nvim-cmp.sources = {luasnip = "[LuaSnip]";}; - pluginRC.luasnip = cfg.loaders; + lazy.plugins = { + luasnip = { + package = "luasnip"; + lazy = true; + after = cfg.loaders; + }; + }; + startPlugins = cfg.providers; + autocomplete.nvim-cmp = { + sources = {luasnip = "[LuaSnip]";}; + sourcePlugins = ["cmp-luasnip"]; + }; }; }; } diff --git a/modules/plugins/terminal/toggleterm/config.nix b/modules/plugins/terminal/toggleterm/config.nix index 07851e40..f0ebd726 100644 --- a/modules/plugins/terminal/toggleterm/config.nix +++ b/modules/plugins/terminal/toggleterm/config.nix @@ -3,39 +3,31 @@ lib, ... }: let - inherit (builtins) toJSON; - inherit (lib.lists) optionals; - inherit (lib.modules) mkIf mkMerge; + inherit (lib.strings) optionalString; + inherit (lib.lists) optional; + inherit (lib.modules) mkIf; inherit (lib.meta) getExe; - inherit (lib.nvim.binds) mkBinding; - inherit (lib.nvim.dag) entryAnywhere entryAfter; + inherit (lib.nvim.binds) mkLznBinding; inherit (lib.nvim.lua) toLuaObject; cfg = config.vim.terminal.toggleterm; + lazygitMapDesc = "Open lazygit [toggleterm]"; in { - config = mkMerge [ - ( - mkIf cfg.enable { - vim = { - startPlugins = [ - "toggleterm-nvim" - ]; + config = mkIf cfg.enable { + vim = { + lazy.plugins.toggleterm-nvim = { + package = "toggleterm-nvim"; + cmd = ["ToggleTerm" "ToggleTermSendCurrentLine" "ToggleTermSendVisualLines" "ToggleTermSendVisualSelection" "ToggleTermSetName" "ToggleTermToggleAll"]; + keys = + [(mkLznBinding ["n"] cfg.mappings.open "execute v:count . \"ToggleTerm\"" "Toggle terminal")] + ++ optional cfg.lazygit.enable { + key = cfg.lazygit.mappings.open; + desc = lazygitMapDesc; + }; - maps.normal = mkBinding cfg.mappings.open "execute v:count . \"ToggleTerm\"" "Toggle terminal"; - - pluginRC.toggleterm = entryAnywhere '' - require("toggleterm").setup(${toLuaObject cfg.setupOpts}) - ''; - }; - } - ) - ( - mkIf (cfg.enable && cfg.lazygit.enable) - { - vim.startPlugins = optionals (cfg.lazygit.package != null) [ - cfg.lazygit.package - ]; - vim.pluginRC.toggleterm-lazygit = entryAfter ["toggleterm"] '' + setupModule = "toggleterm"; + inherit (cfg) setupOpts; + after = optionalString cfg.lazygit.enable '' local terminal = require 'toggleterm.terminal' local lazygit = terminal.Terminal:new({ cmd = '${ @@ -50,9 +42,9 @@ in { end }) - vim.keymap.set('n', ${toJSON cfg.lazygit.mappings.open}, function() lazygit:toggle() end, {silent = true, noremap = true, desc = 'Open lazygit [toggleterm]'}) + vim.keymap.set('n', ${toLuaObject cfg.lazygit.mappings.open}, function() lazygit:toggle() end, {silent = true, noremap = true, desc = '${lazygitMapDesc}'}) ''; - } - ) - ]; + }; + }; + }; } diff --git a/modules/plugins/theme/theme.nix b/modules/plugins/theme/theme.nix index 0422c027..b3147c00 100644 --- a/modules/plugins/theme/theme.nix +++ b/modules/plugins/theme/theme.nix @@ -66,7 +66,7 @@ in { config = mkIf cfg.enable { vim = { startPlugins = [cfg.name]; - luaConfigRC.theme = entryBefore ["pluginConfigs"] '' + luaConfigRC.theme = entryBefore ["pluginConfigs" "lazyConfigs"] '' ${cfg.extraConfig} ${supportedThemes.${cfg.name}.setup {inherit (cfg) style transparent base16-colors;}} ''; diff --git a/modules/plugins/treesitter/config.nix b/modules/plugins/treesitter/config.nix index ae093862..566a716e 100644 --- a/modules/plugins/treesitter/config.nix +++ b/modules/plugins/treesitter/config.nix @@ -5,13 +5,12 @@ ... }: let inherit (lib.modules) mkIf mkMerge; - inherit (lib.lists) optional optionals; + inherit (lib.lists) optionals; inherit (lib.nvim.binds) mkSetBinding addDescriptionsToMappings; inherit (lib.nvim.lua) toLuaObject; inherit (lib.nvim.dag) entryBefore entryAfter; cfg = config.vim.treesitter; - usingNvimCmp = config.vim.autocomplete.nvim-cmp.enable; self = import ./treesitter.nix {inherit pkgs lib;}; mappingDefinitions = self.options.vim.treesitter.mappings; @@ -19,9 +18,13 @@ in { config = mkIf cfg.enable { vim = { - startPlugins = ["nvim-treesitter"] ++ optional usingNvimCmp "cmp-treesitter"; + startPlugins = ["nvim-treesitter"]; + + autocomplete.nvim-cmp = { + sources = {treesitter = "[Treesitter]";}; + sourcePlugins = ["cmp-treesitter"]; + }; - autocomplete.nvim-cmp.sources = {treesitter = "[Treesitter]";}; treesitter.grammars = optionals cfg.addDefaultGrammars cfg.defaultGrammars; maps = { diff --git a/modules/plugins/utility/binds/cheatsheet/config.nix b/modules/plugins/utility/binds/cheatsheet/config.nix index 2848ddc2..2fb3e25b 100644 --- a/modules/plugins/utility/binds/cheatsheet/config.nix +++ b/modules/plugins/utility/binds/cheatsheet/config.nix @@ -4,15 +4,18 @@ ... }: let inherit (lib.modules) mkIf; - inherit (lib.nvim.dag) entryAnywhere; + inherit (lib.strings) optionalString; cfg = config.vim.binds.cheatsheet; in { config = mkIf cfg.enable { - vim.startPlugins = ["cheatsheet-nvim"]; + vim.lazy.plugins.cheatsheet-nvim = { + package = "cheatsheet-nvim"; + setupModule = "cheatsheet"; + setupOpts = {}; + cmd = ["Cheatsheet" "CheatsheetEdit"]; - vim.pluginRC.cheaetsheet-nvim = entryAnywhere '' - require('cheatsheet').setup({}) - ''; + before = optionalString config.vim.lazy.enable "require('lz.n').trigger_load('telescope')"; + }; }; } diff --git a/modules/plugins/utility/diffview/config.nix b/modules/plugins/utility/diffview/config.nix index 681a3053..a6458ed5 100644 --- a/modules/plugins/utility/diffview/config.nix +++ b/modules/plugins/utility/diffview/config.nix @@ -8,9 +8,14 @@ cfg = config.vim.utility.diffview-nvim; in { config = mkIf cfg.enable { - vim.startPlugins = [ - "diffview-nvim" - "plenary-nvim" - ]; + vim = { + startPlugins = ["plenary-nvim"]; + lazy.plugins.diffview-nvim = { + package = "diffview-nvim"; + cmd = ["DiffviewClose" "DiffviewFileHistory" "DiffviewFocusFiles" "DiffviewLog" "DiffviewOpen" "DiffviewRefresh" "DiffviewToggleFiles"]; + setupModule = "diffview"; + inherit (cfg) setupOpts; + }; + }; }; } diff --git a/modules/plugins/utility/diffview/diffview.nix b/modules/plugins/utility/diffview/diffview.nix index 74ddd574..793666dc 100644 --- a/modules/plugins/utility/diffview/diffview.nix +++ b/modules/plugins/utility/diffview/diffview.nix @@ -1,7 +1,9 @@ {lib, ...}: let inherit (lib.options) mkEnableOption; + inherit (lib.nvim.types) mkPluginSetupOption; in { options.vim.utility.diffview-nvim = { enable = mkEnableOption "diffview-nvim: cycle through diffs for all modified files for any git rev"; + setupOpts = mkPluginSetupOption "Fidget" {}; }; } diff --git a/modules/plugins/utility/icon-picker/config.nix b/modules/plugins/utility/icon-picker/config.nix index 405f6917..99e43044 100644 --- a/modules/plugins/utility/icon-picker/config.nix +++ b/modules/plugins/utility/icon-picker/config.nix @@ -4,20 +4,20 @@ ... }: let inherit (lib.modules) mkIf; - inherit (lib.nvim.dag) entryAnywhere; cfg = config.vim.utility.icon-picker; in { config = mkIf cfg.enable { - vim.startPlugins = [ - "icon-picker-nvim" - "dressing-nvim" - ]; + vim.startPlugins = ["dressing-nvim"]; - vim.pluginRC.icon-picker = entryAnywhere '' - require("icon-picker").setup({ - disable_legacy_commands = true - }) - ''; + vim.lazy.plugins.icon-picker-nvim = { + package = "icon-picker-nvim"; + setupModule = "icon-picker"; + setupOpts = { + disable_legacy_commands = true; + }; + + cmd = ["IconPickerInsert" "IconPickerNormal" "IconPickerYank"]; + }; }; } diff --git a/modules/plugins/utility/motion/leap/config.nix b/modules/plugins/utility/motion/leap/config.nix index 687ed24d..94a00c99 100644 --- a/modules/plugins/utility/motion/leap/config.nix +++ b/modules/plugins/utility/motion/leap/config.nix @@ -3,73 +3,59 @@ lib, ... }: let - inherit (lib.modules) mkIf mkMerge mkDefault; - inherit (lib.nvim.binds) mkBinding; - inherit (lib.nvim.dag) entryAnywhere; + inherit (lib.modules) mkIf mkDefault; + inherit (lib.nvim.binds) mkLznBinding; cfg = config.vim.utility.motion.leap; in { config = mkIf cfg.enable { - vim.startPlugins = [ - "leap-nvim" - "vim-repeat" - ]; + vim = { + startPlugins = ["vim-repeat"]; + lazy.plugins.leap-nvim = { + package = "leap-nvim"; + keys = [ + (mkLznBinding ["n" "o" "x"] cfg.mappings.leapForwardTo "(leap-forward-to)" "Leap forward to") + (mkLznBinding ["n" "o" "x"] cfg.mappings.leapBackwardTo "(leap-backward-to)" "Leap backward to") + (mkLznBinding ["n" "o" "x"] cfg.mappings.leapForwardTill "(leap-forward-till)" "Leap forward till") + (mkLznBinding ["n" "o" "x"] cfg.mappings.leapBackwardTill "(leap-backward-till)" "Leap backward till") + (mkLznBinding ["n" "o" "x"] cfg.mappings.leapFromWindow "(leap-from-window)" "Leap from window") + ]; - vim.maps.normal = mkMerge [ - (mkBinding cfg.mappings.leapForwardTo "(leap-forward-to)" "Leap forward to") - (mkBinding cfg.mappings.leapBackwardTo "(leap-backward-to)" "Leap backward to") - (mkBinding cfg.mappings.leapFromWindow "(leap-from-window)" "Leap from window") - ]; + after = '' + require('leap').opts = { + max_phase_one_targets = nil, + highlight_unlabeled_phase_one_targets = false, + max_highlighted_traversal_targets = 10, + case_sensitive = false, + equivalence_classes = { ' \t\r\n', }, + substitute_chars = {}, + safe_labels = { + "s", "f", "n", "u", "t", "/", + "S", "F", "N", "L", "H", "M", "U", "G", "T", "?", "Z" + }, + labels = { + "s", "f", "n", + "j", "k", "l", "h", "o", "d", "w", "e", "m", "b", + "u", "y", "v", "r", "g", "t", "c", "x", "/", "z", + "S", "F", "N", + "J", "K", "L", "H", "O", "D", "W", "E", "M", "B", + "U", "Y", "V", "R", "G", "T", "C", "X", "?", "Z" + }, + special_keys = { + repeat_search = '', + next_phase_one_target = '', + next_target = {'', ';'}, + prev_target = {'', ','}, + next_group = '', + prev_group = '', + multi_accept = '', + multi_revert = '', + }, + } + ''; + }; - vim.maps.operator = mkMerge [ - (mkBinding cfg.mappings.leapForwardTo "(leap-forward-to)" "Leap forward to") - (mkBinding cfg.mappings.leapBackwardTo "(leap-backward-to)" "Leap backward to") - (mkBinding cfg.mappings.leapForwardTill "(leap-forward-till)" "Leap forward till") - (mkBinding cfg.mappings.leapBackwardTill "(leap-backward-till)" "Leap backward till") - (mkBinding cfg.mappings.leapFromWindow "(leap-from-window)" "Leap from window") - ]; - - vim.maps.visualOnly = mkMerge [ - (mkBinding cfg.mappings.leapForwardTo "(leap-forward-to)" "Leap forward to") - (mkBinding cfg.mappings.leapBackwardTo "(leap-backward-to)" "Leap backward to") - (mkBinding cfg.mappings.leapForwardTill "(leap-forward-till)" "Leap forward till") - (mkBinding cfg.mappings.leapBackwardTill "(leap-backward-till)" "Leap backward till") - (mkBinding cfg.mappings.leapFromWindow "(leap-from-window)" "Leap from window") - ]; - - vim.binds.whichKey.register."s" = mkDefault "+Leap"; - - vim.pluginRC.leap-nvim = entryAnywhere '' - require('leap').opts = { - max_phase_one_targets = nil, - highlight_unlabeled_phase_one_targets = false, - max_highlighted_traversal_targets = 10, - case_sensitive = false, - equivalence_classes = { ' \t\r\n', }, - substitute_chars = {}, - safe_labels = { - "s", "f", "n", "u", "t", "/", - "S", "F", "N", "L", "H", "M", "U", "G", "T", "?", "Z" - }, - labels = { - "s", "f", "n", - "j", "k", "l", "h", "o", "d", "w", "e", "m", "b", - "u", "y", "v", "r", "g", "t", "c", "x", "/", "z", - "S", "F", "N", - "J", "K", "L", "H", "O", "D", "W", "E", "M", "B", - "U", "Y", "V", "R", "G", "T", "C", "X", "?", "Z" - }, - special_keys = { - repeat_search = '', - next_phase_one_target = '', - next_target = {'', ';'}, - prev_target = {'', ','}, - next_group = '', - prev_group = '', - multi_accept = '', - multi_revert = '', - }, - } - ''; + binds.whichKey.register."s" = mkDefault "+Leap"; + }; }; } diff --git a/modules/plugins/utility/surround/config.nix b/modules/plugins/utility/surround/config.nix index 4c98c865..7161cf6b 100644 --- a/modules/plugins/utility/surround/config.nix +++ b/modules/plugins/utility/surround/config.nix @@ -8,24 +8,47 @@ inherit (lib.nvim.lua) toLuaObject; cfg = config.vim.utility.surround; + mkLznKey = mode: key: { + inherit key mode; + }; in { config = mkIf cfg.enable { vim = { startPlugins = ["nvim-surround"]; pluginRC.surround = entryAnywhere "require('nvim-surround').setup(${toLuaObject cfg.setupOpts})"; - utility.surround.setupOpts.keymaps = mkIf cfg.useVendoredKeybindings { - insert = "z"; - insert_line = "Z"; - normal = "gz"; - normal_cur = "gZ"; - normal_line = "gzz"; - normal_cur_line = "gZZ"; - visual = "gz"; - visual_line = "gZ"; - delete = "gzd"; - change = "gzr"; - change_line = "gZR"; + lazy.plugins.nvim-surround = { + package = "nvim-surround"; + setupModule = "nvim-surround"; + inherit (cfg) setupOpts; + + keys = + [ + (mkLznKey ["i"] cfg.setupOpts.keymaps.insert) + (mkLznKey ["i"] cfg.setupOpts.keymaps.insert_line) + (mkLznKey ["x"] cfg.setupOpts.keymaps.visual) + (mkLznKey ["x"] cfg.setupOpts.keymaps.visual_line) + (mkLznKey ["n"] cfg.setupOpts.keymaps.normal) + (mkLznKey ["n"] cfg.setupOpts.keymaps.normal_cur) + (mkLznKey ["n"] cfg.setupOpts.keymaps.normal_line) + (mkLznKey ["n"] cfg.setupOpts.keymaps.normal_cur_line) + (mkLznKey ["n"] cfg.setupOpts.keymaps.delete) + (mkLznKey ["n"] cfg.setupOpts.keymaps.change) + (mkLznKey ["n"] cfg.setupOpts.keymaps.change_line) + ] + ++ map (mkLznKey ["n" "i" "v"]) [ + "(nvim-surround-insert)" + "(nvim-surround-insert-line)" + "(nvim-surround-normal)" + "(nvim-surround-normal-cur)" + "(nvim-surround-normal-line)" + "(nvim-surround-normal-cur-line)" + "(nvim-surround-visual)" + "(nvim-surround-visual-line)" + "(nvim-surround-delete)" + "(nvim-surround-change)" + "(nvim-surround-change-line)" + ]; }; }; }; diff --git a/modules/plugins/utility/surround/surround.nix b/modules/plugins/utility/surround/surround.nix index 7d006381..d74966af 100644 --- a/modules/plugins/utility/surround/surround.nix +++ b/modules/plugins/utility/surround/surround.nix @@ -1,7 +1,36 @@ -{lib, ...}: let +{ + lib, + config, + ... +}: let inherit (lib.options) mkOption; - inherit (lib.types) bool; + inherit (lib.types) bool str; inherit (lib.nvim.types) mkPluginSetupOption; + + cfg = config.vim.utility.surround; + vendoredKeybinds = { + insert = "z"; + insert_line = "Z"; + normal = "gz"; + normal_cur = "gZ"; + normal_line = "gzz"; + normal_cur_line = "gZZ"; + visual = "gz"; + visual_line = "gZ"; + delete = "gzd"; + change = "gzr"; + change_line = "gZR"; + }; + + mkKeymapOption = name: default: + mkOption { + description = "keymap for ${name}"; + type = str; + default = + if cfg.useVendoredKeybindings + then vendoredKeybinds.${name} + else default; + }; in { options.vim.utility.surround = { enable = mkOption { @@ -13,7 +42,21 @@ in { with nvim-leap. ''; }; - setupOpts = mkPluginSetupOption "nvim-surround" {}; + setupOpts = mkPluginSetupOption "nvim-surround" { + keymaps = { + insert = mkKeymapOption "insert" "s"; + insert_line = mkKeymapOption "insert_line" "S"; + normal = mkKeymapOption "normal" "ys"; + normal_cur = mkKeymapOption "normal_cur" "yss"; + normal_line = mkKeymapOption "normal_line" "yS"; + normal_cur_line = mkKeymapOption "normal_cur_line" "ySS"; + visual = mkKeymapOption "visual" "S"; + visual_line = mkKeymapOption "visual_line" "gS"; + delete = mkKeymapOption "delete" "ds"; + change = mkKeymapOption "change" "cs"; + change_line = mkKeymapOption "change_line" "cS"; + }; + }; useVendoredKeybindings = mkOption { type = bool; diff --git a/modules/plugins/utility/telescope/config.nix b/modules/plugins/utility/telescope/config.nix index 68af9645..61436279 100644 --- a/modules/plugins/utility/telescope/config.nix +++ b/modules/plugins/utility/telescope/config.nix @@ -1,63 +1,72 @@ { + options, config, - pkgs, lib, ... }: let - inherit (lib.modules) mkIf mkMerge; - inherit (lib.nvim.binds) addDescriptionsToMappings mkSetBinding; - inherit (lib.nvim.dag) entryAnywhere; - inherit (lib.nvim.binds) pushDownDefault; - inherit (lib.nvim.lua) toLuaObject; + inherit (lib.modules) mkIf; + inherit (lib.nvim.binds) addDescriptionsToMappings; + inherit (lib.strings) optionalString; + inherit (lib.lists) optionals; + inherit (lib.nvim.binds) pushDownDefault mkSetLznBinding; cfg = config.vim.telescope; - self = import ./telescope.nix {inherit pkgs lib;}; - mappingDefinitions = self.options.vim.telescope.mappings; + mappingDefinitions = options.vim.telescope.mappings; mappings = addDescriptionsToMappings cfg.mappings mappingDefinitions; in { config = mkIf cfg.enable { vim = { - startPlugins = [ - "telescope" - "plenary-nvim" - ]; + startPlugins = ["plenary-nvim"]; - maps.normal = mkMerge [ - (mkSetBinding mappings.findFiles " Telescope find_files") - (mkSetBinding mappings.liveGrep " Telescope live_grep") - (mkSetBinding mappings.buffers " Telescope buffers") - (mkSetBinding mappings.helpTags " Telescope help_tags") - (mkSetBinding mappings.open " Telescope") - (mkSetBinding mappings.resume " Telescope resume") + lazy.plugins.telescope = { + package = "telescope"; + setupModule = "telescope"; + inherit (cfg) setupOpts; + after = '' + local telescope = require("telescope") + ${optionalString config.vim.ui.noice.enable "telescope.load_extension('noice')"} + ${optionalString config.vim.notify.nvim-notify.enable "telescope.load_extension('notify')"} + ${optionalString config.vim.projects.project-nvim.enable "telescope.load_extension('projects')"} + ''; - (mkSetBinding mappings.gitCommits " Telescope git_commits") - (mkSetBinding mappings.gitBufferCommits " Telescope git_bcommits") - (mkSetBinding mappings.gitBranches " Telescope git_branches") - (mkSetBinding mappings.gitStatus " Telescope git_status") - (mkSetBinding mappings.gitStash " Telescope git_stash") + cmd = ["Telescope"]; - (mkIf config.vim.lsp.enable (mkMerge [ - (mkSetBinding mappings.lspDocumentSymbols " Telescope lsp_document_symbols") - (mkSetBinding mappings.lspWorkspaceSymbols " Telescope lsp_workspace_symbols") + keys = + [ + (mkSetLznBinding mappings.findFiles " Telescope find_files") + (mkSetLznBinding mappings.liveGrep " Telescope live_grep") + (mkSetLznBinding mappings.buffers " Telescope buffers") + (mkSetLznBinding mappings.helpTags " Telescope help_tags") + (mkSetLznBinding mappings.open " Telescope") - (mkSetBinding mappings.lspReferences " Telescope lsp_references") - (mkSetBinding mappings.lspImplementations " Telescope lsp_implementations") - (mkSetBinding mappings.lspDefinitions " Telescope lsp_definitions") - (mkSetBinding mappings.lspTypeDefinitions " Telescope lsp_type_definitions") - (mkSetBinding mappings.diagnostics " Telescope diagnostics") - ])) + (mkSetLznBinding mappings.gitCommits " Telescope git_commits") + (mkSetLznBinding mappings.gitBufferCommits " Telescope git_bcommits") + (mkSetLznBinding mappings.gitBranches " Telescope git_branches") + (mkSetLznBinding mappings.gitStatus " Telescope git_status") + (mkSetLznBinding mappings.gitStash " Telescope git_stash") + ] + ++ (optionals config.vim.lsp.enable [ + (mkSetLznBinding mappings.lspDocumentSymbols " Telescope lsp_document_symbols") + (mkSetLznBinding mappings.lspWorkspaceSymbols " Telescope lsp_workspace_symbols") - ( - mkIf config.vim.treesitter.enable - (mkSetBinding mappings.treesitter " Telescope treesitter") - ) - - ( - mkIf config.vim.projects.project-nvim.enable - (mkSetBinding mappings.findProjects " Telescope projects") - ) - ]; + (mkSetLznBinding mappings.lspReferences " Telescope lsp_references") + (mkSetLznBinding mappings.lspImplementations " Telescope lsp_implementations") + (mkSetLznBinding mappings.lspDefinitions " Telescope lsp_definitions") + (mkSetLznBinding mappings.lspTypeDefinitions " Telescope lsp_type_definitions") + (mkSetLznBinding mappings.diagnostics " Telescope diagnostics") + ]) + ++ ( + optionals config.vim.treesitter.enable [ + (mkSetLznBinding mappings.treesitter " Telescope treesitter") + ] + ) + ++ ( + optionals config.vim.projects.project-nvim.enable [ + (mkSetLznBinding mappings.findProjects "") + ] + ); + }; binds.whichKey.register = pushDownDefault { "f" = "+Telescope"; @@ -66,29 +75,6 @@ in { "fv" = "Telescope Git"; "fvc" = "Commits"; }; - - pluginRC.telescope = entryAnywhere '' - local telescope = require('telescope') - telescope.setup(${toLuaObject cfg.setupOpts}) - - ${ - if config.vim.ui.noice.enable - then "telescope.load_extension('noice')" - else "" - } - - ${ - if config.vim.notify.nvim-notify.enable - then "telescope.load_extension('notify')" - else "" - } - - ${ - if config.vim.projects.project-nvim.enable - then "telescope.load_extension('projects')" - else "" - } - ''; }; }; } diff --git a/modules/plugins/visuals/fidget/config.nix b/modules/plugins/visuals/fidget/config.nix index 3ae3b6b9..7c83cd96 100644 --- a/modules/plugins/visuals/fidget/config.nix +++ b/modules/plugins/visuals/fidget/config.nix @@ -4,16 +4,15 @@ ... }: let inherit (lib.modules) mkIf; - inherit (lib.nvim.lua) toLuaObject; - inherit (lib.nvim.dag) entryAnywhere; cfg = config.vim.visuals.fidget-nvim; in { config = mkIf cfg.enable { - vim.startPlugins = ["fidget-nvim"]; - - vim.pluginRC.fidget-nvim = entryAnywhere '' - require'fidget'.setup(${toLuaObject cfg.setupOpts}) - ''; + vim.lazy.plugins.fidget-nvim = { + package = "fidget-nvim"; + setupModule = "fidget"; + event = "LspAttach"; + inherit (cfg) setupOpts; + }; }; } diff --git a/modules/wrapper/lazy/config.nix b/modules/wrapper/lazy/config.nix new file mode 100644 index 00000000..01deeb0f --- /dev/null +++ b/modules/wrapper/lazy/config.nix @@ -0,0 +1,108 @@ +{ + lib, + config, + ... +}: let + inherit (builtins) toJSON typeOf head length filter concatLists concatStringsSep; + inherit (lib.attrsets) mapAttrsToList; + inherit (lib.modules) mkIf mkMerge; + inherit (lib.generators) mkLuaInline; + inherit (lib.strings) optionalString; + inherit (lib.nvim.lua) toLuaObject; + inherit (lib.nvim.dag) entryBefore entryAfter; + cfg = config.vim.lazy; + + toLuaLznKeySpec = keySpec: + (removeAttrs keySpec ["key" "lua" "action"]) + // { + "@1" = keySpec.key; + "@2" = + if keySpec.lua + then mkLuaInline keySpec.action + else keySpec.action; + }; + + toLuaLznSpec = name: spec: + (removeAttrs spec ["package" "setupModule" "setupOpts" "keys"]) + // { + "@1" = name; + before = + if spec.before != null + then + mkLuaInline '' + function() + ${spec.before} + end + '' + else null; + + after = + if spec.setupModule == null && spec.after == null + then null + else + mkLuaInline '' + function() + ${ + optionalString (spec.setupModule != null) + "require(${toJSON spec.setupModule}).setup(${toLuaObject spec.setupOpts})" + } + ${optionalString (spec.after != null) spec.after} + end + ''; + + keys = + if typeOf spec.keys == "list" && length spec.keys > 0 && typeOf (head spec.keys) == "set" + then map toLuaLznKeySpec (filter (keySpec: keySpec.key != null) spec.keys) + # empty list or str or (listOf str) + else spec.keys; + }; + lznSpecs = mapAttrsToList toLuaLznSpec cfg.plugins; + + pluginPackages = mapAttrsToList (_: plugin: plugin.package) cfg.plugins; + + specToNotLazyConfig = _: spec: '' + do + ${optionalString (spec.before != null) spec.before} + ${optionalString (spec.setupModule != null) + "require(${toJSON spec.setupModule}).setup(${toLuaObject spec.setupOpts})"} + ${optionalString (spec.after != null) spec.after} + end + ''; + + specToKeymaps = _: spec: + if typeOf spec.keys == "list" + then map (x: removeAttrs x ["ft"]) (filter (lznKey: lznKey.action != null && lznKey.ft == null) spec.keys) + else if spec.keys == null || typeOf spec.keys == "string" + then [] + else [spec.keys]; + + notLazyConfig = + concatStringsSep "\n" + (mapAttrsToList specToNotLazyConfig cfg.plugins); + + beforeAllJoined = + concatStringsSep "\n" + (filter (x: x != null) (mapAttrsToList (_: spec: spec.beforeAll) cfg.plugins)); +in { + config.vim = mkMerge [ + (mkIf cfg.enable { + startPlugins = ["lz-n" "lzn-auto-require"]; + + optPlugins = pluginPackages; + + lazy.builtLazyConfig = '' + require('lz.n').load(${toLuaObject lznSpecs}) + ${optionalString cfg.enableLznAutoRequire "require('lzn-auto-require').enable()"} + ''; + }) + + (mkIf (!cfg.enable) { + startPlugins = pluginPackages; + lazy.builtLazyConfig = '' + ${beforeAllJoined} + ${notLazyConfig} + ''; + keymaps = concatLists (mapAttrsToList specToKeymaps cfg.plugins); + }) + ]; +} diff --git a/modules/wrapper/lazy/default.nix b/modules/wrapper/lazy/default.nix new file mode 100644 index 00000000..671516b0 --- /dev/null +++ b/modules/wrapper/lazy/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./lazy.nix + ./config.nix + ]; +} diff --git a/modules/wrapper/lazy/lazy.nix b/modules/wrapper/lazy/lazy.nix new file mode 100644 index 00000000..5b2c53d1 --- /dev/null +++ b/modules/wrapper/lazy/lazy.nix @@ -0,0 +1,237 @@ +{lib, ...}: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.types) enum listOf submodule nullOr str bool int attrsOf anything either oneOf lines; + inherit (lib.nvim.types) pluginType; + inherit (lib.nvim.config) mkBool; + + lznKeysSpec = submodule { + options = { + key = mkOption { + type = nullOr str; + description = "Key to bind to. If key is null this entry is ignored."; + }; + + action = mkOption { + type = nullOr str; + default = null; + description = "Action to trigger."; + }; + lua = mkBool false '' + If true, `action` is considered to be lua code. + Thus, it will not be wrapped in `""`. + ''; + + desc = mkOption { + description = "Description of the key map"; + type = nullOr str; + default = null; + }; + + ft = mkOption { + description = "TBD"; + type = nullOr (listOf str); + default = null; + }; + + mode = mkOption { + description = "Modes to bind in"; + type = either str (listOf str); + default = ["n" "x" "s" "o"]; + }; + + silent = mkBool true "Whether this mapping should be silent. Equivalent to adding to a map."; + nowait = mkBool false "Whether to wait for extra input on ambiguous mappings. Equivalent to adding to a map."; + script = mkBool false "Equivalent to adding