This commit is contained in:
pengo 2026-06-16 15:14:09 +02:00 committed by GitHub
commit 74b49cd346
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 386 additions and 385 deletions

26
default.nix Normal file
View file

@ -0,0 +1,26 @@
let
inherit (builtins) fromJSON readFile;
lock = fromJSON (readFile ./flake.lock);
node = lock.nodes.${lock.nodes.root.inputs.nixpkgs}.locked;
nixpkgs = fetchTarball {
url = with node; "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz";
sha256 = node.narHash;
};
in
{pkgs ? import nixpkgs {}}: let
inherit (pkgs) callPackage;
inherit (pkgs.lib.modules) importApply;
package = callPackage ./nix/package.nix {};
in {
overlay = final: prev: {
mango = package;
};
inherit package;
nixosModule = importApply ./nix/nixos-module.nix package;
hmModule = importApply ./nix/hm-module.nix package;
}

34
flake.lock generated
View file

@ -1,23 +1,5 @@
{
"nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1749398372,
"narHash": "sha256-tYBdgS56eXYaWVW3fsnPQ/nFlgWi/Z2Ymhyu21zVM98=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "9305fe4e5c2a6fcf5ba6a3ff155720fbe4076569",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1778274207,
@ -34,24 +16,8 @@
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1748740939,
"narHash": "sha256-rQaysilft1aVMwF14xIdGS3sj1yHlI6oKQNBRTF40cc=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "656a64127e9d791a334452c6b6606d17539476e2",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"root": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs",
"scenefx": "scenefx"
}

104
flake.nix
View file

