Suppose a file looking something like this:
{
list = [ "foo" "bar" ];
# a bunch
# of other
# code
list = list ++ [ "foobar" ];
}
This won’t work, because list
is defined twice.
So my question is:
From the same .nix file, is it possible to define a list in a way, that multiple values are declared at different locations in my file?
My usecase is that i want to have my configuration.nix split into sections like this:
{ config, lib, pkgs, ... }:
{
# section one
path.to.option1 = "foo";
environment.systemPackages = with pkgs; [ foo ];
# section two
path.to.option2 = "bar";
environment.systemPackages = with pkgs; [ bar ];
}
This works if I import a separate module for every section, but that is not what i want.
i could probably write a function that turns an attribute set like this:
{
o1 = [ "foo" "bar" ];
o2 = [ "foobar" ];
}
to the list
[ "foo" "bar" "foobar" ]
and then declare my list like this:
let
# edit: it is actually really simple lol
concatListsInAttrs = attrs: builtins.concatLists (builtins.attrValues attrs);
in
{
list = concatListsInAttrs listAttrs;
listAttrs.foo = [ "foo" "bar" ];
# a bunch
# of other
# code
listAttrs.foobar = [ "foobar" ];
}
but idk that seems pretty hacky
i’d still like to have a better solution
This is not a Nix language feature, but rather a module system feature:
{ config, lib, pkgs, ... }:
lib.mkMerge [
{
# section one
path.to.option1 = "foo";
environment.systemPackages = with pkgs; [ foo ];
}
{
# section two
path.to.option2 = "bar";
environment.systemPackages = with pkgs; [ bar ];
}
]
1 Like
Oh and alternatively, just using additional inline modules:
{ config, lib, pkgs, ... }: {
imports = [
{
# section one
path.to.option1 = "foo";
environment.systemPackages = with pkgs; [ foo ];
}
{
# section two
path.to.option2 = "bar";
environment.systemPackages = with pkgs; [ bar ];
}
];
}
2 Likes
shouldn’t it be
{ config, lib, pkgs, ... }: {
imports = [
({ config, lib, pkgs }: {
# section one
path.to.option1 = "foo";
environment.systemPackages = with pkgs; [ foo ];
})
({ config, lib, pkgs }: {
# section two
path.to.option2 = "bar";
environment.systemPackages = with pkgs; [ bar ];
})
];
}
or do inline modules not have to be functions?
Modules in general don’t need to be functions! E.g. this also works:
{
imports = [
{}
{}
];
}
You could even use both mkMerge
and imports
at the same time:
{ lib, ... }: {
imports = [
# These are full modules, they can define options, more `imports`, etc.
{}
{}
];
config = lib.mkMerge [
# These are only `config`, you can define options, but not declare additional ones or import other modules
{}
{}
];
}
2 Likes