Skip to content

Commit

Permalink
lib: add option parameter for default value priority
Browse files Browse the repository at this point in the history
When you define an option's default value, the expectation is that whenever the
option is set somewhere, the default value will be overridden by that setting
rather than merged.

It's sometimes the case however that your option's default value should be
merged with what is being set rather than overwritten by it; only allowing
explicit overrides via `mkForce`. Creating such an option was not possible
previously as all options' default values were forcefully clamped via
mkOptionDefault.

There were some workarounds such as creating additional options ("things" +
"extraThings") which you'd then have to explain to users and generally aren't
ergonomical to use.

Another workaround was to explicitly set options value to the default value in
the implementation but those two lines of code might be many lines apart from
another and it's generally an odd pattern. Example:

    {
      options.foo = lib.mkOption {
        default = [ "foo" ];
      };

      # Many more lines of code

      config.foo = options.foo.default;
    }

It is now possible to control this behaviour at option declaration which is much
clearer in the code and is introspect-able.

    {
      options.foo = lib.mkOption {
        default = [ "foo" ];
        defaultPriority = lib.modules.priorities.baseline;
      };

      # Many more lines of code
    }

The implementation is trivial.

If this becomes used more widely, it should be rendered in the generated options
manual and nixos-search.
  • Loading branch information
Atemu committed Nov 1, 2024
1 parent b488894 commit fdd007f
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 3 deletions.
8 changes: 5 additions & 3 deletions lib/modules.nix
Original file line number Diff line number Diff line change
Expand Up @@ -787,9 +787,11 @@ let
evalOptionValue = loc: opt: defs:
let
# Add in the default value for this option, if any.
defs' =
(optional (opt ? default)
{ file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs;
defs' = (optional (opt ? default) {
file = head opt.declarations;
value = mkOverride (opt.defaultPriority or priorities.optionDefault) opt.default;
})
++ defs;

# Handle properties, check types, and merge everything together.
res =
Expand Down
2 changes: 2 additions & 0 deletions lib/options.nix
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ rec {
{
# Default value used when no definition is given in the configuration.
default ? null,
# Which priority to assign to the default value. This can be used to control whether the default is be merged or overridden when the option is set.
defaultPriority ? lib.modules.priorities.optionDefault,
# Textual representation of the default, for the manual.
defaultText ? null,
# Example value used in the manual.
Expand Down

0 comments on commit fdd007f

Please sign in to comment.