diff --git a/modules/default.nix b/modules/default.nix index 7b2c2c18b1..739a30db84 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -19,6 +19,7 @@ ./lua-loader.nix ./opts.nix ./output.nix + ./performance.nix ./plugins.nix ]; } diff --git a/modules/performance.nix b/modules/performance.nix new file mode 100644 index 0000000000..db0953d452 --- /dev/null +++ b/modules/performance.nix @@ -0,0 +1,63 @@ +{ lib, ... }: +let + inherit (lib) types; +in +{ + options.performance = { + combinePlugins = { + enable = lib.mkEnableOption "combinePlugins" // { + description = '' + Whether to enable EXPERIMENTAL option to combine all plugins + into a single plugin pack. It can significantly reduce startup time, + but all your plugins must have unique filenames and doc tags. + Any collision will result in a build failure. To avoid collisions + you can add your plugin to the `standalonePlugins` option. + Only standard neovim runtime directories are linked to the combined plugin. + If some of your plugins contain important files outside of standard + directories, add these paths to `pathsToLink` option. + ''; + }; + pathsToLink = lib.mkOption { + type = with types; listOf str; + default = [ ]; + example = [ "/data" ]; + description = "List of paths to link into a combined plugin pack."; + }; + standalonePlugins = lib.mkOption { + type = with types; listOf (either str package); + default = [ ]; + example = [ "nvim-treesitter" ]; + description = "List of plugins (names or packages) to exclude from plugin pack."; + }; + }; + }; + + config.performance = { + # Set option value with default priority so that values are appended by default + combinePlugins.pathsToLink = [ + # :h rtp + "/autoload" + "/colors" + "/compiler" + "/doc" + "/ftplugin" + "/indent" + "/keymap" + "/lang" + "/lua" + "/pack" + "/parser" + "/plugin" + "/queries" + "/rplugin" + "/spell" + "/syntax" + "/tutor" + "/after" + # ftdetect + "/ftdetect" + # plenary.nvim + "/data/plenary/filetypes" + ]; + }; +} diff --git a/modules/top-level/files/default.nix b/modules/top-level/files/default.nix index c8a3d24840..c9ec06f828 100644 --- a/modules/top-level/files/default.nix +++ b/modules/top-level/files/default.nix @@ -93,5 +93,8 @@ in ] ) extraFiles} ''; + + # Never combine user files with the rest of the plugins + performance.combinePlugins.standalonePlugins = [ config.filesPlugin ]; }; } diff --git a/modules/top-level/output.nix b/modules/top-level/output.nix index bd62d2174f..6f70876099 100644 --- a/modules/top-level/output.nix +++ b/modules/top-level/output.nix @@ -5,7 +5,10 @@ helpers, ... }: -with lib; +let + inherit (lib) types mkOption; + inherit (lib) optional optionalString optionalAttrs; +in { options = { viAlias = mkOption { @@ -71,15 +74,106 @@ with lib; config = let - defaultPlugin = { - plugin = null; - config = ""; - optional = false; - }; - - normalizedPlugins = map ( - x: defaultPlugin // (if x ? plugin then x else { plugin = x; }) - ) config.extraPlugins; + # Plugin normalization + normalize = + p: + let + defaultPlugin = { + plugin = null; + config = null; + optional = false; + }; + in + defaultPlugin // (if p ? plugin then p else { plugin = p; }); + normalizePluginList = plugins: map normalize plugins; + + # Normalized plugin list + normalizedPlugins = normalizePluginList config.extraPlugins; + + # Plugin list extended with dependencies + allPlugins = + let + pluginWithItsDeps = + p: [ p ] ++ builtins.concatMap pluginWithItsDeps (normalizePluginList p.plugin.dependencies or [ ]); + in + lib.unique (builtins.concatMap pluginWithItsDeps normalizedPlugins); + + # Remove dependencies from all plugins in a list + removeDependencies = ps: map (p: p // { plugin = removeAttrs p.plugin [ "dependencies" ]; }) ps; + + # Separated start and opt plugins + partitionedOptStartPlugins = builtins.partition (p: p.optional) allPlugins; + startPlugins = partitionedOptStartPlugins.wrong; + # Remove opt plugin dependencies since they are already available in start plugins + optPlugins = removeDependencies partitionedOptStartPlugins.right; + + # Test if plugin shouldn't be included in plugin pack + isStandalone = + p: + builtins.elem p.plugin config.performance.combinePlugins.standalonePlugins + || builtins.elem (lib.getName p.plugin) config.performance.combinePlugins.standalonePlugins; + + # Separated standalone and combined start plugins + partitionedStandaloneStartPlugins = builtins.partition isStandalone startPlugins; + toCombinePlugins = partitionedStandaloneStartPlugins.wrong; + # Remove standalone plugin dependencies since they are already available in start plugins + standaloneStartPlugins = removeDependencies partitionedStandaloneStartPlugins.right; + + # Combine start plugins into a single pack + pluginPack = + let + # Every plugin has its own generated help tags (doc/tags) + # Remove them to avoid collisions, new help tags + # will be generate for the entire pack later on + overriddenPlugins = map ( + plugin: + plugin.plugin.overrideAttrs (prev: { + nativeBuildInputs = lib.remove pkgs.vimUtils.vimGenDocHook prev.nativeBuildInputs or [ ]; + configurePhase = '' + ${prev.configurePhase or ""} + rm -vf doc/tags''; + }) + ) toCombinePlugins; + + # Python3 dependencies + python3Dependencies = + let + deps = map (p: p.plugin.python3Dependencies or (_: [ ])) toCombinePlugins; + in + ps: builtins.concatMap (f: f ps) deps; + + # Combined plugin + combinedPlugin = pkgs.vimUtils.toVimPlugin ( + pkgs.buildEnv { + name = "plugin-pack"; + paths = overriddenPlugins; + inherit (config.performance.combinePlugins) pathsToLink; + # Remove empty directories and activate vimGenDocHook + postBuild = '' + find $out -type d -empty -delete + runHook preFixup + ''; + passthru = { + inherit python3Dependencies; + }; + } + ); + + # Combined plugin configs + combinedConfig = builtins.concatStringsSep "\n" ( + builtins.concatMap (x: lib.optional (x.config != null && x.config != "") x.config) toCombinePlugins + ); + in + normalize { + plugin = combinedPlugin; + config = combinedConfig; + }; + + # Combined plugins + combinedPlugins = [ pluginPack ] ++ standaloneStartPlugins ++ optPlugins; + + # Plugins to use in finalPackage + plugins = if config.performance.combinePlugins.enable then combinedPlugins else normalizedPlugins; neovimConfig = pkgs.neovimUtils.makeNeovimConfig ( { @@ -92,15 +186,15 @@ with lib; withNodeJs ; # inherit customRC; - plugins = normalizedPlugins; + inherit plugins; } # Necessary to make sure the runtime path is set properly in NixOS 22.05, # or more generally before the commit: # cda1f8ae468 - neovim: pass packpath via the wrapper - // optionalAttrs (functionArgs pkgs.neovimUtils.makeNeovimConfig ? configure) { + // optionalAttrs (lib.functionArgs pkgs.neovimUtils.makeNeovimConfig ? configure) { configure.packages = { nixvim = { - start = map (x: x.plugin) normalizedPlugins; + start = map (x: x.plugin) plugins; opt = [ ]; }; }; @@ -115,7 +209,9 @@ with lib; init = helpers.writeLua "init.lua" customRC; extraWrapperArgs = builtins.concatStringsSep " " ( - (optional (config.extraPackages != [ ]) ''--prefix PATH : "${makeBinPath config.extraPackages}"'') + (optional ( + config.extraPackages != [ ] + ) ''--prefix PATH : "${lib.makeBinPath config.extraPackages}"'') ++ (optional config.wrapRc ''--add-flags -u --add-flags "${init}"'') ); diff --git a/plugins/languages/treesitter/treesitter.nix b/plugins/languages/treesitter/treesitter.nix index 497d98bc07..01257f01a4 100644 --- a/plugins/languages/treesitter/treesitter.nix +++ b/plugins/languages/treesitter/treesitter.nix @@ -328,5 +328,10 @@ helpers.neovim-plugin.mkNeovimPlugin config { foldmethod = mkDefault "expr"; foldexpr = mkDefault "nvim_treesitter#foldexpr()"; }; + + # Since https://github.com/NixOS/nixpkgs/pull/321550 upstream queries are added + # to grammar plugins. Exclude nvim-treesitter itself from combining to avoid + # collisions with grammar's queries + performance.combinePlugins.standalonePlugins = [ cfg.package ]; }; } diff --git a/plugins/telescope/default.nix b/plugins/telescope/default.nix index f0322c6340..706a9320b0 100644 --- a/plugins/telescope/default.nix +++ b/plugins/telescope/default.nix @@ -112,6 +112,9 @@ helpers.neovim-plugin.mkNeovimPlugin config { require('telescope').load_extension(extension) end ''; + + # planets picker requires files in data/memes/planets + performance.combinePlugins.pathsToLink = [ "/data/memes/planets" ]; }; settingsOptions = { diff --git a/plugins/telescope/extensions/fzf-native.nix b/plugins/telescope/extensions/fzf-native.nix index 8742c639b7..d159b223f8 100644 --- a/plugins/telescope/extensions/fzf-native.nix +++ b/plugins/telescope/extensions/fzf-native.nix @@ -52,4 +52,9 @@ override_file_sorter = false; case_mode = "ignore_case"; }; + + extraConfig = cfg: { + # Native library is in build/libfzf.so + performance.combinePlugins.pathsToLink = [ "/build" ]; + }; } diff --git a/plugins/telescope/extensions/fzy-native.nix b/plugins/telescope/extensions/fzy-native.nix index 602d8bb2f8..744d1a767a 100644 --- a/plugins/telescope/extensions/fzy-native.nix +++ b/plugins/telescope/extensions/fzy-native.nix @@ -38,4 +38,9 @@ override_file_sorter = true; override_generic_sorter = false; }; + + extraConfig = cfg: { + # fzy-native itself is in deps directory + performance.combinePlugins.pathsToLink = [ "/deps/fzy-lua-native" ]; + }; } diff --git a/tests/test-sources/modules/performance/combine-plugins.nix b/tests/test-sources/modules/performance/combine-plugins.nix new file mode 100644 index 0000000000..6290bdfe0a --- /dev/null +++ b/tests/test-sources/modules/performance/combine-plugins.nix @@ -0,0 +1,387 @@ +{ pkgs, ... }: +let + inherit (pkgs) lib; + + # Count plugins of given type excluding 'filesPlugin' + pluginCount = + pkg: filesPlugin: type: + builtins.length (builtins.filter (p: p != filesPlugin) pkg.packpathDirs.myNeovimPackages.${type}); +in +{ + # Test basic functionality + default.module = + { config, ... }: + { + performance.combinePlugins.enable = true; + extraPlugins = with pkgs.vimPlugins; [ + nvim-lspconfig + nvim-treesitter + ]; + extraConfigLuaPost = '' + -- Plugins are loadable + require("lspconfig") + require("nvim-treesitter") + + -- No separate plugin entries in nvim_list_runtime_paths + assert(not vim.iter(vim.api.nvim_list_runtime_paths()):any(function(entry) + return entry:find("treesitter") or entry:find("lspconfig") + end), "separate plugins are found in runtime") + + -- Help tags are generated + assert(vim.fn.getcompletion("lspconfig", "help")[1], "no help tags for nvim-lspconfig") + assert(vim.fn.getcompletion("nvim-treesitter", "help")[1], "no help tags for nvim-treesitter") + ''; + assertions = [ + { + assertion = pluginCount config.finalPackage config.filesPlugin "start" == 1; + message = "More than one plugin is defined in packpathDirs, expected one plugin pack."; + } + ]; + }; + + # Test disabled option + disabled.module = + { config, ... }: + { + performance.combinePlugins.enable = false; + extraPlugins = with pkgs.vimPlugins; [ + nvim-lspconfig + nvim-treesitter + ]; + assertions = [ + { + assertion = pluginCount config.finalPackage config.filesPlugin "start" >= 2; + message = "Only one plugin is defined in packpathDirs, expected at least two."; + } + ]; + }; + + # Test that plugin dependencies are handled + dependencies.module = + { config, ... }: + { + performance.combinePlugins.enable = true; + extraPlugins = with pkgs.vimPlugins; [ + # Depends on nvim-cmp + cmp-dictionary + # Depends on telescope-nvim which itself depends on plenary-nvim + telescope-undo-nvim + ]; + extraConfigLuaPost = '' + -- Plugins and its dependencies are loadable + require("cmp_dictionary") + require("cmp") + require("telescope-undo") + require("telescope") + require("plenary") + ''; + assertions = [ + { + assertion = pluginCount config.finalPackage config.filesPlugin "start" == 1; + message = "More than one plugin is defined in packpathDirs."; + } + ]; + }; + + # Test that pathsToLink option works + paths-to-link.module = + { config, ... }: + { + performance.combinePlugins = { + enable = true; + # fzf native library is in build directory + pathsToLink = [ "/build" ]; + }; + extraPlugins = [ pkgs.vimPlugins.telescope-fzf-native-nvim ]; + extraConfigLuaPost = '' + -- Native library is in runtimepath + assert( + vim.api.nvim_get_runtime_file("build/libfzf.so", false)[1], + "build/libfzf.so is not found in runtimepath" + ) + + -- Native library is loadable + require("fzf_lib") + ''; + assertions = [ + { + assertion = pluginCount config.finalPackage config.filesPlugin "start" == 1; + message = "More than one plugin is defined in packpathDirs."; + } + ]; + }; + + # Test that plugin python3 dependencies are handled + python-dependencies.module = + { config, ... }: + { + performance.combinePlugins.enable = true; + extraPlugins = with pkgs.vimPlugins; [ + # No python3 dependencies + plenary-nvim + # Duplicate python3 dependencies + (nvim-lspconfig.overrideAttrs { passthru.python3Dependencies = ps: [ ps.pyyaml ]; }) + (nvim-treesitter.overrideAttrs { passthru.python3Dependencies = ps: [ ps.pyyaml ]; }) + # Another python3 dependency + (nvim-cmp.overrideAttrs { passthru.python3Dependencies = ps: [ ps.requests ]; }) + ]; + extraConfigLuaPost = '' + -- Python modules are importable + vim.cmd.py3("import yaml") + vim.cmd.py3("import requests") + ''; + assertions = [ + { + assertion = pluginCount config.finalPackage config.filesPlugin "start" == 1; + message = "More than one plugin is defined in packpathDirs."; + } + ]; + }; + + # Test that optional plugins are handled + optional-plugins.module = + { config, ... }: + { + performance.combinePlugins.enable = true; + extraPlugins = with pkgs.vimPlugins; [ + # Start plugins + plenary-nvim + nvim-lspconfig + # Optional plugin + { + plugin = nvim-treesitter; + optional = true; + } + # Optional plugin with dependency on plenary-nvim + # Dependencies should not be duplicated + { + plugin = telescope-nvim; + optional = true; + } + ]; + extraConfigLuaPost = '' + -- Start plugins are loadable + require("plenary") + require("lspconfig") + + -- Opt plugins are not loadable + local ok = pcall(require, "nvim-treesitter") + assert(not ok, "nvim-treesitter plugin is loadable") + ok = pcall(require, "telescope") + assert(not ok, "telescope-nvim plugin is loadable") + + -- Load plugins + vim.cmd.packadd("nvim-treesitter") + vim.cmd.packadd("telescope.nvim") + + -- Now opt plugins are loadable + require("nvim-treesitter") + require("telescope") + + -- Only one copy of plenary-nvim should be available + assert( + #vim.api.nvim_get_runtime_file("lua/plenary/init.lua", true) == 1, + "plenary-nvim is duplicated" + ) + ''; + assertions = [ + { + assertion = pluginCount config.finalPackage config.filesPlugin "start" == 1; + message = "More than one start plugin is defined in packpathDirs"; + } + { + assertion = pluginCount config.finalPackage config.filesPlugin "opt" == 2; + message = "Less than two opt plugins are defined in packpathDirs"; + } + ]; + }; + + # Test that plugin configs are handled + configs.module = + { config, ... }: + { + performance.combinePlugins.enable = true; + extraPlugins = with pkgs.vimPlugins; [ + # A plugin without config + plenary-nvim + # Plugins with configs + { + plugin = nvim-treesitter; + config = "let g:treesitter_config = 1"; + } + { + plugin = nvim-lspconfig; + config = "let g:lspconfig_config = 1"; + } + # Optional plugin with config + { + plugin = telescope-nvim; + optional = true; + config = "let g:telescope_config = 1"; + } + ]; + extraConfigLuaPost = '' + -- Plugins are loadable + require("plenary") + require("nvim-treesitter") + require("lspconfig") + + -- Configs are evaluated + assert(vim.g.treesitter_config == 1, "nvim-treesitter config isn't evaluated") + assert(vim.g.lspconfig_config == 1, "nvim-lspconfig config isn't evaluated") + assert(vim.g.telescope_config == 1, "telescope-nvim config isn't evaluated") + ''; + assertions = [ + { + assertion = pluginCount config.finalPackage config.filesPlugin "start" == 1; + message = "More than one start plugin is defined in packpathDirs"; + } + ]; + }; + + # Test that config.filesPlugin is not combined + files-plugin.module = + { config, ... }: + { + performance.combinePlugins.enable = true; + extraPlugins = with pkgs.vimPlugins; [ + nvim-treesitter + vim-nix + ]; + # Ensure that filesPlugin is added extraPlugins + wrapRc = true; + # Extra user files colliding with plugins + extraFiles = { + "ftplugin/nix.vim".text = "let b:test = 1"; + "queries/nix/highlights.scm".text = '' + ;; extends + (comment) @comment + ''; + }; + # Another form of user files + files = { + "ftdetect/nix.vim" = { + autoCmd = [ + { + event = [ + "BufRead" + "BufNewFile" + ]; + pattern = "*.nix"; + command = "setf nix"; + } + ]; + }; + }; + extraConfigLuaPost = '' + local function get_paths(name) + local paths = vim.api.nvim_get_runtime_file(name, true); + return vim.tbl_filter(function(v) + -- Skip paths from neovim runtime + return not v:find("/nvim/runtime/") + end, paths) + end + + -- Both plugin and user version are available + assert(#get_paths("ftplugin/nix.vim") == 2, "only one version of ftplugin/nix.vim") + assert(#get_paths("ftdetect/nix.vim") == 2, "only one version of ftdetect/nix.vim") + assert(#get_paths("queries/nix/highlights.scm") == 2, "only one version of queries/nix/highlights.scm") + + -- First found file is from filesPlugin + assert( + get_paths("ftplugin/nix.vim")[1]:find("${lib.getName config.filesPlugin}", 1, true), + "first found ftplugin/nix.vim isn't in filesPlugin runtime path" + ) + assert( + get_paths("queries/nix/highlights.scm")[1]:find("${lib.getName config.filesPlugin}", 1, true), + "first found queries/nix/highlights.scm isn't in filesPlugin runtime path" + ) + assert( + get_paths("queries/nix/highlights.scm")[1]:find("${lib.getName config.filesPlugin}", 1, true), + "first found queries/nix/highlights.scm isn't in filesPlugin runtime path" + ) + ''; + assertions = [ + { + assertion = pluginCount config.finalPackage config.filesPlugin "start" == 1; + message = "More than one start plugin is defined in packpathDirs"; + } + ]; + }; + + # Test that standalonePlugins option works + standalone-plugins.module = + { config, ... }: + { + performance.combinePlugins = { + enable = true; + standalonePlugins = with pkgs.vimPlugins; [ + # By plugin name + "nvim-treesitter" + # By package itself + nvim-lspconfig + # Its dependency, plenary-nvim, not in this list, so will be combined + telescope-nvim + # Dependency of other plugin + "nvim-cmp" + ]; + }; + extraPlugins = with pkgs.vimPlugins; [ + nvim-treesitter + nvim-lspconfig + telescope-nvim + # Only its dependency (nvim-cmp) won't be combined, but not the plugin itself + cmp-dictionary + # More plugins + gitsigns-nvim + luasnip + ]; + extraConfigLuaPost = '' + -- Plugins are loadable + require("nvim-treesitter") + require("lspconfig") + require("telescope") + require("plenary") + require("cmp_dictionary") + require("cmp") + require("gitsigns") + require("luasnip") + + -- Verify if plugin is standalone or combined + local function is_standalone(name, dirname) + local paths = vim.api.nvim_get_runtime_file("lua/" .. name, true); + assert(#paths == 1, "more than one copy of " .. name .. " in runtime") + return paths[1]:match("^(.+)/lua/"):find(dirname or name, 1, true) ~= nil + end + + -- Standalone plugins + assert(is_standalone("nvim-treesitter"), "nvim-treesitter is combined, expected standalone") + assert(is_standalone("lspconfig"), "nvim-lspconfig is combined, expected standalone") + assert(is_standalone("telescope"), "telescope-nvim is combined, expected standalone") + -- Add trailing slash to ensure that it doesn't match cmp_dictionary + assert(is_standalone("cmp/", "nvim-cmp"), "nvim-cmp is combined, expected standalone") + -- Combined plugins + assert(not is_standalone("plenary"), "plenary-nvim is standalone, expected combined") + assert(not is_standalone("cmp_dictionary", "cmp-dictionary"), "cmp-dictionary is standalone, expected combined") + assert(not is_standalone("gitsigns"), "gitsigns-nvim is standalone, expected combined") + assert(not is_standalone("luasnip"), "luasnip is standalone, expected combined") + ''; + assertions = [ + { + # plugin-pack, nvim-treesitter, nvim-lspconfig, telescope-nvim, nvim-cmp + assertion = pluginCount config.finalPackage config.filesPlugin "start" == 5; + message = "Wrong number of plugins in packpathDirs"; + } + ]; + }; + + # Test if plenary.filetype is working + plenary-nvim = { + performance.combinePlugins.enable = true; + extraPlugins = [ pkgs.vimPlugins.plenary-nvim ]; + extraConfigLuaPost = '' + -- Plenary filetype detection is usable + assert(require("plenary.filetype").detect(".bashrc") == "sh", "plenary.filetype is not working") + ''; + }; +} diff --git a/tests/test-sources/plugins/languages/treesitter/combine-plugins.nix b/tests/test-sources/plugins/languages/treesitter/combine-plugins.nix new file mode 100644 index 0000000000..074c95ad86 --- /dev/null +++ b/tests/test-sources/plugins/languages/treesitter/combine-plugins.nix @@ -0,0 +1,37 @@ +{ pkgs, ... }: +{ + combine-plugins = { + performance.combinePlugins.enable = true; + + plugins.treesitter = { + enable = true; + + # Exclude nixvim injections for test to pass + nixvimInjections = false; + }; + + extraConfigLuaPost = '' + -- Ensure that queries from nvim-treesitter are first in rtp + local queries_path = "${pkgs.vimPlugins.nvim-treesitter}/queries" + for name, type in vim.fs.dir(queries_path, {depth = 10}) do + if type == "file" then + -- Resolve all symlinks and compare nvim-treesitter's path with + -- whatever we've got from runtime + local nvim_treesitter_path = assert(vim.uv.fs_realpath(vim.fs.joinpath(queries_path, name))) + local rtp_path = assert( + vim.uv.fs_realpath(vim.api.nvim_get_runtime_file("queries/" .. name, false)[1]), + name .. " not found in runtime" + ) + assert( + nvim_treesitter_path == rtp_path, + string.format( + "%s from rtp (%s) is not the same as from nvim-treesitter (%s)", + name, + rtp_path, nvim_treesitter_path + ) + ) + end + end + ''; + }; +} diff --git a/tests/test-sources/plugins/telescope/default.nix b/tests/test-sources/plugins/telescope/default.nix index 8354ea174f..15d2760795 100644 --- a/tests/test-sources/plugins/telescope/default.nix +++ b/tests/test-sources/plugins/telescope/default.nix @@ -17,4 +17,19 @@ highlightTheme = "gruvbox"; }; }; + + combine-plugins.module = + { config, ... }: + { + plugins.telescope.enable = true; + + performance.combinePlugins.enable = true; + + extraConfigLuaPost = # lua + '' + -- I don't know how run telescope properly in test environment, + -- so just check that files exist + assert(vim.api.nvim_get_runtime_file("data/memes/planets/earth", false)[1], "telescope planets aren't found in runtime") + ''; + }; } diff --git a/tests/test-sources/plugins/telescope/fzf-native.nix b/tests/test-sources/plugins/telescope/fzf-native.nix index 7cf63acd80..6a1b2c8707 100644 --- a/tests/test-sources/plugins/telescope/fzf-native.nix +++ b/tests/test-sources/plugins/telescope/fzf-native.nix @@ -22,4 +22,13 @@ }; }; }; + + combine-plugins = { + plugins.telescope = { + enable = true; + extensions.fzf-native.enable = true; + }; + + performance.combinePlugins.enable = true; + }; } diff --git a/tests/test-sources/plugins/telescope/fzy-native.nix b/tests/test-sources/plugins/telescope/fzy-native.nix index f6f3474768..42112ea3e3 100644 --- a/tests/test-sources/plugins/telescope/fzy-native.nix +++ b/tests/test-sources/plugins/telescope/fzy-native.nix @@ -20,4 +20,13 @@ }; }; }; + + combine-plugins = { + plugins.telescope = { + enable = true; + extensions.fzy-native.enable = true; + }; + + performance.combinePlugins.enable = true; + }; }