feat(nix): add keymode support for modal keybindings

This commit is contained in:
Ananya Timalsina 2026-02-15 14:04:56 +01:00 committed by DreamMaoMao
parent c7c41c3103
commit b63e93fc09
2 changed files with 71 additions and 2 deletions

View file

@ -107,6 +107,9 @@ in
This option uses a structured format that is converted to Mango's This option uses a structured format that is converted to Mango's
configuration syntax. Nested attributes are flattened with underscore separators. configuration syntax. Nested attributes are flattened with underscore separators.
For example: `animation.duration_open = 400` becomes `animation_duration_open = 400` For example: `animation.duration_open = 400` becomes `animation_duration_open = 400`
Keymodes (submaps) are supported via the special `keymode` attribute. Each keymode
is a nested attribute set under `keymode` that contains its own bindings.
::: :::
''; '';
example = lib.literalExpression '' example = lib.literalExpression ''
@ -139,12 +142,23 @@ in
"SUPER,r,reload_config" "SUPER,r,reload_config"
"Alt,space,spawn,rofi -show drun" "Alt,space,spawn,rofi -show drun"
"Alt,Return,spawn,foot" "Alt,Return,spawn,foot"
"ALT,R,setkeymode,resize" # Enter resize mode
]; ];
tagrule = [ tagrule = [
"id:1,layout_name:tile" "id:1,layout_name:tile"
"id:2,layout_name:scroller" "id:2,layout_name:scroller"
]; ];
# Keymodes (submaps) for modal keybindings
keymode = {
resize = {
bind = [
"NONE,Left,resizewin,-10,0"
"NONE,Escape,setkeymode,default"
];
};
};
} }
''; '';
}; };

View file

@ -6,6 +6,7 @@ let
foldl foldl
generators generators
partition partition
removeAttrs
; ;
inherit (lib.strings) inherit (lib.strings)
@ -136,6 +137,39 @@ let
tagrule = id:2,layout_name:scroller 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 =
@ -156,9 +190,28 @@ let
indent = ""; # No indent, since we don't have nesting indent = ""; # No indent, since we don't have nesting
}; };
# 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}";
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"`. # 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}") attrs; 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;
@ -174,11 +227,13 @@ let
regularCommands = removeAttrs remainingCommands result2.right; regularCommands = removeAttrs remainingCommands result2.right;
in in
# Concatenate strings from mapping `mkCommands` over top, regular, and bottom commands. # Concatenate strings from mapping `mkCommands` over top, regular, and bottom commands.
# Keymodes are appended at the end.
concatMapStrings mkCommands [ concatMapStrings mkCommands [
topCommands topCommands
regularCommands regularCommands
bottomCommands bottomCommands
]; ]
+ keymodeBlocks;
in in
toMango' attrs; toMango' attrs;