From ce505a39845b93e48f125ededeaaec6f597df43f Mon Sep 17 00:00:00 2001 From: Matthieu Coudron Date: Sun, 19 Jun 2022 14:18:16 +0200 Subject: [PATCH] vimPlugins: use lua derivation if it exists (#178180) Neovim plugins are now more often than not written in lua. One advantage of the lua ecosystem over vim's is the existence of luarocks and the rockspec format, which allows to specify a package dependencies formally. I would like more neovim plugins to have a formal description, "rockspec" being the current candidate. This MR allows to use nix lua packages as neovim plugins, so as to enjoy every benefit that rockspecs bring: - dependdency discovery - ability to run test suite - luarocks versioning - rockspec metadata the vim update.py script will check if an attribute with the vim plugin pname exists in lua51Packages. If it does, it uses buildNeovimPluginFrom2Nix on it, which modifies the luarocks config to do an almost flat install (luarocks will install the package in the lua folder instead of share/5.1/lua etc). It also calls toVimPlugin on it to get all the vim plugin niceties. The list of packages that could benefit from this is available at https://luarocks.org/labels/neovim but I hope it grows. --- .../editors/neovim/build-neovim-plugin.nix | 35 ++++++++++++++++++ pkgs/applications/editors/neovim/utils.nix | 7 ++++ .../editors/vim/plugins/build-vim-plugin.nix | 10 ++--- .../editors/vim/plugins/default.nix | 22 +++-------- .../editors/vim/plugins/generated.nix | 8 ++-- .../editors/vim/plugins/vim-utils.nix | 37 ++++++++++++------- .../interpreters/lua-5/hooks/default.nix | 8 ++++ .../lua-5/hooks/luarocks-move-data.sh | 15 ++++++++ pkgs/top-level/all-packages.nix | 4 +- pkgs/top-level/lua-packages.nix | 2 +- 10 files changed, 105 insertions(+), 43 deletions(-) create mode 100644 pkgs/applications/editors/neovim/build-neovim-plugin.nix create mode 100644 pkgs/development/interpreters/lua-5/hooks/luarocks-move-data.sh diff --git a/pkgs/applications/editors/neovim/build-neovim-plugin.nix b/pkgs/applications/editors/neovim/build-neovim-plugin.nix new file mode 100644 index 000000000000..cb69b5ecacdb --- /dev/null +++ b/pkgs/applications/editors/neovim/build-neovim-plugin.nix @@ -0,0 +1,35 @@ +{ lib +, stdenv +, buildVimPluginFrom2Nix +, buildLuarocksPackage +, lua51Packages +, toVimPlugin +}: +let + # sanitizeDerivationName + normalizeName = lib.replaceStrings [ "." ] [ "-" ]; +in + + # function to create vim plugin from lua packages that are already packaged in + # luaPackages + { + # the lua attribute name that matches this vim plugin. Both should be equal + # in the majority of cases but we make it possible to have different attribute names + luaAttr ? (normalizeName attrs.pname) + , ... + }@attrs: + let + originalLuaDrv = lua51Packages.${luaAttr}; + luaDrv = lua51Packages.lib.overrideLuarocks originalLuaDrv (drv: { + extraConfig = '' + -- to create a flat hierarchy + lua_modules_path = "lua" + ''; + }); + finalDrv = toVimPlugin (luaDrv.overrideAttrs(oa: { + nativeBuildInputs = oa.nativeBuildInputs or [] ++ [ + lua51Packages.luarocksMoveDataFolder + ]; + })); + in + finalDrv diff --git a/pkgs/applications/editors/neovim/utils.nix b/pkgs/applications/editors/neovim/utils.nix index ee0abb582891..16b19f63d2d3 100644 --- a/pkgs/applications/editors/neovim/utils.nix +++ b/pkgs/applications/editors/neovim/utils.nix @@ -1,4 +1,6 @@ { lib +, buildLuarocksPackage +, callPackage , vimUtils , nodejs , neovim-unwrapped @@ -184,4 +186,9 @@ in { inherit makeNeovimConfig; inherit legacyWrapper; + + buildNeovimPluginFrom2Nix = callPackage ./build-neovim-plugin.nix { + inherit (vimUtils) buildVimPluginFrom2Nix toVimPlugin; + inherit buildLuarocksPackage; + }; } diff --git a/pkgs/applications/editors/vim/plugins/build-vim-plugin.nix b/pkgs/applications/editors/vim/plugins/build-vim-plugin.nix index 6b4cf674ac5a..9e7bb1be2d5c 100644 --- a/pkgs/applications/editors/vim/plugins/build-vim-plugin.nix +++ b/pkgs/applications/editors/vim/plugins/build-vim-plugin.nix @@ -4,6 +4,7 @@ , vimCommandCheckHook , vimGenDocHook , neovimRequireCheckHook +, toVimPlugin }: rec { @@ -23,11 +24,6 @@ rec { let drv = stdenv.mkDerivation (attrs // { name = namePrefix + name; - # dont move the doc folder since vim expects it - forceShare= [ "man" "info" ]; - - nativeBuildInputs = attrs.nativeBuildInputs or [] - ++ lib.optionals (stdenv.hostPlatform == stdenv.buildPlatform) [ vimCommandCheckHook vimGenDocHook ]; inherit unpackPhase configurePhase buildPhase addonInfo preInstall postInstall; installPhase = '' @@ -40,9 +36,9 @@ rec { runHook postInstall ''; }); - in drv.overrideAttrs(oa: { + in toVimPlugin(drv.overrideAttrs(oa: { rtp = "${drv}"; - }); + })); buildVimPluginFrom2Nix = attrs: buildVimPlugin ({ # vim plugins may override this diff --git a/pkgs/applications/editors/vim/plugins/default.nix b/pkgs/applications/editors/vim/plugins/default.nix index c6ef409d637b..17e03b7dd76d 100644 --- a/pkgs/applications/editors/vim/plugins/default.nix +++ b/pkgs/applications/editors/vim/plugins/default.nix @@ -1,5 +1,8 @@ # TODO check that no license information gets lost -{ callPackage, config, lib, vimUtils, vim, darwin, llvmPackages, luaPackages }: +{ callPackage, config, lib, vimUtils, vim, darwin, llvmPackages +, neovimUtils +, luaPackages +}: let @@ -8,24 +11,11 @@ let inherit (lib) extends; - initialPackages = self: { - # Convert derivation to a vim plugin. - toVimPlugin = drv: - drv.overrideAttrs(oldAttrs: { - - nativeBuildInputs = oldAttrs.nativeBuildInputs or [] ++ [ - vimGenDocHook - vimCommandCheckHook - ]; - passthru = (oldAttrs.passthru or {}) // { - vimPlugin = true; - }; - }); - }; + initialPackages = self: { }; plugins = callPackage ./generated.nix { inherit buildVimPluginFrom2Nix; - inherit (vimUtils) buildNeovimPluginFrom2Nix; + inherit (neovimUtils) buildNeovimPluginFrom2Nix; }; # TL;DR diff --git a/pkgs/applications/editors/vim/plugins/generated.nix b/pkgs/applications/editors/vim/plugins/generated.nix index dac92940b6de..b11d09063f8a 100644 --- a/pkgs/applications/editors/vim/plugins/generated.nix +++ b/pkgs/applications/editors/vim/plugins/generated.nix @@ -2527,7 +2527,7 @@ final: prev: meta.homepage = "https://github.com/nvim-lua/diagnostic-nvim/"; }; - diffview-nvim = buildNeovimPluginFrom2Nix { + diffview-nvim = buildVimPluginFrom2Nix { pname = "diffview.nvim"; version = "2022-06-09"; src = fetchFromGitHub { @@ -3154,7 +3154,7 @@ final: prev: meta.homepage = "https://github.com/ruifm/gitlinker.nvim/"; }; - gitsigns-nvim = buildNeovimPluginFrom2Nix { + gitsigns-nvim = buildVimPluginFrom2Nix { pname = "gitsigns.nvim"; version = "2022-05-26"; src = fetchFromGitHub { @@ -4282,7 +4282,7 @@ final: prev: meta.homepage = "https://github.com/iamcco/markdown-preview.nvim/"; }; - marks-nvim = buildNeovimPluginFrom2Nix { + marks-nvim = buildVimPluginFrom2Nix { pname = "marks.nvim"; version = "2022-05-13"; src = fetchFromGitHub { @@ -5110,7 +5110,7 @@ final: prev: meta.homepage = "https://github.com/RRethy/nvim-base16/"; }; - nvim-biscuits = buildNeovimPluginFrom2Nix { + nvim-biscuits = buildVimPluginFrom2Nix { pname = "nvim-biscuits"; version = "2022-05-31"; src = fetchFromGitHub { diff --git a/pkgs/applications/editors/vim/plugins/vim-utils.nix b/pkgs/applications/editors/vim/plugins/vim-utils.nix index 1170771c62a1..4c6bb5d0da0f 100644 --- a/pkgs/applications/editors/vim/plugins/vim-utils.nix +++ b/pkgs/applications/editors/vim/plugins/vim-utils.nix @@ -205,9 +205,6 @@ let ln -sf ${plugin}/${rtpPath} $out/pack/${packageName}/${dir}/${lib.getName plugin} ''; - link = pluginPath: if hasLuaModule pluginPath - then linkLuaPlugin pluginPath - else linkVimlPlugin pluginPath; packageLinks = packageName: {start ? [], opt ? []}: let @@ -225,9 +222,9 @@ let [ "mkdir -p $out/pack/${packageName}/start" ] # To avoid confusion, even dependencies of optional plugins are added # to `start` (except if they are explicitly listed as optional plugins). - ++ (builtins.map (x: link x packageName "start") allPlugins) + ++ (builtins.map (x: linkVimlPlugin x packageName "start") allPlugins) ++ ["mkdir -p $out/pack/${packageName}/opt"] - ++ (builtins.map (x: link x packageName "opt") opt) + ++ (builtins.map (x: linkVimlPlugin x packageName "opt") opt) # Assemble all python3 dependencies into a single `site-packages` to avoid doing recursive dependency collection # for each plugin. # This directory is only for python import search path, and will not slow down the startup time. @@ -290,14 +287,14 @@ let /* vim-plug is an extremely popular vim plugin manager. */ plugImpl = - ('' + '' source ${vimPlugins.vim-plug.rtp}/plug.vim silent! call plug#begin('/dev/null') '' + (lib.concatMapStringsSep "\n" (pkg: "Plug '${pkg.rtp}'") plug.plugins) + '' call plug#end() - ''); + ''; /* vim-addon-manager = VAM @@ -533,16 +530,11 @@ rec { } ./neovim-require-check-hook.sh) {}; inherit (import ./build-vim-plugin.nix { - inherit lib stdenv rtpPath vim vimGenDocHook vimCommandCheckHook neovimRequireCheckHook; + inherit lib stdenv rtpPath vim vimGenDocHook + toVimPlugin vimCommandCheckHook neovimRequireCheckHook; }) buildVimPlugin buildVimPluginFrom2Nix; - # TODO placeholder to ease working on automatic plugin detection - # this should be a luarocks "flat" install with appropriate vim hooks - buildNeovimPluginFrom2Nix = attrs: let drv = (buildVimPluginFrom2Nix attrs); in drv.overrideAttrs(oa: { - nativeBuildInputs = oa.nativeBuildInputs ++ [ neovimRequireCheckHook ]; - }); - # used to figure out which python dependencies etc. neovim needs requiredPlugins = { packages ? {}, @@ -566,4 +558,21 @@ rec { nativePlugins = lib.concatMap ({start?[], opt?[], knownPlugins?vimPlugins}: start++opt) nativePluginsConfigs; in nativePlugins ++ nonNativePlugins; + + toVimPlugin = drv: + drv.overrideAttrs(oldAttrs: { + # dont move the "doc" folder since vim expects it + forceShare = [ "man" "info" ]; + + nativeBuildInputs = oldAttrs.nativeBuildInputs or [] + ++ lib.optionals (stdenv.hostPlatform == stdenv.buildPlatform) [ + vimCommandCheckHook vimGenDocHook + # many neovim plugins keep using buildVimPlugin + neovimRequireCheckHook + ]; + + passthru = (oldAttrs.passthru or {}) // { + vimPlugin = true; + }; + }); } diff --git a/pkgs/development/interpreters/lua-5/hooks/default.nix b/pkgs/development/interpreters/lua-5/hooks/default.nix index 61261ca3d046..fc92c59bb910 100644 --- a/pkgs/development/interpreters/lua-5/hooks/default.nix +++ b/pkgs/development/interpreters/lua-5/hooks/default.nix @@ -29,4 +29,12 @@ in { name = "luarocks-check-hook"; deps = [ luarocks ]; } ./luarocks-check-hook.sh) {}; + + # luarocks installs data in a non-overridable location. Until a proper luarocks patch, + # we move the files around ourselves + luarocksMoveDataFolder = callPackage ({ }: + makeSetupHook { + name = "luarocks-move-rock"; + deps = [ ]; + } ./luarocks-move-data.sh) {}; } diff --git a/pkgs/development/interpreters/lua-5/hooks/luarocks-move-data.sh b/pkgs/development/interpreters/lua-5/hooks/luarocks-move-data.sh new file mode 100644 index 000000000000..f0b56178f01e --- /dev/null +++ b/pkgs/development/interpreters/lua-5/hooks/luarocks-move-data.sh @@ -0,0 +1,15 @@ +# luarocks installs data in a non-overridable location. Until a proper luarocks patch, +# we move the files around ourselves +echo "Sourcing luarocks-move-data-hook.sh" + +luarocksMoveDataHook () { + echo "Executing luarocksMoveDataHook" + if [ -d "$out/$rocksSubdir" ]; then + cp -rfv "$out/$rocksSubdir/$pname/$version/." "$out" + fi + + echo "Finished executing luarocksMoveDataHook" +} + +echo "Using luarocksMoveDataHook" +preDistPhases+=" luarocksMoveDataHook" diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 943f7f9025cf..1089bee58a97 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -30449,7 +30449,9 @@ with pkgs; lua = luajit; }; - neovimUtils = callPackage ../applications/editors/neovim/utils.nix { }; + neovimUtils = callPackage ../applications/editors/neovim/utils.nix { + inherit (lua51Packages) buildLuarocksPackage; + }; neovim = wrapNeovim neovim-unwrapped { }; neovim-qt-unwrapped = libsForQt5.callPackage ../applications/editors/neovim/neovim-qt.nix { }; diff --git a/pkgs/top-level/lua-packages.nix b/pkgs/top-level/lua-packages.nix index 385aef164c2d..cb963bb1b177 100644 --- a/pkgs/top-level/lua-packages.nix +++ b/pkgs/top-level/lua-packages.nix @@ -50,7 +50,7 @@ in getLuaCPath = drv: getPath drv luaLib.luaCPathList; inherit (callPackage ../development/interpreters/lua-5/hooks { inherit (args) lib;}) - luarocksCheckHook lua-setup-hook; + luarocksMoveDataFolder luarocksCheckHook lua-setup-hook; inherit lua callPackage; inherit buildLuaPackage buildLuarocksPackage buildLuaApplication;