Skip to content

Commit

Permalink
feat: add internal features for the composer
Browse files Browse the repository at this point in the history
This is the first implementation of the kinds of features atoms will
be able to set on themselves. The internal composer function has the
ability to define it's own features as well.

the semantic for declaring features is basically identical to doing so
in a Cargo.toml from Rust, for those famililar:
```toml
[features]
my_feature = []
my_other_feature = ["my_feature"]
default = ["my_feature"]
```

Here, the default feature enabled is `my_feature` because it is in the
`default` list. When `my_other_feature` is enabled, it also implicitly
enables `my_feature` since it is in it's list.
  • Loading branch information
nrdxp committed Aug 5, 2024
1 parent fda34a5 commit e3ec481
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 38 deletions.
7 changes: 4 additions & 3 deletions compose.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[std]
use = true
nixpkgs_lib = false
[features]
std = []
pkg_lib = ["std"]
default = ["std"]
29 changes: 21 additions & 8 deletions default.nix
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
let
src = import ./src;
l = builtins;
src = import ./src;
pins = import ./npins;
toml = l.fromTOML (l.readFile ./compose.toml);
in
{
extern ? { },
config ? builtins.fromTOML (builtins.readFile ./compose.toml),
# internal features of the composer function
__features ? toml.features.default or [ ],
}:
dir:
with src;
let
std = composeStd ./std;

__features' = src.features.parse toml.features __features;

f =
f: pre: dir':
let
Expand All @@ -28,8 +32,8 @@ let
};

scope =
injectOptionals
{
let
scope' = {
atom = atom';
mod = self';
builtins = errors.builtins;
Expand All @@ -40,19 +44,28 @@ let
__currentTime = errors.time;
__nixPath = errors.nixPath;
__storePath = errors.storePath;
}
[
};

scope'' = injectOptionals scope' [
preOpt
{
_if = config.std.use or false;
_if = l.elem "std" __features';
std =
std
// cond {
_if = config.std.nixpkgs_lib or false;
_if = l.elem "pkg_lib" __features';
lib = import "${pins."nixpkgs.lib"}/lib";
};
}
];
in
scope''
// {
__internal = {
features = __features';
scope = scope'';
};
};

Import = scopedImport scope;

Expand Down
14 changes: 9 additions & 5 deletions src/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
# so instead we abstract them out here, into a manually specified "psuedo-module"
# to keep the core impelementation clean
let
l = builtins;
compose = import ../.;
fix = import ../std/fix.nix;
cond = import ../std/set/cond.nix;
filterMap = scopedImport { std = builtins; } ../std/set/filterMap.nix;
strToPath = scopedImport { std = builtins; } ../std/path/strToPath.nix;
parse = scopedImport { std = builtins; } ../std/file/parse.nix;
stdFilter = import ./stdFilter.nix;
toLowerCase = scopedImport rec {
std = builtins;
mod = scopedImport { inherit std mod; } ../std/string/mod.nix;
} ../std/string/toLowerCase.nix;
stdFilter = import ./stdFilter.nix;
in
{
inherit
Expand All @@ -36,26 +37,29 @@ in
if s == k then null else { ${s} = v; }
);

rmNixSrcs = builtins.filterSource (
rmNixSrcs = l.filterSource (
path: type:
let
file = parse (baseNameOf path);
in
(type == "regular" && file.ext or null != "nix")
|| (type == "directory" && !builtins.pathExists "${path}/mod.nix")
|| (type == "directory" && !l.pathExists "${path}/mod.nix")
);

composeStd = path: compose { } path // filterMap stdFilter builtins;

modIsValid =
mod: dir:
builtins.isAttrs mod
l.isAttrs mod
|| throw ''
The following module does not evaluate to a valid attribute set:
${toString dir}/mod.nix
'';

injectOptionals = builtins.foldl' (acc: x: acc // cond x);
injectOptionals = l.foldl' (acc: x: acc // cond x);

hasMod = contents: contents."mod.nix" or null == "regular";

features.parse =
featureSet: l.foldl' (xs: x: if l.elem x xs then xs else [ x ] ++ featureSet.${x} ++ xs) [ ];
}
12 changes: 3 additions & 9 deletions test/std-import/import.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,7 @@ let
in
{
default = compose { };
noStd = compose { config.std.use = false; };
withNixpkgsLib = compose {
config.std.nixpkgs_lib = true;
config.std.use = true;
};
noStdNixpkgs = compose {
config.std.nixpkgs_lib = true;
config.std.use = false;
};
noStd = compose { __features = [ ]; };
explicit = compose { __features = [ "std" ]; };
withNixpkgsLib = compose { __features = [ "pkg_lib" ]; };
}
36 changes: 25 additions & 11 deletions test/std-import/import.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,34 @@

set -ex

. ../common.sh

# defaults
nix eval -f import.nix default.std
should_fail nix eval -f import.nix default.lib
f="$(nix eval -f import.nix default.std)"
[[ "$f" == true ]]
f="$(nix eval -f import.nix default.lib)"
[[ "$f" == false ]]
f="$(nix eval -f import.nix default.core)"
[[ "$f" == '[ "std" ]' ]]

# no std set
should_fail nix eval -f import.nix noStd.std
should_fail nix eval -f import.nix noStd.lib
# explicit
f="$(nix eval -f import.nix explicit.std)"
[[ "$f" == true ]]
f="$(nix eval -f import.nix explicit.lib)"
[[ "$f" == false ]]
f="$(nix eval -f import.nix explicit.core)"
[[ "$f" == '[ "std" ]' ]]

# no std set
nix eval -f import.nix withNixpkgsLib.std
nix eval -f import.nix withNixpkgsLib.lib
f="$(nix eval -f import.nix noStd.std)"
[[ "$f" == false ]]
f="$(nix eval -f import.nix noStd.lib)"
[[ "$f" == false ]]
f="$(nix eval -f import.nix noStd.core)"
[[ "$f" == '[ ]' ]]

# no std set
should_fail nix eval -f import.nix noStdNixpkgs.std
should_fail nix eval -f import.nix noStdNixpkgs.lib
f="$(nix eval -f import.nix withNixpkgsLib.std)"
[[ "$f" == true ]]
f="$(nix eval -f import.nix withNixpkgsLib.lib)"
[[ "$f" == true ]]
f="$(nix eval -f import.nix withNixpkgsLib.core)"
[[ "$f" == '[ "pkg_lib" "std" ]' ]]
8 changes: 6 additions & 2 deletions test/std-import/import/mod.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
let
inherit (__internal) scope features;
in
{
Std = std ? set || abort "std missing";
Lib = std ? lib || abort "lib missing";
Std = scope ? std;
Lib = scope ? std && scope.std ? lib;
Core = features;
}

0 comments on commit e3ec481

Please sign in to comment.