Skip to content

feat(wrapperModules.niri): change settings types for better merging#531

Merged
BirdeeHub merged 1 commit into
BirdeeHub:mainfrom
kraftnix:niri-types
May 18, 2026
Merged

feat(wrapperModules.niri): change settings types for better merging#531
BirdeeHub merged 1 commit into
BirdeeHub:mainfrom
kraftnix:niri-types

Conversation

@kraftnix
Copy link
Copy Markdown
Contributor

@kraftnix kraftnix commented May 17, 2026

Issue

Currently it is not possible to merge settings together in the niri wrapper module that are part of the freeform configuration, this leads to unexpected overriding of config instead of merging config options together.

Example

An example of an option that wouldn't merge prior to this minor change is input

# shared config file
wrappers.niri.settings.input.keyboard.xkb.options = "caps:escape";

# in a host file
wrappers.niri.settings.input.mouse.accel-profile = "flat";

The above snippet means that only one of the input configs is selected, there is not even an error warning that multiple options have been set.

Additionally, previously you could not set config with an override level using mkDefault inside nested attributes (again input is an example) as the mkDefault would be interpreted in its unwrapped attrSet.

Other extensions

It may also be worth changing more of the defined options in the freeform settings type to use anything instead of attrs since anything correctly recursively merges attribute sets.

  • layout: is a good candidate as nested attribute sets can occur here
  • binds: it depends, it would allow partial overriding of binds set elsewhere, but this may not necessarily be wanted behaviour, and since you can't merge a functionTo type anyway, it appears less useful here as you may always want to set all config of a binding in one place.
  • outputs: for similar reasons to binds
  • window-rules and layer-rules: are lists of attrs, and so merging also won't happen here either so is not needed.

Just changing the toplevel to anything mostly solves my issues porting my niri config properly to nix-wrapper-modules from niri-flake.

Comment thread wrapperModules/n/niri/module.nix Outdated
default = { };
type = lib.types.submodule {
freeformType = lib.types.attrs;
freeformType = lib.types.anything;
Copy link
Copy Markdown
Owner

@BirdeeHub BirdeeHub May 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
freeformType = lib.types.anything;
freeformType = wlib.types.attrsRecursive;

^ lib.types.anything but also merges lists like normal too rather than overwriting with no choice in the matter? (like, you could lib.mkForce to overwrite the list still with this too, but also lib.mkBefore and lib.mkAfter and stuff)

Copy link
Copy Markdown
Owner

@BirdeeHub BirdeeHub May 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didnt notice the lib.types.attrs in the original PR, and then I noticed it but I just haven't really felt the need to change it, but if it is surprising to people, happy to do so!

Copy link
Copy Markdown
Owner

@BirdeeHub BirdeeHub May 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also be open to changing layouts and maybe the other ones.

Also it does actually merge functions as far as I am aware? Especially functions that return sets. If it doesn't we should see why not!

lambda =
loc: defs: arg:
wlib.types.attrsRecursive.merge (loc ++ [ "<function body>" ]) (
map (def: {
file = def.file;
value = def.value arg;
}) defs
);

^ If it encounters a function, as specified by builtins.typeOf, it returns a function that calls the merge function on the results of the functions. lib.types.anything also works like this.

Also the function recieves self as an arg, it is called via lib.fix so it would know about the extras too, if you had use for that.

However, once you used a function or a set, all future ones would have to be of that type. It can't merge a set with a function, you would need a custom type for that.

On that note, we can also see about maybe making a custom kdl type to match our generator one day which is better than wlib.types.attrsRecursive for that usecase, i.e. allowing us to merge a list or set kdl value into its function variant, so that all the things you could provide as a value can merge according to the format created by wlib.toKdl regardless of what was first provided there.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also it does actually merge functions as far as I am aware? Especially functions that return sets. If it doesn't we should see why not!

Oh that's neat.

wlib.types.attrsRecursive seems like a good choice too. I'll go with that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also be open to changing layouts and maybe the other ones.

Yeah, give the ability of wlib.types.attrsRecursive to merge functionTo I can also add changes for layout, binds and outputs.

I don't think adding to window-rules and layer-rules would help much but it probably wouldn't hurt either?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets leave those alone in the interest of not making the module system do more checking than we care about.

This is fine.

@kraftnix kraftnix changed the title feat(wrapperModules.niri): change settings type to anything for better merging feat(wrapperModules.niri): change settings types for better merging May 18, 2026
@BirdeeHub BirdeeHub merged commit 597b35c into BirdeeHub:main May 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants