From 3a8d4fee35642ee326f5fea8ddb7aacd1176f23e Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Sat, 29 Jun 2024 08:26:56 +0100 Subject: [PATCH] plugins/cmp: refactor source->plugin association Introduce the internal option `cmpSourcePlugins` where plugins can register their nvim-cmp source name association. --- plugins/completion/cmp/auto-enable.nix | 90 +++++++++++++++++++ plugins/completion/cmp/cmp-helpers.nix | 50 ++--------- plugins/completion/cmp/default.nix | 32 +------ plugins/completion/cmp/sources/default.nix | 7 +- tests/fetch-tests.nix | 1 - .../plugins/completion/cmp-all-sources.nix | 57 +++++++----- 6 files changed, 137 insertions(+), 100 deletions(-) create mode 100644 plugins/completion/cmp/auto-enable.nix diff --git a/plugins/completion/cmp/auto-enable.nix b/plugins/completion/cmp/auto-enable.nix new file mode 100644 index 00000000..b4365c36 --- /dev/null +++ b/plugins/completion/cmp/auto-enable.nix @@ -0,0 +1,90 @@ +{ + lib, + helpers, + config, + ... +}: +with lib; +let + cfg = config.plugins.cmp; + + extractSources = { sources, ... }: if isList sources then sources else [ ]; + + # Collect the names of the sources provided by the user + # ["foo" "bar"] + enabledSources = + pipe + [ + # cfg.setup.sources + (extractSources cfg.settings) + # cfg.filetype..sources + (mapAttrsToList (_: extractSources) cfg.filetype) + # cfg.cmdline..sources + (mapAttrsToList (_: extractSources) cfg.cmdline) + ] + [ + flatten + (map (getAttr "name")) + unique + ]; +in +{ + options = { + # Note: this option must be outside of `plugins` to avoid infinite recursion + cmpSourcePlugins = mkOption { + type = with types; attrsOf str; + default = { }; + description = '' + Internal option used to associate nvim-cmp source names with nixvim plugin module names. + + Maps ` = ` where _plugin-name_ is the module name: `plugins..enable`. + ''; + example = { + foo = "cmp-foo"; + bar = "cmp-bar"; + }; + internal = true; + visible = false; + }; + + plugins.cmp.autoEnableSources = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Scans the sources array and enable the corresponding plugins if they are known to nixvim. + ''; + }; + }; + + config = mkIf (cfg.enable && cfg.autoEnableSources) (mkMerge [ + { + warnings = + # TODO: expand this warning to ft & cmd sources lists and `showDefs` the offending definitions + optional (helpers.nixvimTypes.isRawType cfg.settings.sources) '' + Nixvim (plugins.cmp): You have enabled `autoEnableSources` that tells Nixvim to automatically + enable the source plugins with respect to the list of sources provided in `settings.sources`. + However, the latter is proveded as a raw lua string which is not parseable by Nixvim. + + If you want to keep using raw lua for defining your sources: + - Ensure you enable the relevant plugins manually in your configuration; + - Dismiss this warning by explicitly setting `autoEnableSources` to `false`; + ''; + + # If the user has enabled the `foo` and `bar` sources, then `plugins` will look like: + # { + # cmp-foo.enable = true; + # cmp-bar.enable = true; + # } + plugins = mapAttrs' (source: name: { + inherit name; + value.enable = mkIf (elem source enabledSources) true; + }) config.cmpSourcePlugins; + } + { + plugins.lsp.capabilities = mkIf (elem "nvim_lsp" enabledSources) '' + capabilities = vim.tbl_deep_extend("force", capabilities, require('cmp_nvim_lsp').default_capabilities()) + ''; + } + ]); +} diff --git a/plugins/completion/cmp/cmp-helpers.nix b/plugins/completion/cmp/cmp-helpers.nix index 4fb88c5e..47889791 100644 --- a/plugins/completion/cmp/cmp-helpers.nix +++ b/plugins/completion/cmp/cmp-helpers.nix @@ -7,10 +7,11 @@ }: with helpers.vim-plugin; with lib; -rec { +{ mkCmpSourcePlugin = { name, + sourceName, extraPlugins ? [ ], useDefaultPackage ? true, ... @@ -20,49 +21,8 @@ rec { extraPlugins = extraPlugins ++ (lists.optional useDefaultPackage pkgs.vimPlugins.${name}); maintainers = [ maintainers.GaetanLepage ]; + + # Register the source -> plugin name association + imports = [ { cmpSourcePlugins.${sourceName} = name; } ]; }; - - extractSourcesFromOptionValue = sources: if isList sources then sources else [ ]; - - autoInstallSourcePluginsModule = - cfg: - let - # cfg.setup.sources - setupSources = extractSourcesFromOptionValue cfg.settings.sources; - # cfg.filetype..sources - filetypeSources = mapAttrsToList ( - _: filetypeConfig: extractSourcesFromOptionValue filetypeConfig.sources - ) cfg.filetype; - # cfg.cmdline..sources - cmdlineSources = mapAttrsToList ( - _: cmdlineConfig: extractSourcesFromOptionValue cmdlineConfig.sources - ) cfg.cmdline; - - # [{name = "foo";} {name = "bar"; x = 42;} ...] - allSources = flatten (setupSources ++ filetypeSources ++ cmdlineSources); - - # Take only the names from the sources provided by the user - # ["foo" "bar"] - foundSources = lists.unique (map (source: source.name) allSources); - - # If the user has enabled the `foo` and `bar` sources, this attrs will look like: - # { - # cmp-foo.enable = true; - # cmp-bar.enable = true; - # } - attrsEnabled = mapAttrs' (sourceName: pluginName: { - name = pluginName; - value.enable = mkIf (elem sourceName foundSources) true; - }) (import ./sources.nix); - - lspCapabilities = mkIf (elem "nvim_lsp" foundSources) { - lsp.capabilities = '' - capabilities = vim.tbl_deep_extend("force", capabilities, require('cmp_nvim_lsp').default_capabilities()) - ''; - }; - in - mkMerge [ - (mkIf cfg.autoEnableSources attrsEnabled) - lspCapabilities - ]; } diff --git a/plugins/completion/cmp/default.nix b/plugins/completion/cmp/default.nix index ffd0ed96..45aa74e1 100644 --- a/plugins/completion/cmp/default.nix +++ b/plugins/completion/cmp/default.nix @@ -16,42 +16,22 @@ helpers.neovim-plugin.mkNeovimPlugin config { maintainers = [ maintainers.GaetanLepage ]; - # Introduced on 2024 February 21 - # TODO: remove ~June 2024 imports = [ + # Introduced on 2024 February 21 + # TODO: remove ~June 2024 ./deprecations.nix + ./auto-enable.nix ./sources ]; deprecateExtraOptions = true; + inherit (cmpOptions) settingsOptions settingsExample; extraOptions = { - autoEnableSources = mkOption { - type = types.bool; - default = true; - description = '' - Scans the sources array and installs the plugins if they are known to nixvim. - ''; - }; - inherit (cmpOptions) filetype cmdline; }; - inherit (cmpOptions) settingsOptions settingsExample; - callSetup = false; extraConfig = cfg: { - warnings = - optional (cfg.autoEnableSources && (helpers.nixvimTypes.isRawType cfg.settings.sources)) - '' - Nixvim (plugins.cmp): You have enabled `autoEnableSources` that tells Nixvim to automatically - enable the source plugins with respect to the list of sources provided in `settings.sources`. - However, the latter is proveded as a raw lua string which is not parseable by Nixvim. - - If you want to keep using raw lua for defining your sources: - - Ensure you enable the relevant plugins manually in your configuration; - - Dismiss this warning by explicitly setting `autoEnableSources` to `false`; - ''; - extraConfigLua = '' local cmp = require('cmp') @@ -68,9 +48,5 @@ helpers.neovim-plugin.mkNeovimPlugin config { cmdtype: settings: "cmp.setup.cmdline('${cmdtype}', ${helpers.toLuaObject settings})\n" ) cfg.cmdline )); - - # If autoEnableSources is set to true, figure out which are provided by the user - # and enable the corresponding plugins. - plugins = (import ./cmp-helpers.nix args).autoInstallSourcePluginsModule cfg; }; } diff --git a/plugins/completion/cmp/sources/default.nix b/plugins/completion/cmp/sources/default.nix index 662a3738..448834fa 100644 --- a/plugins/completion/cmp/sources/default.nix +++ b/plugins/completion/cmp/sources/default.nix @@ -15,8 +15,11 @@ let pkgs ; }; - cmpSourcesPluginNames = attrValues (import ../sources.nix); - pluginModules = map (name: cmpLib.mkCmpSourcePlugin { inherit name; }) cmpSourcesPluginNames; + + cmpSourcesPluginNames = import ../sources.nix; + pluginModules = mapAttrsToList ( + sourceName: name: cmpLib.mkCmpSourcePlugin { inherit sourceName name; } + ) cmpSourcesPluginNames; in { # For extra cmp plugins diff --git a/tests/fetch-tests.nix b/tests/fetch-tests.nix index 9b52c155..7cb5229e 100644 --- a/tests/fetch-tests.nix +++ b/tests/fetch-tests.nix @@ -57,7 +57,6 @@ let inherit pkgs lib helpers; config = { }; }; - cmp-sources = import ../plugins/completion/cmp/sources.nix; }; inherit namespace; } diff --git a/tests/test-sources/plugins/completion/cmp-all-sources.nix b/tests/test-sources/plugins/completion/cmp-all-sources.nix index 7677d4e7..f3690324 100644 --- a/tests/test-sources/plugins/completion/cmp-all-sources.nix +++ b/tests/test-sources/plugins/completion/cmp-all-sources.nix @@ -1,30 +1,39 @@ -{ pkgs, cmp-sources, ... }: +{ pkgs, ... }: { all-sources = { - plugins = { - copilot-lua = { - enable = true; + module = + { config, ... }: + { + plugins = { + copilot-lua = { + enable = true; - panel.enabled = false; - suggestion.enabled = false; + panel.enabled = false; + suggestion.enabled = false; + }; + + cmp = { + enable = true; + settings.sources = + with pkgs.lib; + let + disabledSources = [ + # We do not provide the required HF_API_KEY environment variable. + "cmp_ai" + ] ++ optional (pkgs.stdenv.hostPlatform.system == "aarch64-linux") "cmp_tabnine"; + in + pipe config.cmpSourcePlugins [ + # All known source names + attrNames + # Filter out disabled sources + (filter (name: !(elem name disabledSources))) + # Convert names to source attributes + (map (name: { + inherit name; + })) + ]; + }; + }; }; - - cmp = { - enable = true; - settings.sources = - with pkgs.lib; - let - disabledSources = [ - # We do not provide the required HF_API_KEY environment variable. - "cmp_ai" - ] ++ optional (pkgs.stdenv.hostPlatform.system == "aarch64-linux") "cmp_tabnine"; - - filterFunc = sourceName: !(elem sourceName disabledSources); - - sourceNames = filter filterFunc (attrNames cmp-sources); - in - map (sourceName: { name = sourceName; }) sourceNames; - }; - }; }; }