Custom submodules without default values #622
|
In Configure Aspects, we have an example on how to setup a custom submodule for an user aspect, but is it possible to make it work without setting any default values? For context, I have a { ... }:
{
den.aspects.fonts =
{ config, lib, ... }:
{
imports = [
{
options = with lib.types; {
sansSerif = lib.mkOption { type = str; };
};
}
];
nixos =
{ pkgs, ... }:
{
fonts.fontconfig.defaultFonts = {
sansSerif = [ config.sansSerif ];
};
};
};
}Notice the lack of default values. My goal is to force hosts/users to set these values, but I also want to reference the values in other submodules, such as So, in the host file: den.aspects.myHost = {
includes = [
den.aspects.fonts
den.aspects.gnome
];
# Set default fonts here.
fonts.sansSerif = "Ubuntu";
# Or maybe we need the whole namespace?
den.aspects.fonts.sansSerif = "Ubuntu";
# Host config
nixos = { pkgs, ... }: {};
};Then, inside my { den, ... }:
{
# Simplified for the example.
den.aspects.gnome.homeManager.dconf = {
enable = true;
settings = {
"org/gnome/desktop/interface" = {
font-name = "${den.aspects.fonts.sans} 11";
# Or using `config.den.aspects.fonts.sans`.
};
};
};
}I've tried everything, but I could only make it work by setting a default value in the option. Without the default value, it says the option was accessed but has no value defined, even with me configuring the option in the host. It could be some kind of evaluation problem, where So, I'm either doing something wrong, forgetting about something important, or Den simply doesn't support this in the way that I'm approaching it. I know an alternative would be to set these options via Any tips? |
Replies: 3 comments 11 replies
|
If it's something you want set per-user, you might be better served by creating a new option on the user schema. |
|
I'll put together a gist of how I do aspect settings in my config tomorrow. What you're describing is either our quirks system, or my custom settings extension. Aspects provide behavior; they aren't data. Users/hosts provide data/context -- so in my configuration I define options on aspects, and assign values to context (generally the host). |
|
Just wanted to mention that I got this working nicely. The gist was very helpful, thanks again @sini. I implemented Option 1 as shown, but then created a policy to automatically inject # den/policies/settings-injection.nix
{ den, ... }:
{
den.policies.settings-injection =
{
host ? null,
home ? null,
...
}:
[
(den.lib.policy.resolve {
settings =
if host ? settings then
host.settings
else if home ? settings then
home.settings
else
throw "No settings found on host or home";
})
];
}# den/default.nix
{ den, ... }:
{
den.default.includes = [
den.policies.settings-injection
];
# Other settings..
}Also, an important change from the gist is that I went from # den/settings.nix
{ den, lib, ... }:
let
inherit (lib) mkOption types;
# Dynamic settings type. Read the gist for details.
settingsType = ...
in
{
den.reservedKeys = [ "settings" ];
# Applies to hosts, homes, and users, but I tend to configure everything in the host/home side.
den.schema.conf = {
imports = [
{
options.settings =
mkOption {
type = settingsType;
default = { };
description = "Per-aspect typed settings";
}
# Exclude settings from entity identity hashing
// {
identity = false;
};
}
];
};
}Now, the only thing "missing" would be the ability to reference values from inside the settings block somehow, like so: den.hosts.x86_64-linux."${host}" = {
users.lucas = { };
settings = rec {
fonts = {
sans = "Adwaita Sans";
};
gnome = {
interface-font = fonts.sans; # Defined above, `rec` lets us use this.
document-font = ???; # Use the default from `den.aspects.fonts.settings.serif`.
};
};
};But the above seems to be an unusual pattern in NixOS (even though it's common in enterprise development), so that's not really an issue for me. Besides that, I might run into issues if I ever need something more than what NixOS options pattern provides, but for now this is working nicely as a way for aspects to expose configurable options that can be defined in a per-host (or home) basis. EDIT: I think we're also missing the ability to set values inside another aspect, like the |
Just wanted to mention that I got this working nicely. The gist was very helpful, thanks again @sini. I implemented Option 1 as shown, but then created a policy to automatically inject
settingsfrom eitherhost.settingson NixOS orhome.settingson standalonehome-manager:# …