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.
This commit is contained in:
Matthieu Coudron 2022-06-19 14:18:16 +02:00 committed by GitHub
parent 849bf88af1
commit ce505a3984
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 105 additions and 43 deletions

View File

@ -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

View File

@ -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;
};
}

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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;
};
});
}

View File

@ -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) {};
}

View File

@ -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"

View File

@ -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 { };

View File

@ -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;