diff --git a/docs/manual/configuring/dag-entries.md b/docs/manual/configuring/dag-entries.md index 402cde6..32dd4c6 100644 --- a/docs/manual/configuring/dag-entries.md +++ b/docs/manual/configuring/dag-entries.md @@ -15,9 +15,11 @@ entries in nvf: 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, +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 7c80215..8531aa9 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 d5f050a..496b945 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 34a2243..2d73a3e 100644 --- a/flake.lock +++ b/flake.lock @@ -876,6 +876,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": { @@ -1597,6 +1630,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": { @@ -1958,6 +2007,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", @@ -2003,6 +2054,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 d12bdc5..4de493e 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 8c9e9a6..298cd30 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 6a95080..6306da9 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 1204e43..784c413 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 923a0c6..9f92d14 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 61a9171..76fd813 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 e228d92..0fde788 100644 --- a/modules/plugins/comments/comment-nvim/config.nix +++ b/modules/plugins/comments/comment-nvim/config.nix @@ -3,9 +3,8 @@ 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;}; @@ -14,35 +13,30 @@ 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 5d20242..27d0bfb 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')"} + require("lz.n").trigger_load("cmp-path") + local cmp = require("cmp") + cmp.setup(${toLuaObject cfg.setupOpts}) + + ${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 + 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 })"; - ${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 860a1c3..8246e71 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 358d7c8..7e9e8f7 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 3fab33a..5a69949 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 be67df1..13da035 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 b97b1e4..30cc680 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 52dc15b..841e28b 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,7 @@ in { end local capabilities = vim.lsp.protocol.make_client_capabilities() - ${optionalString usingNvimCmp "capabilities = require('cmp_nvim_lsp').default_capabilities()"} + -- ${optionalString usingNvimCmp "capabilities = require('cmp_nvim_lsp').default_capabilities()"} ''; }; }; diff --git a/modules/plugins/lsp/trouble/config.nix b/modules/plugins/lsp/trouble/config.nix index dd853e3..cae0c7a 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 bd16c67..04bd506 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 541fd0f..927b21f 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 07851e4..d96e480 100644 --- a/modules/plugins/terminal/toggleterm/config.nix +++ b/modules/plugins/terminal/toggleterm/config.nix @@ -4,38 +4,30 @@ ... }: let inherit (builtins) toJSON; - inherit (lib.lists) optionals; - inherit (lib.modules) mkIf mkMerge; + inherit (lib.strings) optionalString; + inherit (lib.modules) mkIf; inherit (lib.meta) getExe; - inherit (lib.nvim.binds) mkBinding; - inherit (lib.nvim.dag) entryAnywhere entryAfter; - inherit (lib.nvim.lua) toLuaObject; + inherit (lib.nvim.binds) mkLznBinding; cfg = config.vim.terminal.toggleterm; + lazygitMapDesc = "Open lazygit [toggleterm]"; in { - config = mkMerge [ - ( - mkIf cfg.enable { - vim = { - startPlugins = [ - "toggleterm-nvim" - ]; - - 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 + 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") + { + key = cfg.lazygit.mappings.open; + desc = lazygitMapDesc; + } ]; - 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', ${toJSON cfg.lazygit.mappings.open}, function() lazygit:toggle() end, {silent = true, noremap = true, desc = '${lazygitMapDesc}'}) ''; - } - ) - ]; + }; + }; + }; } diff --git a/modules/plugins/treesitter/config.nix b/modules/plugins/treesitter/config.nix index ae09386..e863d04 100644 --- a/modules/plugins/treesitter/config.nix +++ b/modules/plugins/treesitter/config.nix @@ -5,7 +5,7 @@ ... }: 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; @@ -19,9 +19,24 @@ in { config = mkIf cfg.enable { vim = { - startPlugins = ["nvim-treesitter"] ++ optional usingNvimCmp "cmp-treesitter"; + startPlugins = ["nvim-treesitter"]; + + lazy.plugins = { + cmp-treesitter = mkIf usingNvimCmp { + package = "cmp-treesitter"; + after = '' + local path = vim.fn.globpath(vim.o.packpath, 'pack/*/opt/cmp-treesitter') + require("rtp_nvim").source_after_plugin_dir(path) + ''; + }; + nvim-cmp.after = mkIf usingNvimCmp "require('lz.n').trigger_load('cmp-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 2848ddc..2fb3e25 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 681a305..a6458ed 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 74ddd57..793666d 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 405f691..99e4304 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 687ed24..94a00c9 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 4c98c86..4ce15ca 100644 --- a/modules/plugins/utility/surround/config.nix +++ b/modules/plugins/utility/surround/config.nix @@ -8,25 +8,48 @@ inherit (lib.nvim.lua) toLuaObject; 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"; + }; + 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 = + map (mkLznKey ["i"]) (with vendoredKeybinds; [insert insert_line]) + ++ map (mkLznKey ["x"]) (with vendoredKeybinds; [visual visual_line]) + ++ map (mkLznKey ["n"]) (with vendoredKeybinds; [ + normal + normal_cur + normal_line + normal_cur_line + delete + change + change_line + ]); }; + + utility.surround.setupOpts.keymaps = mkIf cfg.useVendoredKeybindings vendoredKeybinds; }; }; } diff --git a/modules/plugins/utility/telescope/config.nix b/modules/plugins/utility/telescope/config.nix index 68af964..d42e1bb 100644 --- a/modules/plugins/utility/telescope/config.nix +++ b/modules/plugins/utility/telescope/config.nix @@ -1,63 +1,73 @@ { + 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; + # FIXME: how do I deal with extensions? set all as deps? + 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 +76,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 3ae3b6b..7c83cd9 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 0000000..01deeb0 --- /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 0000000..fa40127 --- /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 0000000..5b2c53d --- /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