Skip to content

Commit

Permalink
lib: add proper NixDoc
Browse files Browse the repository at this point in the history
  • Loading branch information
fufexan committed Feb 23, 2025
1 parent d723956 commit ee6a95d
Showing 1 changed file with 112 additions and 46 deletions.
158 changes: 112 additions & 46 deletions nix/lib.nix
Original file line number Diff line number Diff line change
@@ -1,47 +1,105 @@
lib: with lib; let
/**
Convert a structured Nix attribute set into Hyprland's configuration format.
This function takes a nested attribute set and converts it into Hyprland-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 Hyprland's expected format.
Configuration:
* `topCommandsPrefixes` - A list of prefixes to define **top** commands (default: `["$"]`).
* `bottomCommandsPrefixes` - A list of prefixes to define **bottom** commands (default: `[]`).
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 Hyprland.
# Inputs
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.
Value:
: The attribute set to be converted to Hyprland configuration format.
# Type
```
toHyprlang :: AttrSet -> AttrSet -> String
```
# Examples
:::{.example}
```nix
let
config = {
"$mod" = "SUPER";
monitor = {
"HDMI-A-1" = "1920x1080@60,0x0,1";
};
exec = [
"waybar"
"dunst"
];
};
in lib.toHyprlang {} config
```
**Output:**
```nix
"$mod = SUPER"
"monitor:HDMI-A-1 = 1920x1080@60,0x0,1"
"exec = waybar"
"exec = dunst"
```
:::
*/
toHyprlang = {
topCommandsPrefixes ? ["$"],
bottomCommandsPrefixes ? [],
}: attrs: let
toHyprlang' = attrs: let
# Specially configured `toKeyValue` generator with support for duplicate
# keys and legible key-value separator.
# Specially configured `toKeyValue` generator with support for duplicate keys
# and a legible key-value separator.
mkCommands = generators.toKeyValue {
mkKeyValue = generators.mkKeyValueDefault {} " = ";
listsAsDuplicateKeys = true;
# No indent, since we don't have nesting
indent = "";
indent = ""; # No indent, since we don't have nesting
};

# Flatten the attrset, combining keys in a "path" like `"a:b:c" = "x"`.
# See `flattenAttrs` for more info.
# Uses `flattenAttrs` with a colon separator.
commands = flattenAttrs (p: k: "${p}:${k}") attrs;

# General filtering command. Used for filtering top/bottom commands.
# Takes a list of prefixes and an element to check.
# Returns true if any of the prefixes matched, otherwise false.
filterCommands = list: n: foldl (acc: prefix: acc || hasPrefix prefix n) false list;

# FIXME(docs): improve explanations for the below amalgamation
# 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;

# Get topCommands attribute names
# Partition keys into top commands and the rest
result = partition (filterCommands topCommandsPrefixes) (attrNames commands);
# Filter top commands from all commands, using the attribute names
# previously obtained
topCommands = filterAttrs (n: _: (builtins.elem n result.right)) commands;
# Remaining commands = allcallCommands - topCommands
topCommands = filterAttrs (n: _: builtins.elem n result.right) commands;
remainingCommands = removeAttrs commands result.right;

# Get bottomCommands attr names from commands remaining (in result.wrong)
# Partition remaining commands into bottom commands and regular commands
result2 = partition (filterCommands bottomCommandsPrefixes) result.wrong;
# Filter bottom commands from remainingCommands using the attribute names
# previously obtained
bottomCommands = filterAttrs (n: _: (builtins.elem n result2.right)) remainingCommands;
# Regular commands = allCommands - topCommands - bottomCommands
bottomCommands = filterAttrs (n: _: builtins.elem n result2.right) remainingCommands;
regularCommands = removeAttrs remainingCommands result2.right;
in
# Concatenate the strings resulting from mapping `mkCommands` over the
# list of commands.
# Concatenate strings from mapping `mkCommands` over top, regular, and bottom commands.
concatMapStrings mkCommands [
topCommands
regularCommands
Expand All @@ -50,14 +108,37 @@ lib: with lib; let
in
toHyprlang' attrs;


/**
Flatten a nested attribute set into a flat attribute set, joining keys with a user-defined 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.
Configuration:
* `pred` - A function `(string -> string -> string)` defining how keys should be concatenated.
# Inputs
Structured function argument:
This function takes a function `pred` that determines how nested keys should be joined,
and an attribute set `attrs` that should be flattened.
: 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:
## Example
: The nested attribute set to be flattened.
# Type
```
flattenAttrs :: (String -> String -> String) -> AttrSet -> AttrSet
```
# Examples
:::{.example}
```nix
let
Expand All @@ -67,7 +148,7 @@ lib: with lib; let
};
separator = (prefix: key: "${prefix}.${key}"); # Use dot notation
in flattenAttrs separator nested
in lib.flattenAttrs separator nested
```
**Output:**
Expand All @@ -79,24 +160,9 @@ lib: with lib; let
}
```
## Parameters
- **pred** : function `(string -> string -> string)`
A function that takes a prefix and a key and returns the new flattened key.
- **attrs** : attrset
The nested attribute set to be flattened.
## Returns
- **attrset** : A flattened attribute set where keys are joined according to `pred`.
## Notes
:::
- This function works recursively for any level of nesting.
- It does not modify non-attribute values.
- If `pred` is `prefix: key: "${prefix}.${key}"`, it mimics dot notation.
*/
*/
flattenAttrs = pred: attrs: let
flattenAttrs' = prefix: attrs:
builtins.foldl' (
Expand Down

0 comments on commit ee6a95d

Please sign in to comment.