{ lib }:

with builtins;

rec {

  # Derive a file by substituting
  # "${pkgs.foo}/bin/foo" for each {-pkg-}"foo", and
  # "${pkgs.bar}/bin/foo" for each {-pkg:bar-}"foo".
  # If a package doesn't exist, a warning gets printed.
  substitutePkgs = name: { callsite ? null, pkgs, path }:
    pkgs.writeText name (substitutePkgs' {
      inherit pkgs;
      sourceDescription =
        if callsite != null then
          "${name} in ${toString callsite}"
        else
          "${name} from ${toString path}";
      text = readFile path;
    });

  substitutePkgs' = { pkgs, sourceDescription, text }:
    let
      f = s:
        let
          parse = match "(.*)([{]-pkg(:([^}]+))?-[}]\"([^\"]+)\")(.*)" s;
          prefix = elemAt parse 0;
          pname = if elemAt parse 3 != null then elemAt parse 3 else exename;
          exename = elemAt parse 4;
          suffix = elemAt parse 5;
          pkg = pkgs.${pname} or null;

          substitute =
            if pkg != null then
              "${pkg}/bin/${exename}"
            else
              trace (toString [
                "lib.haskell.replacePkg:"
                "warning:"
                "while deriving ${sourceDescription}:"
                "no substitute found for ${elemAt parse 1}"
              ])
              exename;
        in
        if parse == null then
          s
        else
          f (prefix + toJSON substitute + suffix);
    in
    f text;
}
