How to override CoC Vim plugin?

I know how to override a Vim plugin but I’m having trouble in understanding how I can override a Vim plugin that depends on NodeJs, as it is the case with any coc.nvim plugin.

I want to override coc-metals, specifically, which is defined under vim-plugins/generated.nix.

The override compiles fine (using Home Manager) but it still brings in the old version defined in nodePackages if I don’t override this one too.

I tried defining an overlay in this way:

self: super:

{
  nodePackages = super.nodePackages.coc-metals.override {
    coc-metals = (super.callPackage ./programs/neovim/node-pkgs.nix {}).coc-metals;
  };
}

Where node-pkgs.nix is defined as follows (truncating dependencies to make it short):

{ nodeEnv, globalBuildInputs ? [], ... }:

{
  coc-metals = nodeEnv.buildNodePackage {
    name = "coc-metals";
    packageName = "coc-metals";
    version = "0.9.0";
    src = fetchurl {
      url    = "https://registry.npmjs.org/coc-metals/-/coc-metals-0.9.0.tgz";
      sha512 = "DfDQbgbnau8CvTa1uEkYuZnMSaOqnQDvNxbwRi24q3t8z/DwMwEubon/lITGM02CkQH5PnfhE5fJYxt6/Q1wvA==";
    };
    dependencies = [ ... ];
    buildInputs = globalBuildInputs;
    meta = {
      description = "coc.nvim extension for Metals, the Scala language server";
      license = "Apache-2.0";
    };
    production = true;
    bypassCache = true;
    reconstructLock = true;
  };
}

And another override of the vim plugin:

{ pkgs, nodePackages, ... }:

{
  coc-metals = pkgs.vimUtils.buildVimPluginFrom2Nix {
    pname = "coc-metals";
    version = nodePackages.coc-metals.version;
    src = "${nodePackages.coc-metals}/lib/node_modules/coc-metals";
  };
}

Finally, I define the overlay in home.nix to be available by the time Home Manager runs:

  nixpkgs.overlays = [
    (import ./node-overlay.nix)
  ];

There are a lot of moving parts involved and I am not sure if this is the right way to do it. I tried many things and I always get different errors. If anyone familiar with this can shed any light, that would be highly appreciated :blush:

I’m still trying to override a coc.nvim plugin (needs NodeJS), not giving up on it but it’s getting frustrating :smile:

I’ve got the following definition of the Vim plugin in the coc-plugins.nix file

{ pkgs, lib, fetchFromGitHub, overrides ? (self: super: {}), ... }:

let
  packages = (
    self: {
      coc-metals = pkgs.vimUtils.buildVimPlugin {
        name = "coc-metals";
        src = builtins.fetchTarball {
          name   = "coc-metals-v0.9.0";
          url    = "https://github.com/scalameta/coc-metals/archive/v0.9.0.tar.gz";
          sha256 = "0r4xs0mhdxvac81cly89jqnby14h1dmrpkdfs0chz5ji4gbsgair";
        };
      };
    }
  );
in
lib.fix' (lib.extends overrides packages)

And the following in the overrides.nix file:

self: super:

{
  coc-metals = super.vimUtils.buildVimPluginFrom2Nix {
    pname   = "coc-metals";
    version = super.nodePackages.coc-metals.version;
    src     = "${super.nodePackages.coc-metals}/lib/node_modules/coc-metals";
  };  
}

Then I make use of it via Home Manager in my home.nix file:

  overrides = pkgs.callPackage ./overrides.nix {
    inherit pkgs;
  };

  coc-plugins = pkgs.callPackage ./coc-plugins.nix {
    inherit pkgs fetchFromGitHub overrides;
  };

  custom-plugins = pkgs.callPackage ./custom-plugins.nix {};

  #plugins        = pls // custom-plugins;
  plugins        = pkgs.vimPlugins // coc-plugins // custom-plugins;

  vimPlugins = with plugins; [
    coc-nvim                # LSP client + autocompletion plugin
    coc-metals              # Scala LSP client for CoC
  ]

And I get the following error, which I believe comes from the usage of lib.fix' (lib.extends overrides packages) that I blindly copied from Nixpkgs and I don’t fully understand:

