3
0
Fork 0
forked from mirrors/nixpkgs
nixpkgs/pkgs/applications/editors/neovim/utils.nix
Matthieu Coudron 2eb1610725
neovimUtils: neovim utilities to handle more usecases
Current nixpkgs always wraps neovim with the "-u" which has sideeffects as explained in https://github.com/NixOS/nixpkgs/issues/55376 : 
1.  vim won't set the variable $MYVIMRC as explained #34215
 2. vim skips loading folder-specific .vimrc / .nvimrc

I wanted to provide a way for users to better control what flags are used to wrap neovim. This is achived by introducing wrapNeovimUnstable et neovimUtils, utilities to help with that. We provide a compatibility layer so that wrapNeovim still works and to let us experiment with wrapNeovimUnstable to better control neovim configuration, plugin dependencies, haskell environment etc so that it becomes easier to generate per-project neovim config.

With this commit, it's possible for instance for home-manager to wrap neovim without the `-u` and just write the config in the
expected $XDG_CONFIG_HOME/nvim/init.vim .
Expect wrapNeovimUnstable interface to evolve in the upcoming months.
2020-10-29 09:50:26 +01:00

164 lines
5.4 KiB
Nix

{ lib
, vimUtils
, nodejs
, neovim-unwrapped
, bundlerEnv
, ruby
, pythonPackages
, python3Packages
, writeText
, wrapNeovimUnstable
}:
let
# 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 =
{
withPython2 ? false
/* the function you would have passed to python.withPackages */
, extraPython2Packages ? (_: [ ])
, withPython3 ? true
/* the function you would have passed to python3.withPackages */
, extraPython3Packages ? (_: [ ])
, withNodeJs ? false
, withRuby ? true
# same values as in vimUtils.vimrcContent
, configure ? { }
# for forward compability, when adding new environments, haskell etc.
, ...
}:
let
rubyEnv = bundlerEnv {
name = "neovim-ruby-env";
gemdir = ./ruby_provider;
postBuild = ''
ln -sf ${ruby}/bin/* $out/bin
'';
};
requiredPlugins = vimUtils.requiredPlugins configure;
getDeps = attrname: map (plugin: plugin.${attrname} or (_: [ ]));
pluginPython2Packages = getDeps "pythonDependencies" requiredPlugins;
python2Env = pythonPackages.python.withPackages (ps:
[ ps.pynvim ]
++ (extraPython2Packages ps)
++ (lib.concatMap (f: f ps) pluginPython2Packages));
pluginPython3Packages = getDeps "python3Dependencies" requiredPlugins;
python3Env = python3Packages.python.withPackages (ps:
[ ps.pynvim ]
++ (extraPython3Packages ps)
++ (lib.concatMap (f: f ps) pluginPython3Packages));
# Mapping a boolean argument to a key that tells us whether to add or not to
# add to nvim's 'embedded rc' this:
# let g:<key>_host_prog=$out/bin/nvim-<key>
# Or this:
# let g:loaded_${prog}_provider=1
# While the latter tells nvim that this provider is not available
hostprog_check_table = {
node = withNodeJs;
python = withPython2;
python3 = withPython3;
ruby = withRuby;
};
## 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 ]);
flags = lib.concatLists (lib.mapAttrsToList (
prog: withProg: [
"--cmd" (genProviderSettings prog withProg)
]
)
hostprog_check_table);
in
[
"--argv0" "$0" "--add-flags" (lib.escapeShellArgs flags)
] ++ lib.optionals withRuby [
"--set" "GEM_HOME" "${rubyEnv}/${rubyEnv.ruby.gemPath}"
] ++ lib.optionals (binPath != "") [
"--suffix" "PATH" ":" binPath
];
manifestRc = vimUtils.vimrcContent (configure // { customRC = ""; });
neovimRcContent = vimUtils.vimrcContent configure;
in
{
wrapperArgs = makeWrapperArgs;
inherit neovimRcContent;
inherit manifestRc;
inherit rubyEnv;
inherit python2Env;
inherit python3Env;
};
genProviderSettings = prog: withProg:
if withProg then
"let g:${prog}_host_prog='${placeholder "out"}/bin/nvim-${prog}'"
else
"let g:loaded_${prog}_provider=1"
;
# to keep backwards compatibility
legacyWrapper = neovim: {
extraMakeWrapperArgs ? []
, withPython ? true
/* the function you would have passed to python.withPackages */
, extraPythonPackages ? (_: [])
/* the function you would have passed to python.withPackages */
, withPython3 ? true, extraPython3Packages ? (_: [])
, withNodeJs ? false
, withRuby ? true
, vimAlias ? false
, viAlias ? false
, configure ? {}
}:
let
/* for compatibility with passing extraPythonPackages as a list; added 2018-07-11 */
compatFun = funOrList: (if builtins.isList funOrList then
(_: lib.warn "passing a list as extraPythonPackages to the neovim wrapper is deprecated, pass a function as to python.withPackages instead" funOrList)
else funOrList);
res = makeNeovimConfig {
withPython2 = withPython;
extraPythonPackages = compatFun extraPythonPackages;
inherit withPython3;
extraPython3Packages = compatFun extraPython3Packages;
inherit withNodeJs withRuby;
inherit configure;
};
in
wrapNeovimUnstable neovim (res // {
wrapperArgs = res.wrapperArgs
++ [
"--add-flags" "-u ${writeText "init.vim" res.neovimRcContent}"
]
++ (if builtins.isList extraMakeWrapperArgs then extraMakeWrapperArgs
else lib.warn "Passing a string as extraMakeWrapperArgs to the neovim wrapper is
deprecated, please use a list instead")
;
});
in
{
inherit makeNeovimConfig;
inherit legacyWrapper;
}