-
-
Notifications
You must be signed in to change notification settings - Fork 18.6k
neovim: make the derivation more composable #344541
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,46 +13,11 @@ | |
| let | ||
| inherit (vimUtils) toVimPlugin; | ||
|
|
||
| /* 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 | ||
| The caller is responsible for writing the init.vim and adding it to the wrapped | ||
| arguments (["-u" writeText "init.vim" GENERATEDRC)]). | ||
| This makes it possible to write the config anywhere: on a per-project basis | ||
| .nvimrc or in $XDG_CONFIG_HOME/nvim/init.vim to avoid sideeffects. | ||
| 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 ? (_: [ ]) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the new expected way of handling adding extraLuaPackages to a config? I didn't see this argument moved to the wrapper like extraPython3Packages was.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In relation to https://buildbot.nix-community.org/#/builders/2809/builds/1218 trying to figure out what we need to change in https://github.com/nix-community/nixvim/blob/0ca98d02104f7f0a703787a7a080a570b7f1bedd/modules/top-level/output.nix#L266
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you are absolutely correct. I would like to avoid adding them to the wrapper as extraLuaPackages was a workaround to specify plugin dependencies. Lua dependencies are now loaded correctly in the wrapper via shell hooks. A user could call the wrapper directly adding its own wrapper args to add externmal lua dependencies or convert a lua package with
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you could trigger the nnixvim job again, hopefully it is now fixed.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool, kicking off another build there |
||
|
|
||
| # 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 | ||
| /* transform all plugins into an attrset | ||
| { optional = bool; plugin = package; } | ||
| */ | ||
| normalizePlugins = plugins: | ||
| let | ||
| defaultPlugin = { | ||
| plugin = null; | ||
| config = null; | ||
|
|
@@ -61,65 +26,40 @@ let | |
| 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; | ||
| /* 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; | ||
| }; | ||
|
|
||
| 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) [ | ||
| /* 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 | ||
| The caller is responsible for writing the init.vim and adding it to the wrapped | ||
| arguments (["-u" writeText "init.vim" GENERATEDRC)]). | ||
| This makes it possible to write the config anywhere: on a per-project basis | ||
| .nvimrc or in $XDG_CONFIG_HOME/nvim/init.vim to avoid sideeffects. | ||
| Indeed, note that wrapping with `-u init.vim` has sideeffects like .nvimrc wont be loaded | ||
| anymore, $MYVIMRC wont be set etc | ||
| */ | ||
| 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; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,15 @@ | ||
| { stdenv, symlinkJoin, lib, makeWrapper | ||
| , bundlerEnv | ||
| , ruby | ||
| , nodejs | ||
| , writeText | ||
| , nodePackages | ||
| , python3 | ||
| , callPackage | ||
| , 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; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be useful to also have a
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. totally. This will be unblocked by this PR. I prefer it to be done as a follow up though since neovim is a touchy derivation: you quickly know when you break something xD and this has the potential to break configs already (at least for people using the "private/unstable" APIs) |
||
|
|
||
| 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 { | ||
| }; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this removed? Could you add a deprecation stub that throws an appropriate error message for any publicly exposed functions/etc that have been removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, my mistake. This is not removed. Is anything else removed without a
throw?