Created
February 8, 2022 16:15
-
-
Save GrafBlutwurst/2d6156321d6b89cb21a1d0702f5d853e to your computer and use it in GitHub Desktop.
A hacky fix for the either submodule problem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ lib }: with lib; with lib.types; let | |
addTag = typeTag: module: | |
let | |
tagModule = { | |
_tpe = mkOption { | |
type = types.enum [ typeTag ]; | |
description = ''Type Tag (${typeTag})''; | |
}; | |
}; | |
imports = if module ? imports then { inherit (module) imports; } else { }; | |
config = if module ? config then { inherit (module) config; } else { }; | |
in | |
( | |
assert (builtins.isAttrs module) || abort "Module passed to oneOfTagged must be a Record"; | |
assert (builtins.isString typeTag) || abort "TypeTag passed to oneOfTagged must be a String"; | |
assert !(module ? option._tpe) || abort "Module passed to oneOfTagged canno't have an option called _tpe (reserved for typetag)"; | |
imports // config // { | |
options = module.options // tagModule; | |
} | |
); | |
taggedSubmodule = typeTag: module: | |
let | |
taggedModule = addTag typeTag module; | |
baseSubmodule = submodule taggedModule; | |
check = v: (baseSubmodule.check v) && (v._tpe == typeTag); | |
description = "Submodule[${typeTag}]"; | |
in | |
baseSubmodule // { inherit check; inherit description; }; | |
mapAttrDefs = definitions: attrValues (mapAttrs taggedSubmodule definitions); | |
oneOfTagged = definitions: | |
types.oneOf (mapAttrDefs definitions); | |
mkTaggers = definition: | |
let | |
tagger = tag: record: { _tpe = tag; } // record; | |
in | |
( | |
assert (builtins.isAttrs definition) || abort "Definition passed to mkTaggers must be a record"; | |
mapAttrs (name: value: tagger name) definition | |
); | |
in | |
rec { | |
inherit oneOfTagged; | |
inherit mkTaggers; | |
#Use it e.g like this at your use site. | |
#put your choices into a record | |
choices = { | |
left.options.foo = mkOption {type = string;}; | |
right.options.bar = mkOption {type = string;}; | |
}; | |
#This will generate a one of with overridden `check` for the underlying submodules that now have a field `_tpe | |
taggedChoices = oneOfTagged choices; | |
#you can get taggers to add the type tag to your records like this | |
taggers = mkTaggers choices; | |
#mkTaggers just maps over the attrset so you can do | |
leftValue = taggers.left { | |
foo = "asdf"; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment