refactor(nix): share glyph decoding helper

This commit is contained in:
2026-10-11 20:16:43 -04:00
parent 5b644e1fd2
commit 8edf330a06
14 changed files with 57 additions and 37 deletions

View File

@@ -3,6 +3,7 @@
inputs, inputs,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Configures Firefox as the desktop browser. # Configures Firefox as the desktop browser.
@@ -28,7 +29,7 @@ in
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
registry.window-icon.${config.networking.hostName}.firefox = { registry.window-icon.${config.networking.hostName}.firefox = {
class = ".*[Ff]irefox.*"; class = ".*[Ff]irefox.*";
icon = builtins.fromJSON ''"\uf269"''; icon = util.glyph "f269";
}; };
home-manager.users.${config.user.name} = hm: { home-manager.users.${config.user.name} = hm: {

View File

@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Ghostty as the desktop terminal. # Ghostty as the desktop terminal.
@@ -22,7 +23,7 @@ in
registry.window-icon.${config.networking.hostName}.ghostty = { registry.window-icon.${config.networking.hostName}.ghostty = {
class = "com.mitchellh.ghostty"; class = "com.mitchellh.ghostty";
icon = builtins.fromJSON ''"\uf120"''; icon = util.glyph "f120";
}; };
home-manager.users.${user}.home.packages = [ pkgs.ghostty ]; home-manager.users.${user}.home.packages = [ pkgs.ghostty ];

View File

@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Obsidian as the desktop note-taking vault. # Obsidian as the desktop note-taking vault.
@@ -17,7 +18,7 @@ in
registry.window-icon.${config.networking.hostName}.obsidian = { registry.window-icon.${config.networking.hostName}.obsidian = {
class = "obsidian"; class = "obsidian";
icon = builtins.fromJSON ''"\uf02d"''; icon = util.glyph "f02d";
}; };
}; };
} }

View File

@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Signal desktop messenger. # Signal desktop messenger.
@@ -16,7 +17,7 @@ in
registry.window-icon.${config.networking.hostName}.signal = { registry.window-icon.${config.networking.hostName}.signal = {
class = "[Ss]ignal"; class = "[Ss]ignal";
icon = builtins.fromJSON ''"\uf4ad"''; icon = util.glyph "f4ad";
}; };
}; };
} }

View File

@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Steam game launcher and runtime integration. # Steam game launcher and runtime integration.
@@ -26,7 +27,7 @@
registry.window-icon.${config.networking.hostName}.steam = { registry.window-icon.${config.networking.hostName}.steam = {
class = "[Ss]team"; class = "[Ss]team";
icon = builtins.fromJSON ''"\uf1b6"''; icon = util.glyph "f1b6";
}; };
}; };
} }

View File

@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Vesktop, a Discord client with Vencord built in. # Vesktop, a Discord client with Vencord built in.
@@ -17,7 +18,7 @@ in
registry.window-icon.${config.networking.hostName}.vesktop = { registry.window-icon.${config.networking.hostName}.vesktop = {
class = "[Vv]esktop"; class = "[Vv]esktop";
icon = builtins.fromJSON ''"\uf1ff"''; icon = util.glyph "f1ff";
}; };
}; };
} }

View File

@@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
util,
... ...
}: }:
# The Hyprland compositor. # The Hyprland compositor.
@@ -235,7 +236,7 @@
on-click = "activate"; on-click = "activate";
format = "{id} {windows}"; format = "{id} {windows}";
format-window-separator = " "; format-window-separator = " ";
window-rewrite-default = builtins.fromJSON ''"\uf2d0"''; window-rewrite-default = util.glyph "f2d0";
window-rewrite = lib.mapAttrs' ( window-rewrite = lib.mapAttrs' (
_name: windowIcon: lib.nameValuePair "class<${windowIcon.class}>" windowIcon.icon _name: windowIcon: lib.nameValuePair "class<${windowIcon.class}>" windowIcon.icon
) (lib.attrByPath [ config.networking.hostName ] { } config.registry.window-icon); ) (lib.attrByPath [ config.networking.hostName ] { } config.registry.window-icon);

View File