@ -1,7 +1,6 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
scenefx = {
url = "github:wlrfx/scenefx";
inputs.nixpkgs.follows = "nixpkgs";
@ -10,54 +9,77 @@
outputs = {
self,
flake-parts,
...
} @ inputs:
flake-parts.lib.mkFlake {inherit inputs;} {
imports = [
inputs.flake-parts.flakeModules.easyOverlay
];
nixpkgs,
scenefx,
}: let
inherit (nixpkgs.lib) genAttrs;
inherit (nixpkgs.lib.modules) importApply;
flake = {
hmModules.mango = import ./nix/hm-modules.nix self;
nixosModules.mango = import ./nix/nixos-modules.nix self;
};
# Systems mangowm supports. Options that call `forEachSystem` will generate an attribute for each of these options.
systems = [
"x86_64-linux"
"aarch64-linux"
];
perSystem = {
config,
# Helper function that generates an attribute set by calling the provided `perSystem` function for each system in `systems` defined above.
forEachSystem = perSystem:
genAttrs systems (
system:
perSystem {
inherit system;
pkgs = nixpkgs.legacyPackages.${system};
}
);
in {
overlays.default = final: prev: {
inherit (self.packages.${final.stdenv.hostPlatform.system}) mango;
};
packages = forEachSystem (
{
pkgs,
...
system,
}: let
inherit (pkgs) callPackage ;
mango = callPackage ./nix {
inherit (inputs.scenefx.packages.${pkgs.stdenv.hostPlatform.system}) scenefx;
};
shellOverride = old: {
nativeBuildInputs = old.nativeBuildInputs ++ [];
buildInputs = old.buildInputs ++ [];
inherit (pkgs) callPackage;
mango = callPackage ./nix/package.nix {
inherit (scenefx.packages.${system}) scenefx;
};
generateOptions = callPackage (import ./nix/generate-options.nix self);
in {
packages.default = mango;
overlayAttrs = {
inherit (config.packages) mango;
inherit mango;
default = mango;
hm-options-json = generateOptions {
module = ./nix/hm-module.nix;
optionPrefix = "wayland.windowManager.mango.";
};
packages = {
inherit mango;
hm-options-json = pkgs.callPackage (import ./nix/generate-options.nix self) {
module = ./nix/hm-modules.nix;
optionPrefix = "wayland.windowManager.mango.";
};
nixos-options-json = pkgs.callPackage (import ./nix/generate-options.nix self) {
module = ./nix/nixos-modules.nix;
optionPrefix = "programs.mango.";
};
nixos-options-json = generateOptions {
module = ./nix/nixos-module.nix;
optionPrefix = "programs.mango.";
};
devShells.default = mango.overrideAttrs shellOverride;
formatter = pkgs.alejandra;
};
systems = [
"x86_64-linux"
"aarch64-linux"
}
);
nixosModules.mango = {pkgs, ...}: {
imports = [
(importApply ./nix/nixos-module.nix self.packages.${pkgs.stdenv.hostPlatform.system}.default)
];
};
hmModules.mango = {pkgs, ...}: {
imports = [
(importApply ./nix/hm-module.nix self.packages.${pkgs.stdenv.hostPlatform.system}.default)
];
};
devShells = forEachSystem (
{system, ...}: {
default = self.packages.${system}.mango;
}
);
formatter = forEachSystem (
{pkgs, ...}: pkgs.alejandra
);
};
}

View file

@ -1,20 +1,18 @@
self:
{
self: {
pkgs,
lib ? pkgs.lib,
module,
optionPrefix,
}:
let
}: let
# Absolute store path of the flake root, used to compute relative subpaths
repoPath = toString self;
eval = lib.evalModules {
modules = [
(import module self)
{ _module.check = false; }
(import module self.packages.${pkgs.stdenv.hostPlatform.system}.default)
{_module.check = false;}
];
specialArgs = { inherit pkgs; };
specialArgs = {inherit pkgs;};
};
# Relative path of the module file within the repo (e.g. "nix/hm-modules.nix")
@ -28,15 +26,14 @@ let
optionsDoc = pkgs.nixosOptionsDoc {
options = eval.options;
transformOptions =
opt:
transformOptions = opt:
opt
// {
visible = opt.visible && !opt.internal;
# Strip the option prefix so docs show "enable" instead of "programs.mango.enable"
name = lib.removePrefix optionPrefix opt.name;
declarations = [ moduleDeclaration ];
declarations = [moduleDeclaration];
};
};
in
optionsDoc.optionsJSON
optionsDoc.optionsJSON

View file

@ -1,11 +1,9 @@
self:
{
mangoPackage: {
lib,
config,
pkgs,
...
}:
let
}: let
cfg = config.wayland.windowManager.mango;
selflib = import ./lib.nix lib;
variables = lib.concatStringsSep " " cfg.systemd.variables;
@ -15,8 +13,7 @@ let
${lib.optionalString cfg.systemd.enable systemdActivation}
${cfg.autostart_sh}
'';
in
{
in {
options = {
wayland.windowManager.mango = with lib; {
enable = mkOption {
@ -26,7 +23,7 @@ in
};
package = lib.mkOption {
type = lib.types.package;
default = self.packages.${pkgs.stdenv.hostPlatform.system}.mango;
default = mangoPackage;
description = "The mango package to use";
};
systemd = {
@ -59,7 +56,7 @@ in
"XCURSOR_THEME"
"XCURSOR_SIZE"
];
example = [ "--all" ];
example = ["--all"];
description = ''
Environment variables imported into the systemd and D-Bus user environment.
'';
@ -80,25 +77,23 @@ in
'';
};
settings = mkOption {
type =
with lib.types;
let
valueType =
nullOr (oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
])
// {
description = "Mango configuration value";
};
in
type = with lib.types; let
valueType =
nullOr (oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
])
// {
description = "Mango configuration value";
};
in
valueType;
default = { };
default = {};
description = ''
Mango configuration written in Nix. Entries with the same key
should be written as lists. Variables and colors names should be
@ -178,21 +173,21 @@ in
};
topPrefixes = mkOption {
type = with lib.types; listOf str;
default = [ ];
default = [];
description = ''
List of prefixes for attributes that should appear at the top of the config file.
Attributes starting with these prefixes will be sorted to the beginning.
'';
example = [ "source" ];
example = ["source"];
};
bottomPrefixes = mkOption {
type = with lib.types; listOf str;
default = [ ];
default = [];
description = ''
List of prefixes for attributes that should appear at the bottom of the config file.
Attributes starting with these prefixes will be sorted to the end.
'';
example = [ "source" ];
example = ["source"];
};
autostart_sh = mkOption {
description = ''
@ -217,25 +212,25 @@ in
finalConfigText =
# Support old string-based config during transition period
(
if builtins.isString cfg.settings then
cfg.settings
if builtins.isString cfg.settings
then cfg.settings
else
lib.optionalString (cfg.settings != { }) (
lib.optionalString (cfg.settings != {}) (
selflib.toMango {
topCommandsPrefixes = cfg.topPrefixes;
bottomCommandsPrefixes = cfg.bottomPrefixes;
} cfg.settings
}
cfg.settings
)
)
+ lib.optionalString (cfg.extraConfig != "") cfg.extraConfig
+ lib.optionalString (cfg.autostart_sh != "") "\nexec-once=~/.config/mango/autostart.sh\n";
validatedConfig = pkgs.runCommand "mango-config.conf" { } ''
validatedConfig = pkgs.runCommand "mango-config.conf" {} ''
cp ${pkgs.writeText "mango-config.conf" finalConfigText} "$out"
${cfg.package}/bin/mango -c "$out" -p || exit 1
'';
in
{
in {
# Backwards compatibility warning for old string-based config
warnings = lib.optional (builtins.isString cfg.settings) ''
wayland.windowManager.mango.settings: Using a string for settings is deprecated.
@ -244,13 +239,13 @@ in
The old string format will be removed in a future release.
'';
home.packages = [ cfg.package ];
home.packages = [cfg.package];
xdg.configFile = {
"mango/config.conf" =
lib.mkIf (cfg.settings != { } || cfg.extraConfig != "" || cfg.autostart_sh != "")
{
source = validatedConfig;
};
lib.mkIf (cfg.settings != {} || cfg.extraConfig != "" || cfg.autostart_sh != "")
{
source = validatedConfig;
};
"mango/autostart.sh" = lib.mkIf (cfg.autostart_sh != "") {
source = autostart_sh;
executable = true;
@ -259,13 +254,14 @@ in
systemd.user.targets.mango-session = lib.mkIf cfg.systemd.enable {
Unit = {
Description = "mango compositor session";
Documentation = [ "man:systemd.special(7)" ];
BindsTo = [ "graphical-session.target" ];
Wants = [
"graphical-session-pre.target"
]
++ lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target";
After = [ "graphical-session-pre.target" ];
Documentation = ["man:systemd.special(7)"];
BindsTo = ["graphical-session.target"];
Wants =
[
"graphical-session-pre.target"
]
++ lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target";
After = ["graphical-session-pre.target"];
Before = lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target";
};
};

View file

@ -1,6 +1,6 @@
lib:
let
inherit (lib)
lib: let
inherit
(lib)
attrNames
filterAttrs
foldl
@ -9,304 +9,299 @@ let
removeAttrs
;
inherit (lib.strings)
inherit
(lib.strings)
concatMapStrings
hasPrefix
;
/**
Convert a structured Nix attribute set into Mango's configuration format.
Convert a structured Nix attribute set into Mango's configuration format.
This function takes a nested attribute set and converts it into Mango-compatible
configuration syntax, supporting top, bottom, and regular command sections.
This function takes a nested attribute set and converts it into Mango-compatible
configuration syntax, supporting top, bottom, and regular command sections.
Commands are flattened using the `flattenAttrs` function, and attributes are formatted as
`key = value` pairs. Lists are expanded as duplicate keys to match Mango's expected format.
Commands are flattened using the `flattenAttrs` function, and attributes are formatted as
`key = value` pairs. Lists are expanded as duplicate keys to match Mango's expected format.
Configuration:
Configuration:
* `topCommandsPrefixes` - A list of prefixes to define **top** commands (default: `[]`).
* `bottomCommandsPrefixes` - A list of prefixes to define **bottom** commands (default: `[]`).
* `topCommandsPrefixes` - A list of prefixes to define **top** commands (default: `[]`).
* `bottomCommandsPrefixes` - A list of prefixes to define **bottom** commands (default: `[]`).
Attention:
Attention:
- The function ensures top commands appear **first** and bottom commands **last**.
- The generated configuration is a **single string**, suitable for writing to a config file.
- Lists are converted into multiple entries, ensuring compatibility with Mango.
- The function ensures top commands appear **first** and bottom commands **last**.
- The generated configuration is a **single string**, suitable for writing to a config file.
- Lists are converted into multiple entries, ensuring compatibility with Mango.
# Inputs
# Inputs
Structured function argument:
Structured function argument:
: topCommandsPrefixes (optional, default: `[]`)
: A list of prefixes that define **top** commands. Any key starting with one of these
prefixes will be placed at the beginning of the configuration.
: bottomCommandsPrefixes (optional, default: `[]`)
: A list of prefixes that define **bottom** commands. Any key starting with one of these
prefixes will be placed at the end of the configuration.
: topCommandsPrefixes (optional, default: `[]`)
: A list of prefixes that define **top** commands. Any key starting with one of these
prefixes will be placed at the beginning of the configuration.
: bottomCommandsPrefixes (optional, default: `[]`)
: A list of prefixes that define **bottom** commands. Any key starting with one of these
prefixes will be placed at the end of the configuration.
Value:
Value:
: The attribute set to be converted to Hyprland configuration format.
: The attribute set to be converted to Hyprland configuration format.
# Type
# Type
```
toMango :: AttrSet -> AttrSet -> String
```
```
toMango :: AttrSet -> AttrSet -> String
```
# Examples
:::{.example}
# Examples
:::{.example}
## Basic mangowc configuration
## Basic mangowc configuration
```nix
let
config = {
blur = 1;
blur_params_radius = 5;
border_radius = 6;
animations = 1;
animation_duration_open = 400;
```nix
let
config = {
blur = 1;
blur_params_radius = 5;
border_radius = 6;
animations = 1;
animation_duration_open = 400;
};
in lib.toMango {} config
```
**Output:**
```
animations = 1
animation_duration_open = 400
blur = 1
blur_params_radius = 5
border_radius = 6
```
## Using nested attributes
```nix
let
config = {
blur = 1;
blur_params = {
radius = 5;
num_passes = 2;
noise = 0.02;
};
in lib.toMango {} config
```
animation_curve = {
open = "0.46,1.0,0.29,1";
close = "0.08,0.92,0,1";
};
};
in lib.toMango {} config
```
**Output:**
```
animations = 1
animation_duration_open = 400
blur = 1
blur_params_radius = 5
border_radius = 6
```
**Output:**
```
animation_curve_close = 0.08,0.92,0,1
animation_curve_open = 0.46,1.0,0.29,1
blur = 1
blur_params_noise = 0.02
blur_params_num_passes = 2
blur_params_radius = 5
```
## Using nested attributes
## Using lists for duplicate keys
```nix
let
config = {
blur = 1;
blur_params = {
radius = 5;
num_passes = 2;
noise = 0.02;
};
animation_curve = {
open = "0.46,1.0,0.29,1";
close = "0.08,0.92,0,1";
```nix
let
config = {
bind = [
"SUPER,r,reload_config"
"Alt,space,spawn,rofi -show drun"
"Alt,Return,spawn,foot"
];
tagrule = [
"id:1,layout_name:tile"
"id:2,layout_name:scroller"
];
};
in lib.toMango {} config
```
**Output:**
```
bind = SUPER,r,reload_config
bind = Alt,space,spawn,rofi -show drun
bind = Alt,Return,spawn,foot
tagrule = id:1,layout_name:tile
tagrule = id:2,layout_name:scroller
```
## Using keymodes (submaps)
```nix
let
config = {
bind = [
"SUPER,Q,killclient"
"ALT,R,setkeymode,resize"
];
keymode = {
resize = {
bind = [
"NONE,Left,resizewin,-10,0"
"NONE,Right,resizewin,10,0"
"NONE,Escape,setkeymode,default"
];
};
};
in lib.toMango {} config
```
};
in lib.toMango {} config
```
**Output:**
```
animation_curve_close = 0.08,0.92,0,1
animation_curve_open = 0.46,1.0,0.29,1
blur = 1
blur_params_noise = 0.02
blur_params_num_passes = 2
blur_params_radius = 5
```
**Output:**
```
bind = SUPER,Q,killclient
bind = ALT,R,setkeymode,resize
## Using lists for duplicate keys
keymode = resize
bind = NONE,Left,resizewin,-10,0
bind = NONE,Right,resizewin,10,0
bind = NONE,Escape,setkeymode,default
```
```nix
let
config = {
bind = [
"SUPER,r,reload_config"
"Alt,space,spawn,rofi -show drun"
"Alt,Return,spawn,foot"
];
tagrule = [
"id:1,layout_name:tile"
"id:2,layout_name:scroller"
];
};
in lib.toMango {} config
```
**Output:**
```
bind = SUPER,r,reload_config
bind = Alt,space,spawn,rofi -show drun
bind = Alt,Return,spawn,foot
tagrule = id:1,layout_name:tile
tagrule = id:2,layout_name:scroller
```
## Using keymodes (submaps)
```nix
let
config = {
bind = [
"SUPER,Q,killclient"
"ALT,R,setkeymode,resize"
];
keymode = {
resize = {
bind = [
"NONE,Left,resizewin,-10,0"
"NONE,Right,resizewin,10,0"
"NONE,Escape,setkeymode,default"
];
};
};
};
in lib.toMango {} config
```
**Output:**
```
bind = SUPER,Q,killclient
bind = ALT,R,setkeymode,resize
keymode = resize
bind = NONE,Left,resizewin,-10,0
bind = NONE,Right,resizewin,10,0
bind = NONE,Escape,setkeymode,default
```
:::
:::
*/
toMango =
{
topCommandsPrefixes ? [ ],
bottomCommandsPrefixes ? [ ],
}:
attrs:
let
toMango' =
attrs:
let
# Specially configured `toKeyValue` generator with support for duplicate keys
# and a legible key-value separator.
mkCommands = generators.toKeyValue {
mkKeyValue = generators.mkKeyValueDefault { } " = ";
listsAsDuplicateKeys = true;
indent = ""; # No indent, since we don't have nesting
};
toMango = {
topCommandsPrefixes ? [],
bottomCommandsPrefixes ? [],
}: attrs: let
toMango' = attrs: let
# Specially configured `toKeyValue` generator with support for duplicate keys
# and a legible key-value separator.
mkCommands = generators.toKeyValue {
mkKeyValue = generators.mkKeyValueDefault {} " = ";
listsAsDuplicateKeys = true;
indent = ""; # No indent, since we don't have nesting
};
# Extract keymode definitions if they exist
keymodes = attrs.keymode or { };
attrsWithoutKeymodes = removeAttrs attrs [ "keymode" ];
# Extract keymode definitions if they exist
keymodes = attrs.keymode or {};
attrsWithoutKeymodes = removeAttrs attrs ["keymode"];
# Generate keymode blocks
# Format: keymode=name\nbind=...\nbind=...\n
mkKeymodeBlock =
name: modeAttrs:
let
modeCommands = flattenAttrs (p: k: "${p}_${k}") modeAttrs;
in
"keymode = ${name}\n${mkCommands modeCommands}";
# Generate keymode blocks
# Format: keymode=name\nbind=...\nbind=...\n
mkKeymodeBlock = name: modeAttrs: let
modeCommands = flattenAttrs (p: k: "${p}_${k}") modeAttrs;
in "keymode = ${name}\n${mkCommands modeCommands}";
keymodeBlocks =
if keymodes == { } then
""
else
"\n" + concatMapStrings (name: mkKeymodeBlock name keymodes.${name} + "\n") (attrNames keymodes);
keymodeBlocks =
if keymodes == {}
then ""
else "\n" + concatMapStrings (name: mkKeymodeBlock name keymodes.${name} + "\n") (attrNames keymodes);
# Flatten the attrset, combining keys in a "path" like `"a_b_c" = "x"`.
# Uses `flattenAttrs` with an underscore separator.
commands = flattenAttrs (p: k: "${p}_${k}") attrsWithoutKeymodes;
# Flatten the attrset, combining keys in a "path" like `"a_b_c" = "x"`.
# Uses `flattenAttrs` with an underscore separator.
commands = flattenAttrs (p: k: "${p}_${k}") attrsWithoutKeymodes;
# General filtering function to check if a key starts with any prefix in a given list.
filterCommands = list: n: foldl (acc: prefix: acc || hasPrefix prefix n) false list;
# General filtering function to check if a key starts with any prefix in a given list.
filterCommands = list: n: foldl (acc: prefix: acc || hasPrefix prefix n) false list;
# Partition keys into top commands and the rest
result = partition (filterCommands topCommandsPrefixes) (attrNames commands);
topCommands = filterAttrs (n: _: builtins.elem n result.right) commands;
remainingCommands = removeAttrs commands result.right;
# Partition keys into top commands and the rest
result = partition (filterCommands topCommandsPrefixes) (attrNames commands);
topCommands = filterAttrs (n: _: builtins.elem n result.right) commands;
remainingCommands = removeAttrs commands result.right;
# Partition remaining commands into bottom commands and regular commands
result2 = partition (filterCommands bottomCommandsPrefixes) result.wrong;
bottomCommands = filterAttrs (n: _: builtins.elem n result2.right) remainingCommands;
regularCommands = removeAttrs remainingCommands result2.right;
in
# Concatenate strings from mapping `mkCommands` over top, regular, and bottom commands.
# Keymodes are appended at the end.
concatMapStrings mkCommands [
topCommands
regularCommands
bottomCommands
]
+ keymodeBlocks;
# Partition remaining commands into bottom commands and regular commands
result2 = partition (filterCommands bottomCommandsPrefixes) result.wrong;
bottomCommands = filterAttrs (n: _: builtins.elem n result2.right) remainingCommands;
regularCommands = removeAttrs remainingCommands result2.right;
in
# Concatenate strings from mapping `mkCommands` over top, regular, and bottom commands.
# Keymodes are appended at the end.
concatMapStrings mkCommands [
topCommands
regularCommands
bottomCommands
]
+ keymodeBlocks;
in
toMango' attrs;
/**
Flatten a nested attribute set into a flat attribute set, using a custom key separator function.
Flatten a nested attribute set into a flat attribute set, using a custom key separator function.
This function recursively traverses a nested attribute set and produces a flat attribute set
where keys are joined using a user-defined function (`pred`). It allows transforming deeply
nested structures into a single-level attribute set while preserving key-value relationships.
This function recursively traverses a nested attribute set and produces a flat attribute set
where keys are joined using a user-defined function (`pred`). It allows transforming deeply
nested structures into a single-level attribute set while preserving key-value relationships.
Configuration:
Configuration:
* `pred` - A function `(string -> string -> string)` defining how keys should be concatenated.
* `pred` - A function `(string -> string -> string)` defining how keys should be concatenated.
# Inputs
# Inputs
Structured function argument:
Structured function argument:
: pred (required)
: A function that determines how parent and child keys should be combined into a single key.
It takes a `prefix` (parent key) and `key` (current key) and returns the joined key.
: pred (required)
: A function that determines how parent and child keys should be combined into a single key.
It takes a `prefix` (parent key) and `key` (current key) and returns the joined key.
Value:
Value:
: The nested attribute set to be flattened.
: The nested attribute set to be flattened.
# Type
# Type
```
flattenAttrs :: (String -> String -> String) -> AttrSet -> AttrSet
```
```
flattenAttrs :: (String -> String -> String) -> AttrSet -> AttrSet
```
# Examples
:::{.example}
# Examples
:::{.example}
```nix
let
nested = {
a = "3";
b = { c = "4"; d = "5"; };
};
```nix
let
nested = {
a = "3";
b = { c = "4"; d = "5"; };
};
separator = (prefix: key: "${prefix}.${key}"); # Use dot notation
in lib.flattenAttrs separator nested
```
separator = (prefix: key: "${prefix}.${key}"); # Use dot notation
in lib.flattenAttrs separator nested
```
**Output:**
```nix
{
"a" = "3";
"b.c" = "4";
"b.d" = "5";
}
```
**Output:**
```nix
{
"a" = "3";
"b.c" = "4";
"b.d" = "5";
}
```
:::
:::
*/
flattenAttrs =
pred: attrs:
let
flattenAttrs' =
prefix: attrs:
builtins.foldl' (
acc: key:
let
value = attrs.${key};
newKey = if prefix == "" then key else pred prefix key;
in
acc // (if builtins.isAttrs value then flattenAttrs' newKey value else { "${newKey}" = value; })
) { } (builtins.attrNames attrs);
in
flattenAttrs = pred: attrs: let
flattenAttrs' = prefix: attrs:
builtins.foldl' (
acc: key: let
value = attrs.${key};
newKey =
if prefix == ""
then key
else pred prefix key;
in
acc
// (
if builtins.isAttrs value
then flattenAttrs' newKey value
else {"${newKey}" = value;}
)
) {} (builtins.attrNames attrs);
in
flattenAttrs' "" attrs;
in
{
in {
inherit flattenAttrs toMango;
}

View file

@ -1,4 +1,4 @@
self: {
mangoPackage: {
config,
lib,
pkgs,
@ -16,17 +16,16 @@ in {
};
package = lib.mkOption {
type = lib.types.package;
default = self.packages.${pkgs.stdenv.hostPlatform.system}.mango;
default = mangoPackage;
description = "The mango package to use";
};
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages =
[
cfg.package
];
environment.systemPackages = [
cfg.package
];
xdg.portal = {
enable = lib.mkDefault true;
@ -60,7 +59,7 @@ in {
programs.xwayland.enable = lib.mkDefault true;
services = {
displayManager.sessionPackages = lib.mkIf cfg.addLoginEntry [ cfg.package ];
displayManager.sessionPackages = lib.mkIf cfg.addLoginEntry [cfg.package];
graphical-desktop.enable = lib.mkDefault true;
};