9 Jul 2024 |
| sbc64 joined the room. | 16:49:13 |
14 Jul 2024 |
| Tsomipa_ts joined the room. | 18:55:59 |
15 Jul 2024 |
| dminca changed their display name from dminca to nixpkgs. | 17:29:06 |
| dminca changed their display name from nixpkgs to dminca. | 17:42:43 |
23 Jul 2024 |
| Ezzobir Bezziou joined the room. | 08:21:01 |
26 Jul 2024 |
| Gaétan Lepage joined the room. | 15:30:55 |
| Matt Sturgeon joined the room. | 16:39:44 |
27 Jul 2024 |
| @brian:bmcgee.ie joined the room. | 11:20:49 |
28 Jul 2024 |
Matt Sturgeon | Question: In a submodule with a freeformType , how can one access the freeform definition (and option metadata) separately from any sub-options?
I.e. get definitions, metadata and final merged value for the freeform definitions separately from option definitions.
Alternative: Is it possible to configure a submodule evaluation to only merge "defined" options into the final config value?
Motivation: In nixvim, we have several freeform "settings" submodules, and we directly pass the resulting config to a toLua generator.
Currently any sub-options defined will always show up in the resulting config, and we work-around this by having them default to null .
This has two main downsides:
- When filtering out nulls, we also filter out any explicitly defined nulls.
- When we have options at nested attr paths, we have to filter out the empty attr after we filter the null
Instead, I would like to have sub-options without a default and have them not show up in the final config if they are not defined.
I don't mind doing this manually, by merging the freeform value with any options.*.value where options.*.isDefined , but idk how to access the freeform value separately.
Follow up: If I have to do this within the submodule, idk the best way to access the result from outside the submodule? I could declare an internal option definedConfig , but I'm not sure if I could avoid infinite recursion when merging the other option values into it?
Apologies for the long-form question!
| 20:01:34 |
Matt Sturgeon | Maybe the correct implementation is to define any "optional" options outside the freeform submodule, and then copy them in if defined?
# Set settings.foo to foo, if defined
optionalAttrs options.something.foo.isDefined {
# Use mkDerivedConfig to also copy definition priority
something.settings.foo = lib.mkDerivedConfig options.something.foo (v: v);
}
Perhaps submodule sub-options are only intended to be used when the value should always be in the generated value?
| 20:41:12 |
Matt Sturgeon | * Maybe the correct implementation is to define any "optional" options outside the freeform submodule, and then copy them in if defined?
# Set settings.foo to foo, if defined
lib.optionalAttrs options.something.foo.isDefined {
# Use mkDerivedConfig to also copy definition priority
something.settings.foo = lib.mkDerivedConfig options.something.foo (v: v);
}
Perhaps submodule sub-options are only intended to be used when the value should always be in the generated value?
| 20:41:39 |
29 Jul 2024 |
infinisil | Related: https://github.com/NixOS/nixpkgs/pull/63553 | 23:08:02 |
infinisil | And https://github.com/NixOS/nixpkgs/issues/158594 | 23:09:27 |
30 Jul 2024 |
Matt Sturgeon | Thanks, those links are insightful!
I think 158598 is also related, but 158594 sounds like exactly what I want:
We could add a mkOption argument that has the effect of producing no default value and no config attribute when no definitions are present for the option.
But it looks like the latest comment is backtracking or downscaling that idea...
Playing around in the repl, I can get _module.freeformType and I can get any _freeformOptions for freeform submodules (freeformType = attrsOf submodule ), but I can't seem to find the freeform value or definitions anywhere separate from the fully merged option value/defs. Can you confirm I'm not missing anything here?
I guess to do this I would have to write my own types.submodule equivalent (e.g. submoduleWithoutUndefs )? With a custom type I should be able to merge using evalModules but filter out any undefined options 🤔
Seems similar in principle to the types.record proposal in #257511, although I'd need optional and nested fields which I think is out of scope for that one.
| 00:34:08 |
Matt Sturgeon | * Thanks, those links are insightful!
158594 sounds like exactly what I want:
We could add a mkOption argument that has the effect of producing no default value and no config attribute when no definitions are present for the option.
But it looks like the latest comment is backtracking or downscaling that idea...
Playing around in the repl, I can get _module.freeformType and I can get any _freeformOptions for freeform submodules (freeformType = attrsOf submodule ), but I can't seem to find the freeform value or definitions anywhere separate from the fully merged option value/defs. Can you confirm I'm not missing anything here?
I guess to do this I would have to write my own types.submodule equivalent (e.g. submoduleWithoutUndefs )? With a custom type I should be able to merge using evalModules but filter out any undefined options 🤔
Seems similar in principle to the types.record proposal in #257511, although I'd need optional and nested fields which I think is out of scope for that one.
| 00:34:48 |
Matt Sturgeon |
I guess to do this I would have to write my own types.submodule equivalent (e.g. submoduleWithoutUndefs )? With a custom type I should be able to merge using evalModules but filter out any undefined options 🤔
Or maybe this wouldn't work, if evalModules itself is what merges the option+freeform defs together
| 00:43:33 |
Matt Sturgeon | Seems it is: freeformConfig is evaluated here, but isn't exposed separately from config .
Would a PR be welcome to have evalModules include declaredConfig , freeformConfig and config separately in the evaluated result?
| 01:20:44 |
Matt Sturgeon | Or maybe returning both config and definedConfig , the latter having filtered out declared options that aren't defined | 01:30:41 |
| purepani joined the room. | 04:11:12 |
31 Jul 2024 |
infinisil | @mattsturg:matrix.org Immediate thoughts are that it might be a bit of a leaky abstraction, but maybe also not. Feel free to make a PR, but I can't promise to get to review it myself soon, but perhaps @roberthensing:matrix.org can :)
| 09:53:38 |
1 Aug 2024 |
| cleverca22 joined the room. | 12:53:32 |
4 Aug 2024 |
| Traxys joined the room. | 13:40:51 |
| tacticaltaco joined the room. | 22:09:55 |
9 Aug 2024 |
Matt Sturgeon | I've been playing around with this in this branch (current commit), but what I have now is infinitely recursive, because config s shape is changing based on options._module.definedOptionsOnly , but options itself depends on config .
Is this approach fundamentally flawed? Do you have any suggestions for working around the inf-recursion?
The immediate alternative that springs to mind is to pass both a config and a definedConfig to the modules and include definedConfig in the result, alongside config . This is more inline with my original proposal, but feels like a worse abstraction than having a _module.definedOptionsOnly option.
I definedOptionsOnly could also be an evalModules argument instead of an option, but that isn't really ideal either.
| 13:30:14 |
Matt Sturgeon | * I've been playing around with this in this branch (current commit), but what I have now is infinitely recursive, because config s shape is changing based on options._module.definedOptionsOnly , but options itself recursively depends on config .
Is this approach fundamentally flawed? Do you have any suggestions for working around the inf-recursion?
The immediate alternative that springs to mind is to pass both a config and a definedConfig to the modules and include definedConfig in the result, alongside config . This is more inline with my original proposal, but feels like a worse abstraction than having a _module.definedOptionsOnly option.
I definedOptionsOnly could also be an evalModules argument instead of an option, but that isn't really ideal either.
| 13:30:54 |
Matt Sturgeon | * I've been playing around with this in this branch (current commit), but what I have now is infinitely recursive, because config s shape is changing based on options._module.definedOptionsOnly , but options itself recursively depends on config .
Is this approach fundamentally flawed? Do you have any suggestions for working around the inf-recursion?
The immediate alternative that springs to mind is to pass both a config and a definedConfig to the modules and include definedConfig in the result, alongside config . This is more inline with my original proposal, but feels like a worse abstraction than having a _module.definedOptionsOnly option.
definedOptionsOnly could also be an evalModules argument instead of an option, but that isn't really ideal either.
| 13:31:39 |
Matt Sturgeon | * infinisil Robert Hensing (roberth) Thanks for your support so far!
I've been playing around with the concept in this branch (current commit), but my current implementation is infinitely recursive, because config s shape is changing based on options._module.definedOptionsOnly , but options itself recursively depends on config .
Is this approach fundamentally flawed? Do you have any suggestions for working around the inf-recursion?
The immediate alternative that springs to mind is to pass both a config and a definedConfig to the modules and include definedConfig in the result, alongside config . This is more inline with my original proposal, but feels like a worse abstraction than having a _module.definedOptionsOnly option.
definedOptionsOnly could also be an evalModules argument instead of an option, but that isn't really ideal either.
| 15:12:07 |
10 Aug 2024 |
Matt Sturgeon | I've opened a draft PR that does it as an evalModules arg, so it actually works without inf-recursion. I detailed this limitation in the PR description. Any feedback would be greatly appreciated!
https://github.com/NixOS/nixpkgs/pull/333799
| 23:30:29 |
13 Aug 2024 |
| Austin Horstman joined the room. | 22:45:20 |
14 Aug 2024 |
Robert Hensing (roberth) | Matt Sturgeon: would you (or anyone I guess?) be interested in completing types.record from https://github.com/NixOS/nixpkgs/pull/257511? I don't have much time for this kind of thing due to other responsibilities recently | 14:41:16 |