@@ -2,12 +2,19 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# The lock screen: a hyprlock session-lock surface the compositor owns. # The lock screen: a hyprlock session-lock surface the compositor owns.
let let
sleepIcon = builtins.fromJSON ''"\udb81\udcb2"''; sleepIcon = util.glyph [
sleepOffIcon = builtins.fromJSON ''"\udb81\udcb3"''; "db81"
"dcb2"
];
sleepOffIcon = util.glyph [
"db81"
"dcb3"
];
idleLockToggle = pkgs.writeShellScript "lockscreen-idle-inhibit-toggle" '' idleLockToggle = pkgs.writeShellScript "lockscreen-idle-inhibit-toggle" ''
unit=lockscreen-idle-inhibit.service unit=lockscreen-idle-inhibit.service

View File

@@ -2,17 +2,16 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# mako as the notification daemon: toasts, a do-not-disturb mode, and history recall. # mako as the notification daemon: toasts, a do-not-disturb mode, and history recall.
let let
glyph = code: builtins.fromJSON ''"\u${code}"'';
dndStatus = pkgs.writeShellScript "waybar-dnd-status" '' dndStatus = pkgs.writeShellScript "waybar-dnd-status" ''
if ${lib.getExe' pkgs.mako "makoctl"} mode 2>/dev/null | ${lib.getExe pkgs.gnugrep} -qx dnd; then if ${lib.getExe' pkgs.mako "makoctl"} mode 2>/dev/null | ${lib.getExe pkgs.gnugrep} -qx dnd; then
printf '{"text":"${glyph "f1f6"}","tooltip":"Do not disturb: on","class":"dnd"}\n' printf '{"text":"${util.glyph "f1f6"}","tooltip":"Do not disturb: on","class":"dnd"}\n'
else else
printf '{"text":"${glyph "f0f3"}","tooltip":"Notifications on","class":"active"}\n' printf '{"text":"${util.glyph "f0f3"}","tooltip":"Notifications on","class":"active"}\n'
fi fi
''; '';

View File

