diff --git a/pkgs/applications/editors/neovim/tests/default.nix b/pkgs/applications/editors/neovim/tests/default.nix index b07f517ea474..c2e6b565de28 100644 --- a/pkgs/applications/editors/neovim/tests/default.nix +++ b/pkgs/applications/editors/neovim/tests/default.nix @@ -43,6 +43,14 @@ let ''; }; + nvim-with-luasnip = wrapNeovim2 "-with-lua-packages" (makeNeovimConfig { + plugins = [ { + plugin = vimPlugins.luasnip; + + } + ]; + }); + nvimAutoDisableWrap = makeNeovimConfig { }; wrapNeovim2 = suffix: config: @@ -281,4 +289,16 @@ rec { export HOME=$TMPDIR ${nvim_with_opt_plugin}/bin/nvim -i NONE +quit! -e ''; + + inherit nvim-with-luasnip; + + # check that bringing in one plugin with lua deps makes those deps visible from wrapper + # for instance luasnip has a dependency on jsregexp + can_require_transitive_deps = + runTest nvim-with-luasnip '' + export HOME=$TMPDIR + cat ${nvim-with-luasnip}/bin/nvim + ${nvim-with-luasnip}/bin/nvim -i NONE --cmd "lua require'jsregexp'" -e + ''; + }) diff --git a/pkgs/applications/editors/neovim/utils.nix b/pkgs/applications/editors/neovim/utils.nix index 8f9a5b880032..902d62d9486a 100644 --- a/pkgs/applications/editors/neovim/utils.nix +++ b/pkgs/applications/editors/neovim/utils.nix @@ -229,12 +229,36 @@ let ln -s ${grammar}/parser $out/parser/${name}.so ''); + /* + Fork of vimUtils.packDir that additionnally generates a propagated-build-inputs-file that + can be used by the lua hooks to generate a proper LUA_PATH + + Generates a packpath folder as expected by vim + Example: + packDir ( {myVimPackage = { start = [ vimPlugins.vim-fugitive ]; opt = []; }; }) + => "/nix/store/xxxxx-pack-dir" + */ + packDir = packages: + let + rawPackDir = vimUtils.packDir packages; + + in + rawPackDir.override ({ + postBuild = '' + mkdir $out/nix-support + for i in $(find -L $out -name propagated-build-inputs ); do + cat "$i" >> $out/nix-support/propagated-build-inputs + done + '';}); + + in { inherit makeNeovimConfig; inherit generateProviderRc; inherit legacyWrapper; inherit grammarToPlugin; + inherit packDir; inherit buildNeovimPlugin; buildNeovimPluginFrom2Nix = lib.warn "buildNeovimPluginFrom2Nix was renamed to buildNeovimPlugin" buildNeovimPlugin; diff --git a/pkgs/applications/editors/neovim/wrapper.nix b/pkgs/applications/editors/neovim/wrapper.nix index e877f1e1f764..d86de46c8738 100644 --- a/pkgs/applications/editors/neovim/wrapper.nix +++ b/pkgs/applications/editors/neovim/wrapper.nix @@ -13,6 +13,9 @@ neovim-unwrapped: let + # inherit interpreter from neovim + lua = neovim-unwrapped.lua; + wrapper = { extraName ? "" # should contain all args but the binary. Can be either a string or list @@ -24,6 +27,8 @@ let , withNodeJs ? false , withPerl ? false , rubyEnv ? null + + # wether to create symlinks in $out/bin/vi(m) -> $out/bin/nvim , vimAlias ? false , viAlias ? false @@ -45,6 +50,8 @@ let stdenv.mkDerivation (finalAttrs: let + finalPackdir = neovimUtils.packDir packpathDirs; + rcContent = '' ${luaRcContent} '' + lib.optionalString (!isNull neovimRcContent) '' @@ -57,10 +64,10 @@ let # vim accepts a limited number of commands so we join them all [ "--add-flags" ''--cmd "lua ${providerLuaRc}"'' - # (lib.intersperse "|" hostProviderViml) - ] ++ lib.optionals (packpathDirs.myNeovimPackages.start != [] || packpathDirs.myNeovimPackages.opt != []) [ - "--add-flags" ''--cmd "set packpath^=${vimUtils.packDir packpathDirs}"'' - "--add-flags" ''--cmd "set rtp^=${vimUtils.packDir packpathDirs}"'' + ] + ++ lib.optionals (packpathDirs.myNeovimPackages.start != [] || packpathDirs.myNeovimPackages.opt != []) [ + "--add-flags" ''--cmd "set packpath^=${finalPackdir}"'' + "--add-flags" ''--cmd "set rtp^=${finalPackdir}"'' ] ; @@ -160,7 +167,17 @@ let + '' rm $out/bin/nvim touch $out/rplugin.vim - makeWrapper ${lib.escapeShellArgs finalMakeWrapperArgs} ${wrapperArgsStr} + + echo "Looking for lua dependencies..." + source ${lua}/nix-support/utils.sh + + _addToLuaPath "${finalPackdir}" + + echo "LUA_PATH towards the end of packdir: $LUA_PATH" + + makeWrapper ${lib.escapeShellArgs finalMakeWrapperArgs} ${wrapperArgsStr} \ + --prefix LUA_PATH ';' "$LUA_PATH" \ + --prefix LUA_CPATH ';' "$LUA_CPATH" ''; buildPhase = '' diff --git a/pkgs/development/interpreters/lua-5/interpreter.nix b/pkgs/development/interpreters/lua-5/interpreter.nix index 7775fa5c8493..497307d57b3f 100644 --- a/pkgs/development/interpreters/lua-5/interpreter.nix +++ b/pkgs/development/interpreters/lua-5/interpreter.nix @@ -54,7 +54,7 @@ stdenv.mkDerivation (finalAttrs: LuaCPathSearchPaths = luaPackages.luaLib.luaCPathList; setupHook = builtins.toFile "lua-setup-hook" '' source @out@/nix-support/utils.sh - addEnvHooks "$hostOffset" addToLuaPath + addEnvHooks "$hostOffset" luaEnvHook ''; nativeBuildInputs = [ makeWrapper ]; diff --git a/pkgs/development/interpreters/lua-5/tests/default.nix b/pkgs/development/interpreters/lua-5/tests/default.nix index c95d11aefc96..768f07cb8400 100644 --- a/pkgs/development/interpreters/lua-5/tests/default.nix +++ b/pkgs/development/interpreters/lua-5/tests/default.nix @@ -96,4 +96,17 @@ in touch $out ''); + + + /* + Check that a lua package's propagatedBuildInputs end up in LUA_PATH + */ + checkPropagatedBuildInputs = pkgs.runCommandLocal "test-${lua.name}-setup-hook" ({ + # lua-curl is a propagatedBuildInput of rest-nvim has + buildInputs = [ lua.pkgs.rest-nvim ]; + }) ('' + ${lua}/bin/lua -e "require'cURL'" + touch $out + ''); + }) diff --git a/pkgs/development/interpreters/lua-5/utils.sh b/pkgs/development/interpreters/lua-5/utils.sh index 5491f8f7ad2d..2365af08dc9c 100644 --- a/pkgs/development/interpreters/lua-5/utils.sh +++ b/pkgs/development/interpreters/lua-5/utils.sh @@ -1,4 +1,8 @@ -#!/bin/sh +#!/bin/bash + +declare -gA luaPathsSeen=() + +# shellcheck disable=SC2164,SC2041 nix_print() { if [ ${NIX_DEBUG:-0} -ge $1 ]; then echo "$2" @@ -33,10 +37,16 @@ addToLuaSearchPathWithCustomDelimiter() { shopt -u globstar } +# used in setup Hooks to load LUA_PATH and LUA_CPATH +# luaEnvHook +luaEnvHook() { + _addToLuaPath "$1" +} + addToLuaPath() { local dir="$1" - if [[ ! -d "$dir" ]]; then + if [ ! -d "$dir" ]; then nix_debug "$dir not a directory abort" return 0 fi @@ -52,3 +62,74 @@ addToLuaPath() { cd - >/dev/null } + +_addToLuaPath() { + local dir="$1" + + echo "_addToLuaPath called for dir $dir" + + if [[ ! -d "$dir" ]]; then + nix_debug "$dir not a directory abort" + return 0 + fi + +# set -x + # if [ -n "${pythonPathsSeen[$dir]}" ]; then return; fi + if [[ -n "${luaPathsSeen[$dir]:-}" ]]; then + # if [ -n "${luaPathsSeen[$dir]}" ]; then + echo "$dir already parsed" + return + fi + + luaPathsSeen["$dir"]=true + + # shellcheck disable=SC2164 + cd "$dir" + for pattern in @luapathsearchpaths@; do + addToLuaSearchPathWithCustomDelimiter LUA_PATH "$PWD/$pattern" + done + + # LUA_CPATH + for pattern in @luacpathsearchpaths@; do + addToLuaSearchPathWithCustomDelimiter LUA_CPATH "$PWD/$pattern" + done + + cd - >/dev/null + + addToSearchPath program_PATH "$dir"/bin + + # Inspect the propagated inputs (if they exist) and recur on them. + local prop="$dir/nix-support/propagated-build-inputs" + if [ -e "$prop" ]; then + local new_path + for new_path in $(cat $prop); do + echo "newpath: $new_path" + _addToLuaPath "$new_path" + done + fi + +} + +# Builds environment variables like LUA_PATH and PATH walking through closure +# of dependencies. +buildLuaPath() { + local luaPath="$1" + local path + + echo "BUILD_LUA_PATH" + +# # set -x +# # Create an empty table of paths (see doc on loadFromPropagatedInputs +# # for how this is used). Build up the program_PATH and program_LUA_PATH +# # variables. + # declare -gA luaPathsSeen=() +# # shellcheck disable=SC2034 + program_PATH= + luaPathsSeen["@lua@"]=1 +# addToSearchPath program_PATH @lua@/bin + for path in $luaPath; do + _addToLuaPath "$path" + done +} + + diff --git a/pkgs/development/interpreters/lua-5/wrap.sh b/pkgs/development/interpreters/lua-5/wrap.sh index 7d59cf609577..f6868e6faac5 100644 --- a/pkgs/development/interpreters/lua-5/wrap.sh +++ b/pkgs/development/interpreters/lua-5/wrap.sh @@ -9,24 +9,6 @@ wrapLuaPrograms() { wrapLuaProgramsIn "$out/bin" "$out $luaPath" } -# Builds environment variables like LUA_PATH and PATH walking through closure -# of dependencies. -buildLuaPath() { - local luaPath="$1" - local path - - # Create an empty table of paths (see doc on loadFromPropagatedInputs - # for how this is used). Build up the program_PATH and program_LUA_PATH - # variables. - declare -A luaPathsSeen=() - program_PATH= - luaPathsSeen["@lua@"]=1 - addToSearchPath program_PATH @lua@/bin - for path in $luaPath; do - addToLuaPath "$path" - done -} - # with an executable shell script which will set some environment variables # and then call into the original binary (which has been given a .wrapped suffix). # luaPath is a list of directories @@ -47,7 +29,6 @@ wrapLuaProgramsIn() { # Find all regular files in the output directory that are executable. find "$dir" -type f -perm -0100 -print0 | while read -d "" f; do # Rewrite "#! .../env lua" to "#! /nix/store/.../lua". - # Strip suffix, like "3" or "2.7m" -- we don't have any choice on which # Lua to use besides one with this hook anyway. if head -n1 "$f" | grep -q '#!.*/env.*\(lua\)'; then sed -i "$f" -e "1 s^.*/env[ ]*\(lua\)[^ ]*^#! @executable@^" @@ -73,28 +54,3 @@ wrapLuaProgramsIn() { done } - -# Adds the lib and bin directories to the LUA_PATH and PATH variables, -# respectively. Recurses on any paths declared in -# `propagated-native-build-inputs`, while avoiding duplicating paths by -# flagging the directories it has visited in `luaPathsSeen`. -loadFromPropagatedInputs() { - local dir="$1" - # Stop if we've already visited here. - if [ -n "${luaPathsSeen[$dir]}" ]; then - return - fi - luaPathsSeen[$dir]=1 - - addToLuaPath "$dir" - addToSearchPath program_PATH $dir/bin - - # Inspect the propagated inputs (if they exist) and recur on them. - local prop="$dir/nix-support/propagated-native-build-inputs" - if [ -e "$prop" ]; then - local new_path - for new_path in $(cat $prop); do - loadFromPropagatedInputs "$new_path" - done - fi -} diff --git a/pkgs/development/interpreters/lua-5/wrapper.nix b/pkgs/development/interpreters/lua-5/wrapper.nix index 07ea75605c0f..6eb94b60360b 100644 --- a/pkgs/development/interpreters/lua-5/wrapper.nix +++ b/pkgs/development/interpreters/lua-5/wrapper.nix @@ -30,7 +30,7 @@ let fi mkdir -p "$out/bin" - addToLuaPath "$out" + buildLuaPath "$out" # take every binary from lua packages and put them into the env for path in ${lib.concatStringsSep " " paths}; do diff --git a/pkgs/development/interpreters/luajit/default.nix b/pkgs/development/interpreters/luajit/default.nix index 3b98e8c79014..25f3332b2602 100644 --- a/pkgs/development/interpreters/luajit/default.nix +++ b/pkgs/development/interpreters/luajit/default.nix @@ -114,7 +114,7 @@ stdenv.mkDerivation (finalAttrs: { setupHook = builtins.toFile "lua-setup-hook" '' source @out@/nix-support/utils.sh - addEnvHooks "$hostOffset" addToLuaPath + addEnvHooks "$hostOffset" luaEnvHook ''; # copied from python