error: attempt to call something which is not a function but a set, at /nix/store/r4701ch1l8mgr9jzysinb00b4a39wayk-nixos-20.09pre233323.dc80d7bc4a2/nixos/lib/fixed-points.nix:69:67

Can anyone help me understand what’s going on here? I don’t see the difference with the original: https://github.com/NixOS/nixpkgs/blob/05a50430663c1d289cd5de4065aa387123bf363d/pkgs/misc/vim-plugins/default.nix#L8

Any pointers would be highly appreciated, been stuck for a few days already.

Okay, I solved the previous issue and I got Home Manager compiling my build but still coc-metals doesn’t get overridden. Here’s what I have now:

{ buildVimPluginFrom2Nix, lib, nodePackages, vimPlugins }:

let
  overrides = (
    self: super:
      {
        coc-metals = buildVimPluginFrom2Nix {
          pname = "coc-metals";
          version = nodePackages.coc-metals.version;
          src = "${nodePackages.coc-metals}/lib/node_modules/coc-metals";
        };
      }
  );

  packages = (
    self: {
      coc-metals = buildVimPluginFrom2Nix {
        pname = "coc-metals";
        version = "0.9.0";
        src = builtins.fetchTarball {
          name = "coc-metals-v0.9.0";
          url = "https://github.com/scalameta/coc-metals/archive/v0.9.0.tar.gz";
          sha256 = "0r4xs0mhdxvac81cly89jqnby14h1dmrpkdfs0chz5ji4gbsgair";
        };
        meta.homepage = "https://github.com/scalameta/coc-metals/";
      };
    }
  );
in
lib.fix' (lib.extends overrides packages)

I still don’t understand how this works in Nixpkgs. Defining a coc-metals to immediately override it with nodePackages.coc-metals doesn’t make sense to me, and in fact, this doesn’t work. If I inspect what’s under /nix/store/ with the coc-metals name, I get this (no coc-metals-0.9.0):

/nix/store/84zrzj6pg5x0qz0pp32xl5lwbv77wh2p-vimplugin-coc-metals-0.8.3/share/vim-plugins/coc-metals
/nix/store/3222zm8dw7sqwrj2kzadxryhyd3ia5jg-vim-pack-dir/pack/home-manager/start/coc-metals
/nix/store/wl72b645hx8l98ffapxjm1j11f4yffzc-node_coc-metals-0.9.0/lib/node_modules/coc-metals

But if I leave the overrides empty as {}, then I see these outputs under /nix/store/:

/nix/store/84zrzj6pg5x0qz0pp32xl5lwbv77wh2p-vimplugin-coc-metals-0.8.3/share/vim-plugins/coc-metals
/nix/store/rg3s5gvilvzyay2zm7syvds32nd3n3s8-vimplugin-coc-metals-0.9.0/share/vim-plugins/coc-metals
/nix/store/grzjhrc61y86qs99yvpm8iks3hwr9r7k-vim-pack-dir/pack/home-manager/start/coc-metals
/nix/store/3222zm8dw7sqwrj2kzadxryhyd3ia5jg-vim-pack-dir/pack/home-manager/start/coc-metals
/nix/store/wl72b645hx8l98ffapxjm1j11f4yffzc-node_coc-metals-0.9.0/lib/node_modules/coc-metals

Here I can see that the new version of coc-metals was built, which doesn’t happen with the overrides.

On the other hand, I have an overlay for nodePackages.coc-metals, which is compiling and I can see its output under /nix/store/ but I don’t know if it’s being picked up by vimPlugins. It looks as follows (skipping the dependencies for conciseness):

self: super:

{
  coc-metals = super.nodePackages.coc-metals.overrideAttrs (
    old: {
      name        = "coc-metals";
      packageName = "coc-metals";
      version     = "0.9.0";
      src = builtins.fetchurl {
        url    = "https://registry.npmjs.org/coc-metals/-/coc-metals-0.9.0.tgz";
        sha512 = "rQPCK+x+/Aij/YqjGTIS5c5WA3dPba2RwubGouXSRkl8+F1I4NyAXiXtHAx2V4W1LYvmjd990i6Dtzr3JLx+5A==";
      };
    }
  );
}

I would appreciate any help. Thanks.