lib.types.attrTag: Support module docs

Changed files
+65 -1
lib
+41
lib/tests/modules/docs.nix
···
+
/*
+
A basic documentation generating module.
+
Declares and defines a `docs` option, suitable for making assertions about
+
the extraction "phase" of documentation generation.
+
*/
+
{ lib, options, ... }:
+
+
let
+
inherit (lib)
+
head
+
length
+
mkOption
+
types
+
;
+
+
traceListSeq = l: v: lib.foldl' (a: b: lib.traceSeq b a) v l;
+
+
in
+
+
{
+
options.docs = mkOption {
+
type = types.lazyAttrsOf types.raw;
+
description = ''
+
All options to be rendered, without any visibility filtering applied.
+
'';
+
};
+
config.docs =
+
lib.zipAttrsWith
+
(name: values:
+
if length values > 1 then
+
traceListSeq values
+
abort "Multiple options with the same name: ${name}"
+
else
+
assert length values == 1;
+
head values
+
)
+
(map
+
(opt: { ${opt.name} = opt; })
+
(lib.optionAttrSetToDocList options)
+
);
+
}
+19
lib/tests/modules/types-attrTag.nix
···
}
);
};
+
submodules = mkOption {
+
type = types.attrsOf (
+
types.attrTag {
+
foo = types.submodule {
+
options = {
+
bar = mkOption {
+
type = types.int;
+
};
+
};
+
};
+
qux = types.str;
+
}
+
);
+
};
okChecks = mkOption {};
};
imports = [
+
./docs.nix
{
options.merged = mkOption {
type = types.attrsOf (
···
assert config.intStrings.numberOne.left == 1;
assert config.merged.negative.nay == false;
assert config.merged.positive.yay == 100;
+
# assert lib.foldl' (a: b: builtins.trace b a) true (lib.attrNames config.docs);
+
assert config.docs."submodules.<name>.foo.bar".type == "signed integer";
+
# It's not an option, so we can't render it as such. Something would be nice though.
+
assert ! (config.docs?"submodules.<name>.qux");
true;
};
}
+5 -1
lib/types.nix
···
mkOptionType {
name = "attrTag";
description = "attribute-tagged union of ${choicesStr}";
-
getSubModules = null;
+
getSubOptions = prefix:
+
mapAttrs
+
(tagName: tagType:
+
tagType.getSubOptions (prefix ++ [ tagName ]))
+
tags;
substSubModules = m: attrTagWith { tags = mapAttrs (n: v: v.substSubModules m) tags; };
check = v: isAttrs v && length (attrNames v) == 1 && tags?${head (attrNames v)};
merge = loc: defs: