{ pkgs }: # This builds devshells using passthru to populate packages and inputsFrom # lazily. # # Packages prefixed with @ are added to inputsFrom and the rest are # added to packages. This makes it possible to obtain a devshell with combining # inputsFrom and packages from the comand line: # # $ nix develop .#quickShell.@nosv.clang-tools.ovni.@tampi # # is equivalent to: # # with pkgs; mkShell { # packages = [ clang-tools ovni ]; # inputsFrom = [ nosv tampi ]; # } # let inherit (builtins) attrNames getAttr listToAttrs; inherit (pkgs) lib; # list of all packages' names names = attrNames pkgs; # generate a attributes containing the selected packages + all the available # packages in names ("" -> packages and "@" -> inputsFrom) go = selected: let mkAttrs = isInputs: (map ( name: let pkg = getAttr name pkgs; in { name = (if isInputs then "@" else "") + name; value = go ( if isInputs then { inherit (selected) packages; inputsFrom = selected.inputsFrom ++ [ pkg ]; } else { inherit (selected) inputsFrom; packages = selected.packages ++ [ pkg ]; } ); } ) names); attrs = listToAttrs ((mkAttrs true) ++ (mkAttrs false)); drv = pkgs.mkShell { inherit (selected) inputsFrom packages; name = # build a label from inputsFrom if (selected.inputsFrom == [ ]) then "nix-quick-shell" else lib.concatStringsSep "-" (map (v: v.pname or v.name or "unknown") selected.inputsFrom); }; in drv.overrideAttrs { passthru = attrs // { _passthru = drv.passthru; }; }; in go { inputsFrom = [ ]; packages = [ ]; }