1
1
forked from extern/flakelight

Allow all of devShells config types in devShells

`devShell` accepted either a package def, a submodule value, or a
function to a submodule value. `devShells` only accepted package defs.
This brings all the options of `devShells` to any devShell configured
with `devShells`.
This commit is contained in:
Archit Gupta 2024-02-07 01:15:56 -08:00
parent 543e3aaa4d
commit a50fbcba1a
4 changed files with 58 additions and 30 deletions

View File

@ -541,12 +541,36 @@ To override the devShell, you can use a package definition as such:
### devShells ### devShells
``` ```
Type: (AttrsOf PackageDef) | (ModuleArgs -> (AttrsOf PackageDef)) Type:
devShells: (AttrsOf (PackageDef | Cfg | (Pkgs -> Cfg)) |
(ModuleArgs -> (AttrsOf (PackageDef | Cfg | (Pkgs -> Cfg))))
Cfg.packages: [Derivation] | (Pkgs -> [Derivation])
Cfg.inputsFrom: [Derivation] | (Pkgs -> [Derivation])
Cfg.shellHook: Str | (Pkgs -> Str)
Cfg.env: (AttrsOf Str) | (Pkgs -> (AttrsOf Str))
Cfg.stdenv: Stdenv | (Pkgs -> Stdenv)
``` ```
The `devShells` option allows you to set additional `devShell` outputs. The `devShells` option allows you to set additional `devShell` outputs. The
values each shell can be set to are the same as described above for the
`devShell` option.
For example: For example, using the configuration options:
```nix
{
inputs.flakelight.url = "github:nix-community/flakelight";
outputs = { flakelight, ... }:
flakelight ./. {
devShells.testing = {
packages = pkgs: [ pkgs.coreutils ];
env.TEST_VAR = "in testing shell";
};
};
}
```
For example, using a package definition:
```nix ```nix
{ {
@ -562,7 +586,7 @@ For example:
} }
``` ```
The above exports `devShells.${system}.testing` outputs. The above flakes export `devShells.${system}.testing` outputs.
### overlays ### overlays

View File

@ -4,13 +4,11 @@
{ config, lib, flakelight, genSystems, moduleArgs, ... }: { config, lib, flakelight, genSystems, moduleArgs, ... }:
let let
inherit (lib) filterAttrs functionArgs mapAttrs mkDefault mkIf mkMerge inherit (lib) filterAttrs functionArgs mapAttrs mkIf mkMerge mkOption;
mkOption;
inherit (lib.types) attrs coercedTo functionTo lazyAttrsOf lines listOf inherit (lib.types) attrs coercedTo functionTo lazyAttrsOf lines listOf
package str submodule; package str submodule;
inherit (flakelight) supportedSystem; inherit (flakelight) supportedSystem;
inherit (flakelight.types) function nullable optCallWith optFunctionTo inherit (flakelight.types) function nullable optCallWith optFunctionTo;
packageDef;
devShellModule.options = { devShellModule.options = {
inputsFrom = mkOption { inputsFrom = mkOption {
@ -39,48 +37,51 @@ let
}; };
overrideShell = mkOption { overrideShell = mkOption {
type = nullable packageDef; type = nullable package;
internal = true; internal = true;
default = null; default = null;
}; };
}; };
wrapFn = fn: pkgs: wrapFn = fn: pkgs:
if (functionArgs fn == { }) || !(package.check (pkgs.callPackage fn { })) let val = pkgs.callPackage fn { }; in
if (functionArgs fn == { }) || !(package.check val)
then fn pkgs then fn pkgs
else { overrideShell = fn; }; else { overrideShell = val; };
devShellType = coercedTo function wrapFn
(coercedTo attrs (x: _: x)
(functionTo (submodule devShellModule)));
genDevShell = pkgs: cfg:
if cfg.overrideShell != null then cfg.overrideShell
else
let cfg' = mapAttrs (_: v: v pkgs) cfg; in
pkgs.mkShell.override { inherit (cfg') stdenv; }
(cfg'.env // { inherit (cfg') inputsFrom packages shellHook; });
in in
{ {
options = { options = {
devShell = mkOption { devShell = mkOption {
default = null; default = null;
type = nullable (coercedTo function wrapFn type = nullable devShellType;
(coercedTo attrs (x: _: x)
(functionTo (submodule devShellModule))));
}; };
devShells = mkOption { devShells = mkOption {
type = optCallWith moduleArgs (lazyAttrsOf packageDef); type = optCallWith moduleArgs (lazyAttrsOf devShellType);
default = { }; default = { };
}; };
}; };
config = mkMerge [ config = mkMerge [
(mkIf (config.devShell != null) { (mkIf (config.devShell != null) {
devShells.default = mkDefault ({ pkgs, mkShell }: devShells.default = config.devShell;
let cfg = mapAttrs (_: v: v pkgs) (config.devShell pkgs); in
mkShell.override { inherit (cfg) stdenv; }
(cfg.env // { inherit (cfg) inputsFrom packages shellHook; }));
})
(mkIf (config.devShell.overrideShell or null != null) {
devShells.default = config.devShell.overrideShell;
}) })
(mkIf (config.devShells != { }) { (mkIf (config.devShells != { }) {
outputs.devShells = genSystems (pkgs: outputs.devShells = genSystems (pkgs:
filterAttrs (_: supportedSystem pkgs) filterAttrs (_: supportedSystem pkgs)
(mapAttrs (_: v: pkgs.callPackage v { }) config.devShells)); (mapAttrs (_: v: genDevShell pkgs (v pkgs)) config.devShells));
}) })
]; ];
} }

View File

@ -94,8 +94,7 @@ let
optFunctionTo = elemType: coercedTo elemType (x: _: x) optFunctionTo = elemType: coercedTo elemType (x: _: x)
(functionTo elemType); (functionTo elemType);
optCallWith = args: elemType: coercedTo (functionTo elemType) (x: x args) optCallWith = args: elemType: coercedTo function (x: x args) elemType;
elemType;
nullable = elemType: mkOptionType { nullable = elemType: mkOptionType {
name = "nullable"; name = "nullable";

View File

@ -370,12 +370,16 @@ in
devShell.inputsFrom = pkgs: [ pkgs.emacs ]; devShell.inputsFrom = pkgs: [ pkgs.emacs ];
devShells = { devShells = {
shell1 = { mkShell }: mkShell { }; shell1 = { mkShell }: mkShell { };
shell2 = { mkShell }: mkShell { }; shell2 = { packages = pkgs: [ pkgs.emacs ]; };
shell3 = pkgs: { packages = [ pkgs.emacs ]; };
shell4 = { emacs, ... }: { packages = [ emacs ]; };
}; };
}) })
(f: (f ? devShells.x86_64-linux.default) (f: (lib.isDerivation f.devShells.x86_64-linux.default)
&& (f ? devShells.x86_64-linux.shell1) && (lib.isDerivation f.devShells.x86_64-linux.shell1)
&& (f ? devShells.x86_64-linux.shell2)); && (lib.isDerivation f.devShells.x86_64-linux.shell2)
&& (lib.isDerivation f.devShells.x86_64-linux.shell3)
&& (lib.isDerivation f.devShells.x86_64-linux.shell4));
devShells-override = test devShells-override = test
(flakelight ./empty { (flakelight ./empty {