From d4894355c114e6950d7cb844c0220c91098cf479 Mon Sep 17 00:00:00 2001 From: Matthieu Coudron Date: Mon, 2 May 2022 00:58:41 +0200 Subject: [PATCH] vim/update.py: distinguish between vim/neovim plugins I've been working for a long time towards automatic nix dependencies for neovim plugins (using luarocks rockspecs to discover the said dependencies). This is an initial commit to help me complete the missing bits. buildNeovimPluginFrom2Nix is right now a placeholder which helps me test in my fork a version that does a flat install of luarocks. the vim updater will now check for attributes with the same name in the lua package set, if that's the case the script will generate buildNeovimPluginFrom2Nix. --- maintainers/scripts/pluginupdate.py | 18 ++++-- .../editors/vim/plugins/default.nix | 4 +- .../editors/vim/plugins/update.py | 63 ++++++++++++++----- .../editors/vim/plugins/vim-utils.nix | 5 ++ 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/maintainers/scripts/pluginupdate.py b/maintainers/scripts/pluginupdate.py index b24d75a6b4d..55eda3c7d45 100644 --- a/maintainers/scripts/pluginupdate.py +++ b/maintainers/scripts/pluginupdate.py @@ -311,6 +311,16 @@ def load_plugins_from_csv(config: FetchConfig, input_file: Path,) -> List[Plugin return plugins +def run_nix_expr(expr): + with CleanEnvironment(): + cmd = ["nix", "eval", "--extra-experimental-features", + "nix-command", "--impure", "--json", "--expr", expr] + log.debug("Running command %s", cmd) + out = subprocess.check_output(cmd) + data = json.loads(out) + return data + + class Editor: """The configuration of the update script.""" @@ -333,13 +343,9 @@ class Editor: self.deprecated = deprecated or root.joinpath("deprecated.json") self.cache_file = cache_file or f"{name}-plugin-cache.json" - def get_current_plugins(editor) -> List[Plugin]: + def get_current_plugins(self) -> List[Plugin]: """To fill the cache""" - with CleanEnvironment(): - cmd = ["nix", "eval", "--extra-experimental-features", "nix-command", "--impure", "--json", "--expr", editor.get_plugins] - log.debug("Running command %s", cmd) - out = subprocess.check_output(cmd) - data = json.loads(out) + data = run_nix_expr(self.get_plugins) plugins = [] for name, attr in data.items(): print("get_current_plugins: name %s" % name) diff --git a/pkgs/applications/editors/vim/plugins/default.nix b/pkgs/applications/editors/vim/plugins/default.nix index cd5a1f9d6e5..c6ef409d637 100644 --- a/pkgs/applications/editors/vim/plugins/default.nix +++ b/pkgs/applications/editors/vim/plugins/default.nix @@ -3,7 +3,8 @@ let - inherit (vimUtils.override {inherit vim;}) buildVimPluginFrom2Nix vimGenDocHook vimCommandCheckHook; + inherit (vimUtils.override {inherit vim;}) + buildVimPluginFrom2Nix vimGenDocHook vimCommandCheckHook; inherit (lib) extends; @@ -24,6 +25,7 @@ let plugins = callPackage ./generated.nix { inherit buildVimPluginFrom2Nix; + inherit (vimUtils) buildNeovimPluginFrom2Nix; }; # TL;DR diff --git a/pkgs/applications/editors/vim/plugins/update.py b/pkgs/applications/editors/vim/plugins/update.py index ad1c38cb375..1214e36372a 100755 --- a/pkgs/applications/editors/vim/plugins/update.py +++ b/pkgs/applications/editors/vim/plugins/update.py @@ -26,19 +26,24 @@ from typing import List, Tuple from pathlib import Path log = logging.getLogger() -log.addHandler(logging.StreamHandler()) + +sh = logging.StreamHandler() +formatter = logging.Formatter('%(name)s:%(levelname)s: %(message)s') +sh.setFormatter(formatter) +log.addHandler(sh) # Import plugin update library from maintainers/scripts/pluginupdate.py ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) # Ideally, ROOT.(parent^5) points to root of Nixpkgs official tree sys.path.insert(0, os.path.join(ROOT.parent.parent.parent.parent.parent, "maintainers", "scripts")) import pluginupdate +from pluginupdate import run_nix_expr, PluginDesc GET_PLUGINS = f"""(with import {{}}; let - inherit (vimUtils.override {{inherit vim;}}) buildVimPluginFrom2Nix; + inherit (vimUtils.override {{inherit vim;}}) buildNeovimPluginFrom2Nix buildVimPluginFrom2Nix; generated = callPackage {ROOT}/generated.nix {{ - inherit buildVimPluginFrom2Nix; + inherit buildNeovimPluginFrom2Nix buildVimPluginFrom2Nix; }}; hasChecksum = value: lib.isAttrs value && lib.hasAttrByPath ["src" "outputHash"] value; getChecksum = name: value: @@ -50,43 +55,69 @@ let checksums = lib.mapAttrs getChecksum generated; in lib.filterAttrs (n: v: v != null) checksums)""" +GET_PLUGINS_LUA = """ +with import {}; +lib.attrNames lua51Packages""" + HEADER = ( "# This file has been generated by ./pkgs/applications/editors/vim/plugins/update.py. Do not edit!" ) +def isNeovimPlugin(plug: pluginupdate.Plugin) -> bool: + ''' + Whether it's a neovim-only plugin + We can check if it's available in lua packages + ''' + global luaPlugins + if plug.normalized_name in luaPlugins: + log.debug("%s is a neovim plugin", plug) + return True + return False + class VimEditor(pluginupdate.Editor): - def generate_nix(self, plugins: List[Tuple[pluginupdate.PluginDesc, pluginupdate.Plugin]], outfile: str): + def generate_nix(self, plugins: List[Tuple[PluginDesc, pluginupdate.Plugin]], outfile: str): sorted_plugins = sorted(plugins, key=lambda v: v[0].name.lower()) with open(outfile, "w+") as f: f.write(HEADER) f.write(textwrap.dedent(""" - { lib, buildVimPluginFrom2Nix, fetchFromGitHub, fetchgit }: + { lib, buildVimPluginFrom2Nix, buildNeovimPluginFrom2Nix, fetchFromGitHub, fetchgit }: final: prev: - {""" + { + """ )) for pdesc, plugin in sorted_plugins: + content = self.plugin2nix(pdesc, plugin) + f.write(content) + f.write("\n}\n") + print(f"updated {outfile}") - repo = pdesc.repo - src_nix = repo.as_nix(plugin) - f.write( - f""" - {plugin.normalized_name} = buildVimPluginFrom2Nix {{ + def plugin2nix(self, pdesc: PluginDesc, plugin: pluginupdate.Plugin) -> str: + + repo = pdesc.repo + isNeovim = isNeovimPlugin(plugin) + + content = f" {plugin.normalized_name} = " + src_nix = repo.as_nix(plugin) + content += """{buildFn} {{ pname = "{plugin.name}"; version = "{plugin.version}"; src = {src_nix}; meta.homepage = "{repo.uri}"; }}; -""" - ) - f.write("\n}\n") - print(f"updated {outfile}") - +""".format( + buildFn="buildNeovimPluginFrom2Nix" if isNeovim else "buildVimPluginFrom2Nix", plugin=plugin, src_nix=src_nix, repo=repo) + print(content) + return content def main(): + + global luaPlugins + luaPlugins = run_nix_expr(GET_PLUGINS_LUA) + editor = VimEditor("vim", ROOT, GET_PLUGINS) parser = editor.create_parser() args = parser.parse_args() diff --git a/pkgs/applications/editors/vim/plugins/vim-utils.nix b/pkgs/applications/editors/vim/plugins/vim-utils.nix index 5e19d33d19d..e685e398fc2 100644 --- a/pkgs/applications/editors/vim/plugins/vim-utils.nix +++ b/pkgs/applications/editors/vim/plugins/vim-utils.nix @@ -535,6 +535,11 @@ rec { inherit lib stdenv rtpPath vim vimGenDocHook vimCommandCheckHook; }) buildVimPlugin buildVimPluginFrom2Nix; + + # TODO placeholder to ease working on automatic plugin detection + # this should be a luarocks "flat" install with appropriate vim hooks + buildNeovimPluginFrom2Nix = buildVimPluginFrom2Nix; + # used to figure out which python dependencies etc. neovim needs requiredPlugins = { packages ? {},