lib/types: Add types.submoduleWith for more flexibility than types.submodule
This commit is contained in:
parent
3cc77ce756
commit
5002e6afbc
1 changed files with 47 additions and 15 deletions
|
@ -358,25 +358,41 @@ rec {
|
||||||
};
|
};
|
||||||
|
|
||||||
# A submodule (like typed attribute set). See NixOS manual.
|
# A submodule (like typed attribute set). See NixOS manual.
|
||||||
submodule = opts:
|
submodule = modules: submoduleWith {
|
||||||
|
shorthandOnlyDefinesConfig = true;
|
||||||
|
modules = toList modules;
|
||||||
|
};
|
||||||
|
|
||||||
|
submoduleWith =
|
||||||
|
{ modules
|
||||||
|
, specialArgs ? {}
|
||||||
|
, shorthandOnlyDefinesConfig ? false
|
||||||
|
}@attrs:
|
||||||
let
|
let
|
||||||
opts' = toList opts;
|
|
||||||
inherit (lib.modules) evalModules;
|
inherit (lib.modules) evalModules;
|
||||||
|
|
||||||
|
coerce = unify: value: if isFunction value
|
||||||
|
then setFunctionArgs (args: unify (value args)) (functionArgs value)
|
||||||
|
else unify (if shorthandOnlyDefinesConfig then { config = value; } else value);
|
||||||
|
|
||||||
|
allModules = defs: modules ++ imap1 (n: { value, file }:
|
||||||
|
# Annotate the value with the location of its definition for better error messages
|
||||||
|
coerce (lib.modules.unifyModuleSyntax file "${toString file}-${toString n}") value
|
||||||
|
) defs;
|
||||||
|
|
||||||
in
|
in
|
||||||
mkOptionType rec {
|
mkOptionType rec {
|
||||||
name = "submodule";
|
name = "submodule";
|
||||||
check = x: isAttrs x || isFunction x;
|
check = x: isAttrs x || isFunction x;
|
||||||
merge = loc: defs:
|
merge = loc: defs:
|
||||||
let
|
(evalModules {
|
||||||
coerce = def: if isFunction def then def else { config = def; };
|
modules = allModules defs;
|
||||||
modules = opts' ++ map (def: { _file = def.file; imports = [(coerce def.value)]; }) defs;
|
inherit specialArgs;
|
||||||
in (evalModules {
|
|
||||||
inherit modules;
|
|
||||||
args.name = last loc;
|
args.name = last loc;
|
||||||
prefix = loc;
|
prefix = loc;
|
||||||
}).config;
|
}).config;
|
||||||
getSubOptions = prefix: (evalModules
|
getSubOptions = prefix: (evalModules
|
||||||
{ modules = opts'; inherit prefix;
|
{ inherit modules prefix specialArgs;
|
||||||
# This is a work-around due to the fact that some sub-modules,
|
# This is a work-around due to the fact that some sub-modules,
|
||||||
# such as the one included in an attribute set, expects a "args"
|
# such as the one included in an attribute set, expects a "args"
|
||||||
# attribute to be given to the sub-module. As the option
|
# attribute to be given to the sub-module. As the option
|
||||||
|
@ -394,13 +410,29 @@ rec {
|
||||||
# It shouldn't cause an issue since this is cosmetic for the manual.
|
# It shouldn't cause an issue since this is cosmetic for the manual.
|
||||||
args.name = "‹name›";
|
args.name = "‹name›";
|
||||||
}).options;
|
}).options;
|
||||||
getSubModules = opts';
|
getSubModules = modules;
|
||||||
substSubModules = m: submodule m;
|
substSubModules = m: submoduleWith (attrs // {
|
||||||
functor = (defaultFunctor name) // {
|
modules = m;
|
||||||
# Merging of submodules is done as part of mergeOptionDecls, as we have to annotate
|
});
|
||||||
# each submodule with its location.
|
functor = defaultFunctor name // {
|
||||||
payload = [];
|
type = types.submoduleWith;
|
||||||
binOp = lhs: rhs: [];
|
payload = {
|
||||||
|
modules = modules;
|
||||||
|
specialArgs = specialArgs;
|
||||||
|
shorthandOnlyDefinesConfig = shorthandOnlyDefinesConfig;
|
||||||
|
};
|
||||||
|
binOp = lhs: rhs: {
|
||||||
|
modules = lhs.modules ++ rhs.modules;
|
||||||
|
specialArgs =
|
||||||
|
let intersecting = builtins.intersectAttrs lhs.specialArgs rhs.specialArgs;
|
||||||
|
in if intersecting == {}
|
||||||
|
then lhs.specialArgs // rhs.specialArgs
|
||||||
|
else throw "A submoduleWith option is declared multiple times with the same specialArgs \"${toString (attrNames intersecting)}\"";
|
||||||
|
shorthandOnlyDefinesConfig =
|
||||||
|
if lhs.shorthandOnlyDefinesConfig == rhs.shorthandOnlyDefinesConfig
|
||||||
|
then lhs.shorthandOnlyDefinesConfig
|
||||||
|
else throw "A submoduleWith option is declared multiple times with conflicting shorthandOnlyDefinesConfig values";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue