about summary refs log tree commit diff
path: root/pkgs/misc/vim-plugins/vim-utils.nix
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/misc/vim-plugins/vim-utils.nix')
-rw-r--r--pkgs/misc/vim-plugins/vim-utils.nix136
1 files changed, 56 insertions, 80 deletions
diff --git a/pkgs/misc/vim-plugins/vim-utils.nix b/pkgs/misc/vim-plugins/vim-utils.nix
index 7122e2a42306..61e89521c8c9 100644
--- a/pkgs/misc/vim-plugins/vim-utils.nix
+++ b/pkgs/misc/vim-plugins/vim-utils.nix
@@ -1,4 +1,4 @@
-{stdenv, vim, vimPlugins, vim_configurable, buildEnv, writeText, writeScriptBin
+{stdenv, vim, vimPlugins, vim_configurable, neovim, buildEnv, writeText, writeScriptBin
 , nix-prefetch-hg, nix-prefetch-git }:
 
 /*
@@ -150,23 +150,35 @@ vim_with_plugins can be installed like any other application within Nix.
 let
   inherit (stdenv) lib;
 
-  toNames = x:
-      if builtins.isString x then [x]
-      else (lib.optional (x ? name) x.name)
-            ++ (x.names or []);
-  findDependenciesRecursively = {knownPlugins, names}:
+  # transitive closure of plugin dependencies
+  transitiveClosure = knownPlugins: plugin:
+  let
+    # vam puts out a list of strings as the dependency list, we need to be able to deal with that.
+    # Because of that, "plugin" may be a string or a derivation. If it is a string, it is resolved
+    # using `knownPlugins`. Otherwise `knownPlugins` can be null.
+    knownPlugins' = if knownPlugins == null then vimPlugins else knownPlugins;
+    pluginDrv = if builtins.isString plugin then knownPlugins'.${plugin} else plugin;
+  in
+    [ pluginDrv ] ++ (
+      lib.unique (builtins.concatLists (map (transitiveClosure knownPlugins) pluginDrv.dependencies or []))
+    );
 
-    let depsOf = name: (builtins.getAttr name knownPlugins).dependencies or [];
+  findDependenciesRecursively = knownPlugins: plugins: lib.concatMap (transitiveClosure knownPlugins) plugins;
 
-        recurseNames = path: names: lib.concatMap (name: recurse ([name]++path)) names;
+  attrnamesToPlugins = { knownPlugins, names }:
+    map (name: if builtins.isString name then knownPlugins.${name} else name) knownPlugins;
 
-        recurse = path:
-          let name = builtins.head path;
-          in if builtins.elem name (builtins.tail path)
-            then throw "recursive vim dependencies"
-            else [name] ++ recurseNames path (depsOf name);
+  pluginToAttrname = plugin:
+    plugin.pname;
+
+  pluginsToAttrnames = plugins: map pluginToAttrname plugins;
+
+  vamDictToNames = x:
+      if builtins.isString x then [x]
+      else (lib.optional (x ? name) x.name)
+            ++ (x.names or []);
 
-    in lib.uniqList { inputList = recurseNames [] names; };
+  rtpPath = "share/vim-plugins";
 
   vimrcFile = {
     packages ? null,
@@ -183,11 +195,11 @@ let
       (let
         knownPlugins = pathogen.knownPlugins or vimPlugins;
 
-        plugins = map (name: knownPlugins.${name}) (findDependenciesRecursively { inherit knownPlugins; names = pathogen.pluginNames; });
+        plugins = findDependenciesRecursively knownPlugins pathogen.pluginNames;
 
         pluginsEnv = buildEnv {
           name = "pathogen-plugin-env";
-          paths = map (x: "${x}/${vimPlugins.rtpPath}") plugins;
+          paths = map (x: "${x}/${rtpPath}") plugins;
         };
       in
       ''
@@ -228,7 +240,7 @@ let
       (let
         knownPlugins = vam.knownPlugins or vimPlugins;
 
-        names = findDependenciesRecursively { inherit knownPlugins; names = lib.concatMap toNames vam.pluginDictionaries; };
+        plugins = findDependenciesRecursively knownPlugins (lib.concatMap vamDictToNames vam.pluginDictionaries);
 
         # Vim almost reads JSON, so eventually JSON support should be added to Nix
         # TODO: proper quoting
@@ -242,9 +254,9 @@ let
       in assert builtins.hasAttr "vim-addon-manager" knownPlugins;
       ''
         let g:nix_plugin_locations = {}
-        ${lib.concatMapStrings (name: ''
-          let g:nix_plugin_locations['${name}'] = "${knownPlugins.${name}.rtp}"
-        '') names}
+        ${lib.concatMapStrings (plugin: ''
+          let g:nix_plugin_locations['${plugin.pname}'] = "${plugin.rtp}"
+        '') plugins}
         let g:nix_plugin_locations['vim-addon-manager'] = "${knownPlugins."vim-addon-manager".rtp}"
 
         let g:vim_addon_manager = {}
@@ -281,8 +293,18 @@ let
       (let
         link = (packageName: dir: pluginPath: "ln -sf ${pluginPath}/share/vim-plugins/* $out/pack/${packageName}/${dir}");
         packageLinks = (packageName: {start ? [], opt ? []}:
+        let
+          # `nativeImpl` expects packages to be derivations, not strings (as
+          # opposed to older implementations that have to maintain backwards
+          # compatibility). Therefore we don't need to deal with "knownPlugins"
+          # and can simply pass `null`.
+          depsOfOptionalPlugins = lib.subtractLists opt (findDependenciesRecursively null opt);
+          startWithDeps = findDependenciesRecursively null start;
+        in
           ["mkdir -p $out/pack/${packageName}/start"]
-          ++ (builtins.map (link packageName "start") start)
+          # To avoid confusion, even dependencies of optional plugins are added
+          # to `start` (except if they are explicitly listed as optional plugins).
+          ++ (builtins.map (link packageName "start") (lib.unique (startWithDeps ++ depsOfOptionalPlugins)))
           ++ ["mkdir -p $out/pack/${packageName}/opt"]
           ++ (builtins.map (link packageName "opt") opt)
         );
@@ -381,62 +403,11 @@ rec {
     '';
   };
 
-  rtpPath = "share/vim-plugins";
-
-  vimHelpTags = ''
-  vimHelpTags(){
-    if [ -d "$1/doc" ]; then
-      ${vim}/bin/vim -N -u NONE -i NONE -n -E -s -c "helptags $1/doc" +quit! || echo "docs to build failed"
-    fi
-  }
-  '';
-
-  addRtp = path: attrs: derivation:
-    derivation // { rtp = "${derivation}/${path}"; } // {
-      overrideAttrs = f: buildVimPlugin (attrs // f attrs);
-    };
-
-  buildVimPlugin = a@{
-    name,
-    namePrefix ? "vimplugin-",
-    src,
-    unpackPhase ? "",
-    configurePhase ? "",
-    buildPhase ? "",
-    preInstall ? "",
-    postInstall ? "",
-    path ? (builtins.parseDrvName name).name,
-    addonInfo ? null,
-    ...
-  }:
-    addRtp "${rtpPath}/${path}" a (stdenv.mkDerivation (a // {
-      name = namePrefix + name;
-
-      inherit unpackPhase configurePhase buildPhase addonInfo preInstall postInstall;
-
-      installPhase = ''
-        runHook preInstall
-
-        target=$out/${rtpPath}/${path}
-        mkdir -p $out/${rtpPath}
-        cp -r . $target
-        ${vimHelpTags}
-        vimHelpTags $target
-        if [ -n "$addonInfo" ]; then
-          echo "$addonInfo" > $target/addon-info.json
-        fi
-
-        runHook postInstall
-      '';
-    }));
-
   vim_with_vim2nix = vim_configurable.customize { name = "vim"; vimrcConfig.vam.pluginDictionaries = [ "vim-addon-vim2nix" ]; };
 
-  buildVimPluginFrom2Nix = a: buildVimPlugin ({
-    buildPhase = ":";
-    configurePhase =":";
-  } // a);
+  inherit (import ./build-vim-plugin.nix { inherit stdenv rtpPath vim; }) buildVimPlugin buildVimPluginFrom2Nix;
 
+  # used to figure out which python dependencies etc. neovim needs
   requiredPlugins = {
     packages ? {},
     givenKnownPlugins ? null,
@@ -450,13 +421,13 @@ rec {
                      if vam != null && vam ? knownPlugins then vam.knownPlugins else
                      if pathogen != null && pathogen ? knownPlugins then pathogen.knownPlugins else
                      vimPlugins;
-      pathogenNames = map (name: knownPlugins.${name}) (findDependenciesRecursively { inherit knownPlugins; names = pathogen.pluginNames; });
-      vamNames = findDependenciesRecursively { inherit knownPlugins; names = lib.concatMap toNames vam.pluginDictionaries; };
-      names = (lib.optionals (pathogen != null) pathogenNames) ++
-              (lib.optionals (vam != null) vamNames);
-      nonNativePlugins = map (name: knownPlugins.${name}) names ++ (lib.optionals (plug != null) plug.plugins);
+      pathogenPlugins = findDependenciesRecursively knownPlugins pathogen.pluginNames;
+      vamPlugins = findDependenciesRecursively knownPlugins (lib.concatMap vamDictToNames vam.pluginDictionaries);
+      nonNativePlugins = (lib.optionals (pathogen != null) pathogenPlugins)
+                      ++ (lib.optionals (vam != null) vamPlugins)
+                      ++ (lib.optionals (plug != null) plug.plugins);
       nativePluginsConfigs = lib.attrsets.attrValues packages;
-      nativePlugins = lib.concatMap ({start?[], opt?[]}: start++opt) nativePluginsConfigs;
+      nativePlugins = lib.concatMap ({start?[], opt?[], knownPlugins?vimPlugins}: start++opt) nativePluginsConfigs;
     in
       nativePlugins ++ nonNativePlugins;
 
@@ -481,4 +452,9 @@ rec {
     name = "vim-with-vim-addon-nix";
     vimrcConfig.packages.myVimPackage.start = with vimPlugins; [ vim-nix ];
   };
+
+  # only neovim makes use of `requiredPlugins`, test this here
+  test_nvim_with_vim_nix_using_pathogen = neovim.override {
+    configure.pathogen.pluginNames = [ "vim-nix" ];
+  };
 }