mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-06-19 14:33:16 -04:00
refactor: format nix code with alejandra & rename nix files for clarity
This commit is contained in:
parent
bb86ea12ca
commit
df492dab6b
6 changed files with 298 additions and 311 deletions
10
flake.nix
10
flake.nix
|
|
@ -40,25 +40,25 @@
|
||||||
system,
|
system,
|
||||||
}: let
|
}: let
|
||||||
inherit (pkgs) callPackage;
|
inherit (pkgs) callPackage;
|
||||||
mango = callPackage ./nix {
|
mango = callPackage ./nix/package.nix {
|
||||||
inherit (scenefx.packages.${system}) scenefx;
|
inherit (scenefx.packages.${system}) scenefx;
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
inherit mango;
|
inherit mango;
|
||||||
default = mango;
|
default = mango;
|
||||||
hm-options-json = callPackage (import ./nix/generate-options.nix self) {
|
hm-options-json = callPackage (import ./nix/generate-options.nix self) {
|
||||||
module = ./nix/hm-modules.nix;
|
module = ./nix/hm-module.nix;
|
||||||
optionPrefix = "wayland.windowManager.mango.";
|
optionPrefix = "wayland.windowManager.mango.";
|
||||||
};
|
};
|
||||||
nixos-options-json = callPackage (import ./nix/generate-options.nix self) {
|
nixos-options-json = callPackage (import ./nix/generate-options.nix self) {
|
||||||
module = ./nix/nixos-modules.nix;
|
module = ./nix/nixos-module.nix;
|
||||||
optionPrefix = "programs.mango.";
|
optionPrefix = "programs.mango.";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
nixosModules.mango = import ./nix/nixos-modules.nix self;
|
nixosModules.mango = import ./nix/nixos-module.nix self;
|
||||||
hmModules.mango = import ./nix/hm-modules.nix self;
|
hmModules.mango = import ./nix/hm-module.nix self;
|
||||||
|
|
||||||
devShells = forEachSystem (
|
devShells = forEachSystem (
|
||||||
{system, ...}: {
|
{system, ...}: {
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,18 @@
|
||||||
self:
|
self: {
|
||||||
{
|
|
||||||
pkgs,
|
pkgs,
|
||||||
lib ? pkgs.lib,
|
lib ? pkgs.lib,
|
||||||
module,
|
module,
|
||||||
optionPrefix,
|
optionPrefix,
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
# Absolute store path of the flake root, used to compute relative subpaths
|
# Absolute store path of the flake root, used to compute relative subpaths
|
||||||
repoPath = toString self;
|
repoPath = toString self;
|
||||||
|
|
||||||
eval = lib.evalModules {
|
eval = lib.evalModules {
|
||||||
modules = [
|
modules = [
|
||||||
(import module self)
|
(import module self)
|
||||||
{ _module.check = false; }
|
{_module.check = false;}
|
||||||
];
|
];
|
||||||
specialArgs = { inherit pkgs; };
|
specialArgs = {inherit pkgs;};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Relative path of the module file within the repo (e.g. "nix/hm-modules.nix")
|
# Relative path of the module file within the repo (e.g. "nix/hm-modules.nix")
|
||||||
|
|
@ -28,15 +26,14 @@ let
|
||||||
|
|
||||||
optionsDoc = pkgs.nixosOptionsDoc {
|
optionsDoc = pkgs.nixosOptionsDoc {
|
||||||
options = eval.options;
|
options = eval.options;
|
||||||
transformOptions =
|
transformOptions = opt:
|
||||||
opt:
|
|
||||||
opt
|
opt
|
||||||
// {
|
// {
|
||||||
visible = opt.visible && !opt.internal;
|
visible = opt.visible && !opt.internal;
|
||||||
# Strip the option prefix so docs show "enable" instead of "programs.mango.enable"
|
# Strip the option prefix so docs show "enable" instead of "programs.mango.enable"
|
||||||
name = lib.removePrefix optionPrefix opt.name;
|
name = lib.removePrefix optionPrefix opt.name;
|
||||||
declarations = [ moduleDeclaration ];
|
declarations = [moduleDeclaration];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
optionsDoc.optionsJSON
|
optionsDoc.optionsJSON
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
self:
|
self: {
|
||||||
{
|
|
||||||
lib,
|
lib,
|
||||||
config,
|
config,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
cfg = config.wayland.windowManager.mango;
|
cfg = config.wayland.windowManager.mango;
|
||||||
selflib = import ./lib.nix lib;
|
selflib = import ./lib.nix lib;
|
||||||
variables = lib.concatStringsSep " " cfg.systemd.variables;
|
variables = lib.concatStringsSep " " cfg.systemd.variables;
|
||||||
|
|
@ -15,8 +13,7 @@ let
|
||||||
${lib.optionalString cfg.systemd.enable systemdActivation}
|
${lib.optionalString cfg.systemd.enable systemdActivation}
|
||||||
${cfg.autostart_sh}
|
${cfg.autostart_sh}
|
||||||
'';
|
'';
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options = {
|
options = {
|
||||||
wayland.windowManager.mango = with lib; {
|
wayland.windowManager.mango = with lib; {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
|
|
@ -59,7 +56,7 @@ in
|
||||||
"XCURSOR_THEME"
|
"XCURSOR_THEME"
|
||||||
"XCURSOR_SIZE"
|
"XCURSOR_SIZE"
|
||||||
];
|
];
|
||||||
example = [ "--all" ];
|
example = ["--all"];
|
||||||
description = ''
|
description = ''
|
||||||
Environment variables imported into the systemd and D-Bus user environment.
|
Environment variables imported into the systemd and D-Bus user environment.
|
||||||
'';
|
'';
|
||||||
|
|
@ -80,25 +77,23 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
settings = mkOption {
|
settings = mkOption {
|
||||||
type =
|
type = with lib.types; let
|
||||||
with lib.types;
|
valueType =
|
||||||
let
|
nullOr (oneOf [
|
||||||
valueType =
|
bool
|
||||||
nullOr (oneOf [
|
int
|
||||||
bool
|
float
|
||||||
int
|
str
|
||||||
float
|
path
|
||||||
str
|
(attrsOf valueType)
|
||||||
path
|
(listOf valueType)
|
||||||
(attrsOf valueType)
|
])
|
||||||
(listOf valueType)
|
// {
|
||||||
])
|
description = "Mango configuration value";
|
||||||
// {
|
};
|
||||||
description = "Mango configuration value";
|
in
|
||||||
};
|
|
||||||
in
|
|
||||||
valueType;
|
valueType;
|
||||||
default = { };
|
default = {};
|
||||||
description = ''
|
description = ''
|
||||||
Mango configuration written in Nix. Entries with the same key
|
Mango configuration written in Nix. Entries with the same key
|
||||||
should be written as lists. Variables and colors names should be
|
should be written as lists. Variables and colors names should be
|
||||||
|
|
@ -178,21 +173,21 @@ in
|
||||||
};
|
};
|
||||||
topPrefixes = mkOption {
|
topPrefixes = mkOption {
|
||||||
type = with lib.types; listOf str;
|
type = with lib.types; listOf str;
|
||||||
default = [ ];
|
default = [];
|
||||||
description = ''
|
description = ''
|
||||||
List of prefixes for attributes that should appear at the top of the config file.
|
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.
|
Attributes starting with these prefixes will be sorted to the beginning.
|
||||||
'';
|
'';
|
||||||
example = [ "source" ];
|
example = ["source"];
|
||||||
};
|
};
|
||||||
bottomPrefixes = mkOption {
|
bottomPrefixes = mkOption {
|
||||||
type = with lib.types; listOf str;
|
type = with lib.types; listOf str;
|
||||||
default = [ ];
|
default = [];
|
||||||
description = ''
|
description = ''
|
||||||
List of prefixes for attributes that should appear at the bottom of the config file.
|
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.
|
Attributes starting with these prefixes will be sorted to the end.
|
||||||
'';
|
'';
|
||||||
example = [ "source" ];
|
example = ["source"];
|
||||||
};
|
};
|
||||||
autostart_sh = mkOption {
|
autostart_sh = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
|
|
@ -217,25 +212,25 @@ in
|
||||||
finalConfigText =
|
finalConfigText =
|
||||||
# Support old string-based config during transition period
|
# Support old string-based config during transition period
|
||||||
(
|
(
|
||||||
if builtins.isString cfg.settings then
|
if builtins.isString cfg.settings
|
||||||
cfg.settings
|
then cfg.settings
|
||||||
else
|
else
|
||||||
lib.optionalString (cfg.settings != { }) (
|
lib.optionalString (cfg.settings != {}) (
|
||||||
selflib.toMango {
|
selflib.toMango {
|
||||||
topCommandsPrefixes = cfg.topPrefixes;
|
topCommandsPrefixes = cfg.topPrefixes;
|
||||||
bottomCommandsPrefixes = cfg.bottomPrefixes;
|
bottomCommandsPrefixes = cfg.bottomPrefixes;
|
||||||
} cfg.settings
|
}
|
||||||
|
cfg.settings
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
+ lib.optionalString (cfg.extraConfig != "") cfg.extraConfig
|
+ lib.optionalString (cfg.extraConfig != "") cfg.extraConfig
|
||||||
+ lib.optionalString (cfg.autostart_sh != "") "\nexec-once=~/.config/mango/autostart.sh\n";
|
+ 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"
|
cp ${pkgs.writeText "mango-config.conf" finalConfigText} "$out"
|
||||||
${cfg.package}/bin/mango -c "$out" -p || exit 1
|
${cfg.package}/bin/mango -c "$out" -p || exit 1
|
||||||
'';
|
'';
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
# Backwards compatibility warning for old string-based config
|
# Backwards compatibility warning for old string-based config
|
||||||
warnings = lib.optional (builtins.isString cfg.settings) ''
|
warnings = lib.optional (builtins.isString cfg.settings) ''
|
||||||
wayland.windowManager.mango.settings: Using a string for settings is deprecated.
|
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.
|
The old string format will be removed in a future release.
|
||||||
'';
|
'';
|
||||||
|
|
||||||
home.packages = [ cfg.package ];
|
home.packages = [cfg.package];
|
||||||
xdg.configFile = {
|
xdg.configFile = {
|
||||||
"mango/config.conf" =
|
"mango/config.conf" =
|
||||||
lib.mkIf (cfg.settings != { } || cfg.extraConfig != "" || cfg.autostart_sh != "")
|
lib.mkIf (cfg.settings != {} || cfg.extraConfig != "" || cfg.autostart_sh != "")
|
||||||
{
|
{
|
||||||
source = validatedConfig;
|
source = validatedConfig;
|
||||||
};
|
};
|
||||||
"mango/autostart.sh" = lib.mkIf (cfg.autostart_sh != "") {
|
"mango/autostart.sh" = lib.mkIf (cfg.autostart_sh != "") {
|
||||||
source = autostart_sh;
|
source = autostart_sh;
|
||||||
executable = true;
|
executable = true;
|
||||||
|
|
@ -259,13 +254,14 @@ in
|
||||||
systemd.user.targets.mango-session = lib.mkIf cfg.systemd.enable {
|
systemd.user.targets.mango-session = lib.mkIf cfg.systemd.enable {
|
||||||
Unit = {
|
Unit = {
|
||||||
Description = "mango compositor session";
|
Description = "mango compositor session";
|
||||||
Documentation = [ "man:systemd.special(7)" ];
|
Documentation = ["man:systemd.special(7)"];
|
||||||
BindsTo = [ "graphical-session.target" ];
|
BindsTo = ["graphical-session.target"];
|
||||||
Wants = [
|
Wants =
|
||||||
"graphical-session-pre.target"
|
[
|
||||||
]
|
"graphical-session-pre.target"
|
||||||
++ lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target";
|
]
|
||||||
After = [ "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";
|
Before = lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
481
nix/lib.nix
481
nix/lib.nix
|
|
@ -1,6 +1,6 @@
|
||||||
lib:
|
lib: let
|
||||||
let
|
inherit
|
||||||
inherit (lib)
|
(lib)
|
||||||
attrNames
|
attrNames
|
||||||
filterAttrs
|
filterAttrs
|
||||||
foldl
|
foldl
|
||||||
|
|
@ -9,304 +9,299 @@ let
|
||||||
removeAttrs
|
removeAttrs
|
||||||
;
|
;
|
||||||
|
|
||||||
inherit (lib.strings)
|
inherit
|
||||||
|
(lib.strings)
|
||||||
concatMapStrings
|
concatMapStrings
|
||||||
hasPrefix
|
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
|
This function takes a nested attribute set and converts it into Mango-compatible
|
||||||
configuration syntax, supporting top, bottom, and regular command sections.
|
configuration syntax, supporting top, bottom, and regular command sections.
|
||||||
|
|
||||||
Commands are flattened using the `flattenAttrs` function, and attributes are formatted as
|
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.
|
`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: `[]`).
|
* `topCommandsPrefixes` - A list of prefixes to define **top** commands (default: `[]`).
|
||||||
* `bottomCommandsPrefixes` - A list of prefixes to define **bottom** 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 function ensures top commands appear **first** and bottom commands **last**.
|
||||||
- The generated configuration is a **single string**, suitable for writing to a config file.
|
- The generated configuration is a **single string**, suitable for writing to a config file.
|
||||||
- Lists are converted into multiple entries, ensuring compatibility with Mango.
|
- Lists are converted into multiple entries, ensuring compatibility with Mango.
|
||||||
|
|
||||||
# Inputs
|
# Inputs
|
||||||
|
|
||||||
Structured function argument:
|
Structured function argument:
|
||||||
|
|
||||||
: topCommandsPrefixes (optional, default: `[]`)
|
: topCommandsPrefixes (optional, default: `[]`)
|
||||||
: A list of prefixes that define **top** commands. Any key starting with one of these
|
: 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.
|
prefixes will be placed at the beginning of the configuration.
|
||||||
: bottomCommandsPrefixes (optional, default: `[]`)
|
: bottomCommandsPrefixes (optional, default: `[]`)
|
||||||
: A list of prefixes that define **bottom** commands. Any key starting with one of these
|
: 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.
|
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
|
# Examples
|
||||||
:::{.example}
|
:::{.example}
|
||||||
|
|
||||||
## Basic mangowc configuration
|
## Basic mangowc configuration
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
let
|
let
|
||||||
config = {
|
config = {
|
||||||
blur = 1;
|
blur = 1;
|
||||||
blur_params_radius = 5;
|
blur_params_radius = 5;
|
||||||
border_radius = 6;
|
border_radius = 6;
|
||||||
animations = 1;
|
animations = 1;
|
||||||
animation_duration_open = 400;
|
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:**
|
**Output:**
|
||||||
```
|
```
|
||||||
animations = 1
|
animation_curve_close = 0.08,0.92,0,1
|
||||||
animation_duration_open = 400
|
animation_curve_open = 0.46,1.0,0.29,1
|
||||||
blur = 1
|
blur = 1
|
||||||
blur_params_radius = 5
|
blur_params_noise = 0.02
|
||||||
border_radius = 6
|
blur_params_num_passes = 2
|
||||||
```
|
blur_params_radius = 5
|
||||||
|
```
|
||||||
|
|
||||||
## Using nested attributes
|
## Using lists for duplicate keys
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
let
|
let
|
||||||
config = {
|
config = {
|
||||||
blur = 1;
|
bind = [
|
||||||
blur_params = {
|
"SUPER,r,reload_config"
|
||||||
radius = 5;
|
"Alt,space,spawn,rofi -show drun"
|
||||||
num_passes = 2;
|
"Alt,Return,spawn,foot"
|
||||||
noise = 0.02;
|
];
|
||||||
};
|
tagrule = [
|
||||||
animation_curve = {
|
"id:1,layout_name:tile"
|
||||||
open = "0.46,1.0,0.29,1";
|
"id:2,layout_name:scroller"
|
||||||
close = "0.08,0.92,0,1";
|
];
|
||||||
|
};
|
||||||
|
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:**
|
**Output:**
|
||||||
```
|
```
|
||||||
animation_curve_close = 0.08,0.92,0,1
|
bind = SUPER,Q,killclient
|
||||||
animation_curve_open = 0.46,1.0,0.29,1
|
bind = ALT,R,setkeymode,resize
|
||||||
blur = 1
|
|
||||||
blur_params_noise = 0.02
|
|
||||||
blur_params_num_passes = 2
|
|
||||||
blur_params_radius = 5
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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 =
|
toMango = {
|
||||||
{
|
topCommandsPrefixes ? [],
|
||||||
topCommandsPrefixes ? [ ],
|
bottomCommandsPrefixes ? [],
|
||||||
bottomCommandsPrefixes ? [ ],
|
}: attrs: let
|
||||||
}:
|
toMango' = attrs: let
|
||||||
attrs:
|
# Specially configured `toKeyValue` generator with support for duplicate keys
|
||||||
let
|
# and a legible key-value separator.
|
||||||
toMango' =
|
mkCommands = generators.toKeyValue {
|
||||||
attrs:
|
mkKeyValue = generators.mkKeyValueDefault {} " = ";
|
||||||
let
|
listsAsDuplicateKeys = true;
|
||||||
# Specially configured `toKeyValue` generator with support for duplicate keys
|
indent = ""; # No indent, since we don't have nesting
|
||||||
# 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
|
# Extract keymode definitions if they exist
|
||||||
keymodes = attrs.keymode or { };
|
keymodes = attrs.keymode or {};
|
||||||
attrsWithoutKeymodes = removeAttrs attrs [ "keymode" ];
|
attrsWithoutKeymodes = removeAttrs attrs ["keymode"];
|
||||||
|
|
||||||
# Generate keymode blocks
|
# Generate keymode blocks
|
||||||
# Format: keymode=name\nbind=...\nbind=...\n
|
# Format: keymode=name\nbind=...\nbind=...\n
|
||||||
mkKeymodeBlock =
|
mkKeymodeBlock = name: modeAttrs: let
|
||||||
name: modeAttrs:
|
modeCommands = flattenAttrs (p: k: "${p}_${k}") modeAttrs;
|
||||||
let
|
in "keymode = ${name}\n${mkCommands modeCommands}";
|
||||||
modeCommands = flattenAttrs (p: k: "${p}_${k}") modeAttrs;
|
|
||||||
in
|
|
||||||
"keymode = ${name}\n${mkCommands modeCommands}";
|
|
||||||
|
|
||||||
keymodeBlocks =
|
keymodeBlocks =
|
||||||
if keymodes == { } then
|
if keymodes == {}
|
||||||
""
|
then ""
|
||||||
else
|
else "\n" + concatMapStrings (name: mkKeymodeBlock name keymodes.${name} + "\n") (attrNames keymodes);
|
||||||
"\n" + concatMapStrings (name: mkKeymodeBlock name keymodes.${name} + "\n") (attrNames keymodes);
|
|
||||||
|
|
||||||
# Flatten the attrset, combining keys in a "path" like `"a_b_c" = "x"`.
|
# Flatten the attrset, combining keys in a "path" like `"a_b_c" = "x"`.
|
||||||
# Uses `flattenAttrs` with an underscore separator.
|
# Uses `flattenAttrs` with an underscore separator.
|
||||||
commands = flattenAttrs (p: k: "${p}_${k}") attrsWithoutKeymodes;
|
commands = flattenAttrs (p: k: "${p}_${k}") attrsWithoutKeymodes;
|
||||||
|
|
||||||
# General filtering function to check if a key starts with any prefix in a given 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;
|
filterCommands = list: n: foldl (acc: prefix: acc || hasPrefix prefix n) false list;
|
||||||
|
|
||||||
# Partition keys into top commands and the rest
|
# Partition keys into top commands and the rest
|
||||||
result = partition (filterCommands topCommandsPrefixes) (attrNames commands);
|
result = partition (filterCommands topCommandsPrefixes) (attrNames commands);
|
||||||
topCommands = filterAttrs (n: _: builtins.elem n result.right) commands;
|
topCommands = filterAttrs (n: _: builtins.elem n result.right) commands;
|
||||||
remainingCommands = removeAttrs commands result.right;
|
remainingCommands = removeAttrs commands result.right;
|
||||||
|
|
||||||
# Partition remaining commands into bottom commands and regular commands
|
# Partition remaining commands into bottom commands and regular commands
|
||||||
result2 = partition (filterCommands bottomCommandsPrefixes) result.wrong;
|
result2 = partition (filterCommands bottomCommandsPrefixes) result.wrong;
|
||||||
bottomCommands = filterAttrs (n: _: builtins.elem n result2.right) remainingCommands;
|
bottomCommands = filterAttrs (n: _: builtins.elem n result2.right) remainingCommands;
|
||||||
regularCommands = removeAttrs remainingCommands result2.right;
|
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
|
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;
|
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
|
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
|
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.
|
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)
|
: pred (required)
|
||||||
: A function that determines how parent and child keys should be combined into a single key.
|
: 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.
|
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
|
# Examples
|
||||||
:::{.example}
|
:::{.example}
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
let
|
let
|
||||||
nested = {
|
nested = {
|
||||||
a = "3";
|
a = "3";
|
||||||
b = { c = "4"; d = "5"; };
|
b = { c = "4"; d = "5"; };
|
||||||
};
|
};
|
||||||
|
|
||||||
separator = (prefix: key: "${prefix}.${key}"); # Use dot notation
|
separator = (prefix: key: "${prefix}.${key}"); # Use dot notation
|
||||||
in lib.flattenAttrs separator nested
|
in lib.flattenAttrs separator nested
|
||||||
```
|
```
|
||||||
|
|
||||||
**Output:**
|
**Output:**
|
||||||
```nix
|
```nix
|
||||||
{
|
{
|
||||||
"a" = "3";
|
"a" = "3";
|
||||||
"b.c" = "4";
|
"b.c" = "4";
|
||||||
"b.d" = "5";
|
"b.d" = "5";
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
*/
|
*/
|
||||||
flattenAttrs =
|
flattenAttrs = pred: attrs: let
|
||||||
pred: attrs:
|
flattenAttrs' = prefix: attrs:
|
||||||
let
|
builtins.foldl' (
|
||||||
flattenAttrs' =
|
acc: key: let
|
||||||
prefix: attrs:
|
value = attrs.${key};
|
||||||
builtins.foldl' (
|
newKey =
|
||||||
acc: key:
|
if prefix == ""
|
||||||
let
|
then key
|
||||||
value = attrs.${key};
|
else pred prefix key;
|
||||||
newKey = if prefix == "" then key else pred prefix key;
|
in
|
||||||
in
|
acc
|
||||||
acc // (if builtins.isAttrs value then flattenAttrs' newKey value else { "${newKey}" = value; })
|
// (
|
||||||
) { } (builtins.attrNames attrs);
|
if builtins.isAttrs value
|
||||||
in
|
then flattenAttrs' newKey value
|
||||||
|
else {"${newKey}" = value;}
|
||||||
|
)
|
||||||
|
) {} (builtins.attrNames attrs);
|
||||||
|
in
|
||||||
flattenAttrs' "" attrs;
|
flattenAttrs' "" attrs;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
inherit flattenAttrs toMango;
|
inherit flattenAttrs toMango;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,9 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
environment.systemPackages =
|
environment.systemPackages = [
|
||||||
[
|
cfg.package
|
||||||
cfg.package
|
];
|
||||||
];
|
|
||||||
|
|
||||||
xdg.portal = {
|
xdg.portal = {
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
|
|
@ -60,7 +59,7 @@ in {
|
||||||
programs.xwayland.enable = lib.mkDefault true;
|
programs.xwayland.enable = lib.mkDefault true;
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
displayManager.sessionPackages = lib.mkIf cfg.addLoginEntry [ cfg.package ];
|
displayManager.sessionPackages = lib.mkIf cfg.addLoginEntry [cfg.package];
|
||||||
|
|
||||||
graphical-desktop.enable = lib.mkDefault true;
|
graphical-desktop.enable = lib.mkDefault true;
|
||||||
};
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue