Currently re-writing a HM module I have, I’m hitting some kind of a roadblock and don’t know how to tackle it. Maybe what I’m trying to do is not possible, which is the reason for this post.
The module has some top-level options and multiple submodules. In addition to that, there is one of the submodules which reuses some of the top-level submodules. This is the culprit.
To simplify, here is a tree view of the module options:
.
├── submodule1
│ ├── option3
│ └── option4
├── submodule2
│ ├── option5
│ └── option6
├── submodule3
│ ├── option7
│ └── option8
├── submodule4
│ ├── submodule2
│ │ ├── option5
│ │ └── option6
│ └── submodule3
│ ├── option7
│ └── option8
├── option1
└── option2
Currently, all submodules (1, 2 and 3) call lambdas which define their options as follows:
{ lib }:
lib.types.submodule { /* Options */ }
They are imported in the top-level like that:
{ lib, config, ... }:
let
submodule1 = import ./submodule1.nix { inherit lib; };
submodule2 = import ./submodule2.nix { inherit lib; };
submodule3 = import ./submodule3.nix { inherit lib; };
in
{
options = {
submodule1 = mkOption {
type = submodule1;
default = { };
description = "First submodule";
};
submodule2 = mkOption {
type = submodule2;
default = { };
description = "Second submodule";
};
submodule3 = mkOption {
type = submodule3;
default = { };
description = "Third submodule";
};
};
}
As for submodule4, it’s a bit more complicated and looks like this:
{ lib, submodule2, submodule3 }:
types.submodule {
options = {
submodule2 = lib.mkOption {
type = submodule2;
default = { };
description = "Second submodule";
};
submodule3 = lib.mkOption {
type = submodule3;
default = { };
description = "Third submodule";
};
}
It is imported in the top-level in this way:
{ lib, config, ... }:
let
submodule1 = import ./submodule1.nix { inherit lib; };
submodule2 = import ./submodule2.nix { inherit lib; };
submodule3 = import ./submodule3.nix { inherit lib; };
submodule4 = import ./submodule4.nix {
inherit lib submodule2 submodule3;
};
in
{
options = {
submodule1 = mkOption {
type = submodule1;
default = { };
description = "First submodule";
};
submodule2 = mkOption {
type = submodule2;
default = { };
description = "Second submodule";
};
submodule3 = mkOption {
type = submodule3;
default = { };
description = "Third submodule";
};
submodule4 = mkOption {
type = lib.types.listOf submodule4;
default = { };
description = "Fourth submodule";
};
};
}
Although this is working fine, I’d like for the submodule files to be « real » submodules that I can import using imports
rather than import
. In the end, the current implementation only uses lambdas which create the submodule types.
The issue I have is that the submodule4
is a list of submodules which happen to have options using top-level submodules definition. Not sure I’m being clear…
While rewriting the submodule4, I noticed that what I’m trying to do might not be possible since if I add submodule2
and submodule3
to submodule4
’s imports
, they will end up being top-level, right?
{ lib, ... }:
{
imports = [
./submodule2.nix
./submodule3.nix
];
options = {
submodule4 = lib.mkOption {
type = lib.types.listOf /* what? */;
default = [ { isDefault = true; } ];
description = "Fourth submodule";
};
}
}
I have a feeling I’m overthinking this and should stick with the current implementation but it somehow feels wrong in the way it currently is implemented.
Any thoughts?