neovim: make the wrapper more evolvable
Now that we have structured attributes enabled, it's easier than ever to access the wrapper config from itself. Let's expose the 'plugins' derivations instead of the final 'packpathDir' with which one can't do much. TLDR: the neovim wrapper accepts a list of neovim derivations in `plugins` instead of the symlinkJoin of plugins in `packpathDir`. With exposed plugins, one could tweak the current wrapper with more plugins, e.g. neovim.withPlugins([fugitive]).withPlugins([plenary]) . we could also add a boolean to autoadd the plugins passthru.initLua, better handle the dependencies (runtime programs, python deps).
This commit is contained in:
parent
11cf80ae32
commit
12dafac23c
@ -13,6 +13,30 @@
|
||||
let
|
||||
inherit (vimUtils) toVimPlugin;
|
||||
|
||||
/* transform all plugins into an attrset
|
||||
{ optional = bool; plugin = package; }
|
||||
*/
|
||||
normalizePlugins = plugins:
|
||||
let
|
||||
defaultPlugin = {
|
||||
plugin = null;
|
||||
config = null;
|
||||
optional = false;
|
||||
};
|
||||
in
|
||||
map (x: defaultPlugin // (if (x ? plugin) then x else { plugin = x; })) plugins;
|
||||
|
||||
|
||||
/* accepts a list of normalized plugins and convert themn
|
||||
*/
|
||||
normalizedPluginsToVimPackage = normalizedPlugins:
|
||||
let
|
||||
pluginsPartitioned = lib.partition (x: x.optional == true) normalizedPlugins;
|
||||
in {
|
||||
start = map (x: x.plugin) pluginsPartitioned.wrong;
|
||||
opt = map (x: x.plugin) pluginsPartitioned.right;
|
||||
};
|
||||
|
||||
/* returns everything needed for the caller to wrap its own neovim:
|
||||
- the generated content of the future init.vim
|
||||
- the arguments to wrap neovim with
|
||||
@ -23,103 +47,19 @@ let
|
||||
Indeed, note that wrapping with `-u init.vim` has sideeffects like .nvimrc wont be loaded
|
||||
anymore, $MYVIMRC wont be set etc
|
||||
*/
|
||||
makeNeovimConfig =
|
||||
{ withPython3 ? true
|
||||
/* the function you would have passed to python3.withPackages */
|
||||
, extraPython3Packages ? (_: [ ])
|
||||
, withNodeJs ? false
|
||||
, withRuby ? true
|
||||
/* the function you would have passed to lua.withPackages */
|
||||
, extraLuaPackages ? (_: [ ])
|
||||
|
||||
# expects a list of plugin configuration
|
||||
# expects { plugin=far-vim; config = "let g:far#source='rg'"; optional = false; }
|
||||
, plugins ? []
|
||||
# custom viml config appended after plugin-specific config
|
||||
, customRC ? ""
|
||||
|
||||
# for forward compability, when adding new environments, haskell etc.
|
||||
, ...
|
||||
}@args:
|
||||
let
|
||||
rubyEnv = bundlerEnv {
|
||||
name = "neovim-ruby-env";
|
||||
gemdir = ./ruby_provider;
|
||||
postBuild = ''
|
||||
ln -sf ${ruby}/bin/* $out/bin
|
||||
'';
|
||||
};
|
||||
|
||||
# transform all plugins into an attrset
|
||||
# { optional = bool; plugin = package; }
|
||||
pluginsNormalized = let
|
||||
defaultPlugin = {
|
||||
plugin = null;
|
||||
config = null;
|
||||
optional = false;
|
||||
};
|
||||
in
|
||||
map (x: defaultPlugin // (if (x ? plugin) then x else { plugin = x; })) plugins;
|
||||
|
||||
pluginRC = lib.foldl (acc: p: if p.config != null then acc ++ [p.config] else acc) [] pluginsNormalized;
|
||||
|
||||
pluginsPartitioned = lib.partition (x: x.optional == true) pluginsNormalized;
|
||||
requiredPlugins = vimUtils.requiredPluginsForPackage myVimPackage;
|
||||
getDeps = attrname: map (plugin: plugin.${attrname} or (_: [ ]));
|
||||
myVimPackage = {
|
||||
start = map (x: x.plugin) pluginsPartitioned.wrong;
|
||||
opt = map (x: x.plugin) pluginsPartitioned.right;
|
||||
};
|
||||
|
||||
pluginPython3Packages = getDeps "python3Dependencies" requiredPlugins;
|
||||
python3Env = python3Packages.python.withPackages (ps:
|
||||
[ ps.pynvim ]
|
||||
++ (extraPython3Packages ps)
|
||||
++ (lib.concatMap (f: f ps) pluginPython3Packages));
|
||||
|
||||
luaEnv = neovim-unwrapped.lua.withPackages extraLuaPackages;
|
||||
|
||||
# as expected by packdir
|
||||
packpathDirs.myNeovimPackages = myVimPackage;
|
||||
## Here we calculate all of the arguments to the 1st call of `makeWrapper`
|
||||
# We start with the executable itself NOTE we call this variable "initial"
|
||||
# because if configure != {} we need to call makeWrapper twice, in order to
|
||||
# avoid double wrapping, see comment near finalMakeWrapperArgs
|
||||
makeWrapperArgs =
|
||||
let
|
||||
binPath = lib.makeBinPath (lib.optionals withRuby [ rubyEnv ] ++ lib.optionals withNodeJs [ nodejs ]);
|
||||
in
|
||||
[
|
||||
"--inherit-argv0"
|
||||
] ++ lib.optionals withRuby [
|
||||
"--set" "GEM_HOME" "${rubyEnv}/${rubyEnv.ruby.gemPath}"
|
||||
] ++ lib.optionals (binPath != "") [
|
||||
"--suffix" "PATH" ":" binPath
|
||||
] ++ lib.optionals (luaEnv != null) [
|
||||
makeNeovimConfig = {
|
||||
customRC ? ""
|
||||
/* the function you would have passed to lua.withPackages */
|
||||
, extraLuaPackages ? (_: [ ])
|
||||
, ...}@attrs: let
|
||||
luaEnv = neovim-unwrapped.lua.withPackages extraLuaPackages;
|
||||
in attrs // {
|
||||
neovimRcContent = customRC;
|
||||
wrapperArgs = lib.optionals (luaEnv != null) [
|
||||
"--prefix" "LUA_PATH" ";" (neovim-unwrapped.lua.pkgs.luaLib.genLuaPathAbsStr luaEnv)
|
||||
"--prefix" "LUA_CPATH" ";" (neovim-unwrapped.lua.pkgs.luaLib.genLuaCPathAbsStr luaEnv)
|
||||
];
|
||||
|
||||
manifestRc = vimUtils.vimrcContent { customRC = ""; };
|
||||
# we call vimrcContent without 'packages' to avoid the init.vim generation
|
||||
neovimRcContent = vimUtils.vimrcContent {
|
||||
beforePlugins = "";
|
||||
customRC = lib.concatStringsSep "\n" (pluginRC ++ [customRC]);
|
||||
packages = null;
|
||||
};
|
||||
in
|
||||
|
||||
builtins.removeAttrs args ["plugins"] // {
|
||||
wrapperArgs = makeWrapperArgs;
|
||||
inherit packpathDirs;
|
||||
inherit neovimRcContent;
|
||||
inherit manifestRc;
|
||||
inherit python3Env;
|
||||
inherit luaEnv;
|
||||
inherit withNodeJs;
|
||||
} // lib.optionalAttrs withRuby {
|
||||
inherit rubyEnv;
|
||||
};
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
# to keep backwards compatibility for people using neovim.override
|
||||
@ -198,6 +138,9 @@ let
|
||||
in
|
||||
lib.concatStringsSep ";" hostProviderLua;
|
||||
|
||||
/* Converts a lua package into a neovim plugin.
|
||||
Does so by installing the lua package with a flat hierarchy of folders
|
||||
*/
|
||||
buildNeovimPlugin = callPackage ./build-neovim-plugin.nix {
|
||||
inherit (vimUtils) toVimPlugin;
|
||||
inherit lua;
|
||||
@ -275,6 +218,7 @@ in
|
||||
inherit legacyWrapper;
|
||||
inherit grammarToPlugin;
|
||||
inherit packDir;
|
||||
inherit normalizePlugins normalizedPluginsToVimPackage;
|
||||
|
||||
inherit buildNeovimPlugin;
|
||||
buildNeovimPluginFrom2Nix = lib.warn "buildNeovimPluginFrom2Nix was renamed to buildNeovimPlugin" buildNeovimPlugin;
|
||||
|
@ -1,4 +1,7 @@
|
||||
{ stdenv, symlinkJoin, lib, makeWrapper
|
||||
, bundlerEnv
|
||||
, ruby
|
||||
, nodejs
|
||||
, writeText
|
||||
, nodePackages
|
||||
, python3
|
||||
@ -6,6 +9,7 @@
|
||||
, neovimUtils
|
||||
, perl
|
||||
, lndir
|
||||
, vimUtils
|
||||
}:
|
||||
|
||||
neovim-unwrapped:
|
||||
@ -18,10 +22,11 @@ let
|
||||
extraName ? ""
|
||||
# should contain all args but the binary. Can be either a string or list
|
||||
, wrapperArgs ? []
|
||||
# a limited RC script used only to generate the manifest for remote plugins
|
||||
, manifestRc ? null
|
||||
, withPython2 ? false
|
||||
, withPython3 ? true, python3Env ? python3
|
||||
, withPython3 ? true
|
||||
/* the function you would have passed to python3.withPackages */
|
||||
, extraPython3Packages ? (_: [ ])
|
||||
|
||||
, withNodeJs ? false
|
||||
, withPerl ? false
|
||||
, rubyEnv ? null
|
||||
@ -39,23 +44,67 @@ let
|
||||
, neovimRcContent ? null
|
||||
# lua code to put into the generated init.lua file
|
||||
, luaRcContent ? ""
|
||||
# entry to load in packpath
|
||||
, packpathDirs
|
||||
# DEPRECATED: entry to load in packpath
|
||||
# use 'plugins' instead
|
||||
, packpathDirs ? null # not used anymore
|
||||
|
||||
# a list of neovim plugin derivations, for instance
|
||||
# plugins = [
|
||||
# { plugin=far-vim; config = "let g:far#source='rg'"; optional = false; }
|
||||
# ]
|
||||
, plugins ? []
|
||||
, ...
|
||||
}:
|
||||
}@attrs:
|
||||
assert withPython2 -> throw "Python2 support has been removed from the neovim wrapper, please remove withPython2 and python2Env.";
|
||||
|
||||
assert packpathDirs != null -> throw "packpathdirs is not used anymore: pass a list of neovim plugin derivations in 'plugins' instead.";
|
||||
|
||||
stdenv.mkDerivation (finalAttrs:
|
||||
let
|
||||
pluginsNormalized = neovimUtils.normalizePlugins plugins;
|
||||
|
||||
myVimPackage = neovimUtils.normalizedPluginsToVimPackage pluginsNormalized;
|
||||
|
||||
rubyEnv = bundlerEnv {
|
||||
name = "neovim-ruby-env";
|
||||
gemdir = ./ruby_provider;
|
||||
postBuild = ''
|
||||
ln -sf ${ruby}/bin/* $out/bin
|
||||
'';
|
||||
};
|
||||
|
||||
pluginRC = lib.foldl (acc: p: if p.config != null then acc ++ [p.config] else acc) [] pluginsNormalized;
|
||||
|
||||
# a limited RC script used only to generate the manifest for remote plugins
|
||||
manifestRc = vimUtils.vimrcContent { customRC = ""; };
|
||||
# we call vimrcContent without 'packages' to avoid the init.vim generation
|
||||
neovimRcContent' = vimUtils.vimrcContent {
|
||||
beforePlugins = "";
|
||||
customRC = lib.concatStringsSep "\n" (pluginRC ++ [neovimRcContent]);
|
||||
packages = null;
|
||||
};
|
||||
|
||||
finalPackdir = neovimUtils.packDir packpathDirs;
|
||||
|
||||
rcContent = ''
|
||||
${luaRcContent}
|
||||
'' + lib.optionalString (!isNull neovimRcContent) ''
|
||||
vim.cmd.source "${writeText "init.vim" neovimRcContent}"
|
||||
'' + lib.optionalString (neovimRcContent' != null) ''
|
||||
vim.cmd.source "${writeText "init.vim" neovimRcContent'}"
|
||||
'';
|
||||
|
||||
getDeps = attrname: map (plugin: plugin.${attrname} or (_: [ ]));
|
||||
|
||||
requiredPlugins = vimUtils.requiredPluginsForPackage myVimPackage;
|
||||
pluginPython3Packages = getDeps "python3Dependencies" requiredPlugins;
|
||||
|
||||
python3Env = lib.warnIf (attrs ? python3Env) "Pass your python packages via the `extraPython3Packages`, e.g., `extraPython3Packages = ps: [ ps.pandas ]`"
|
||||
python3.pkgs.python.withPackages (ps:
|
||||
[ ps.pynvim ]
|
||||
++ (extraPython3Packages ps)
|
||||
++ (lib.concatMap (f: f ps) pluginPython3Packages));
|
||||
|
||||
packpathDirs.myNeovimPackages = myVimPackage;
|
||||
|
||||
wrapperArgsStr = if lib.isString wrapperArgs then wrapperArgs else lib.escapeShellArgs wrapperArgs;
|
||||
|
||||
generatedWrapperArgs =
|
||||
@ -94,6 +143,7 @@ let
|
||||
in {
|
||||
name = "${pname}-${version}${extraName}";
|
||||
inherit pname version;
|
||||
inherit plugins;
|
||||
|
||||
__structuredAttrs = true;
|
||||
dontUnpack = true;
|
||||
@ -193,7 +243,7 @@ let
|
||||
passthru = {
|
||||
inherit providerLuaRc packpathDirs;
|
||||
unwrapped = neovim-unwrapped;
|
||||
initRc = neovimRcContent;
|
||||
initRc = neovimRcContent';
|
||||
|
||||
tests = callPackage ./tests {
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user