@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Waybar: a top status bar reading system state at a glance. # Waybar: a top status bar reading system state at a glance.
@@ -30,10 +31,6 @@ let
registeredWaybarModuleSettings = lib.mapAttrs (_name: module: module.settings) hostWaybarModules; registeredWaybarModuleSettings = lib.mapAttrs (_name: module: module.settings) hostWaybarModules;
# A Nerd Font Private-Use-Area codepoint as a literal character, decoded
# through JSON so the glyph survives as bytes rather than an editor paste.
g = code: builtins.fromJSON ''"\u${code}"'';
networkStatus = pkgs.writeShellScript "waybar-network-status" '' networkStatus = pkgs.writeShellScript "waybar-network-status" ''
active=$( active=$(
${lib.getExe' pkgs.networkmanager "nmcli"} -t -f DEVICE,TYPE,STATE,CONNECTION device status \ ${lib.getExe' pkgs.networkmanager "nmcli"} -t -f DEVICE,TYPE,STATE,CONNECTION device status \
@@ -42,7 +39,7 @@ let
if [ -z "$active" ]; then if [ -z "$active" ]; then
${lib.getExe pkgs.jq} -cn \ ${lib.getExe pkgs.jq} -cn \
--arg text "${g "f127"} off" \ --arg text "${util.glyph "f127"} off" \
--arg tooltip "Network disconnected" \ --arg tooltip "Network disconnected" \
--arg class "disconnected" \ --arg class "disconnected" \
'{ text: $text, tooltip: $tooltip, class: $class }' '{ text: $text, tooltip: $tooltip, class: $class }'
@@ -52,7 +49,7 @@ let
IFS=: read -r device type _state connection <<< "$active" IFS=: read -r device type _state connection <<< "$active"
case "$type" in case "$type" in
wifi) icon="${g "f1eb"}" ;; wifi) icon="${util.glyph "f1eb"}" ;;
ethernet) icon="LAN" ;; ethernet) icon="LAN" ;;
*) icon="NET" ;; *) icon="NET" ;;
esac esac
@@ -99,7 +96,6 @@ in
modules-left = waybarModulesFor "left"; modules-left = waybarModulesFor "left";
modules-center = waybarModulesFor "center"; modules-center = waybarModulesFor "center";
modules-right = waybarModulesFor "right"; modules-right = waybarModulesFor "right";
} }
registeredWaybarModuleSettings registeredWaybarModuleSettings
]; ];
@@ -133,13 +129,13 @@ in
order = 70; order = 70;
settings = { settings = {
format = "{icon} {capacity}%"; format = "{icon} {capacity}%";
format-charging = "${g "f0e7"} {capacity}%"; format-charging = "${util.glyph "f0e7"} {capacity}%";
format-icons = [ format-icons = [
(g "f244") (util.glyph "f244")
(g "f243") (util.glyph "f243")
(g "f242") (util.glyph "f242")
(g "f241") (util.glyph "f241")
(g "f240") (util.glyph "f240")
]; ];
states = { states = {
warning = 20; warning = 20;

View File

@@ -2,12 +2,10 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# PipeWire as the desktop audio server. # PipeWire as the desktop audio server.
let
glyph = code: builtins.fromJSON ''"\u${code}"'';
in
{ {
options.modules.desktop.utilities.audio.enable = lib.mkEnableOption "the PipeWire audio server"; options.modules.desktop.utilities.audio.enable = lib.mkEnableOption "the PipeWire audio server";
@@ -45,8 +43,8 @@ in
mpris = { mpris = {
order = 30; order = 30;
settings = { settings = {
format = "${glyph "f001"} {title}"; format = "${util.glyph "f001"} {title}";
format-paused = "${glyph "f04c"} {title}"; format-paused = "${util.glyph "f04c"} {title}";
max-length = 40; max-length = 40;
on-click = "play-pause"; on-click = "play-pause";
on-scroll-up = "next"; on-scroll-up = "next";
@@ -58,11 +56,11 @@ in
order = 40; order = 40;
settings = { settings = {
format = "{icon} {volume}%"; format = "{icon} {volume}%";
format-muted = "${glyph "f026"} muted"; format-muted = "${util.glyph "f026"} muted";
format-icons = [ format-icons = [
(glyph "f026") (util.glyph "f026")
(glyph "f027") (util.glyph "f027")
(glyph "f028") (util.glyph "f028")
]; ];
on-click = "${lib.getExe' pkgs.wireplumber "wpctl"} set-mute @DEFAULT_AUDIO_SINK@ toggle"; on-click = "${lib.getExe' pkgs.wireplumber "wpctl"} set-mute @DEFAULT_AUDIO_SINK@ toggle";
}; };

View File

@@ -2,11 +2,12 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Keybound screen recording: pick a region, then toggle a video-only capture. # Keybound screen recording: pick a region, then toggle a video-only capture.
let let
recordingIcon = builtins.fromJSON ''"\uf03d"''; recordingIcon = util.glyph "f03d";
# A single key both starts and stops. # A single key both starts and stops.
# A running wf-recorder is stopped with SIGINT so it finalises the file. # A running wf-recorder is stopped with SIGINT so it finalises the file.

View File

@@ -2,12 +2,16 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
let let
cfg = config.modules.network.vpn-client; # NOLINT(let_order) cfg = config.modules.network.vpn-client; # NOLINT(let_order)
vpnIcon = builtins.fromJSON ''"\udb83\udc9d"''; vpnIcon = util.glyph [
"db83"
"dc9d"
];
vpnStatus = pkgs.writeShellScript "waybar-vpn-status" '' vpnStatus = pkgs.writeShellScript "waybar-vpn-status" ''
interface=${lib.escapeShellArg cfg.interface} interface=${lib.escapeShellArg cfg.interface}

View File

@@ -25,6 +25,14 @@ in
removeNixSuffix = path: lib.removeSuffix ".nix" (builtins.baseNameOf path); removeNixSuffix = path: lib.removeSuffix ".nix" (builtins.baseNameOf path);
glyph =
code:
builtins.fromJSON (
"\""
+ (if builtins.isList code then lib.concatMapStrings (part: "\\u${part}") code else "\\u${code}")
+ "\""
);
registry.predicates.uniqueValue = uniqueValue; registry.predicates.uniqueValue = uniqueValue;
registry.predicates.uniquePerHost = registry.predicates.uniquePerHost =