feat: adding iconWorkspaceMap option

fix: use builtin.toJSON

fix: removing useless function

fix: attrSet Names

fix: theme attrSet name

fix: jsonFormat type
This commit is contained in:
VESSE Léo
2025-03-22 22:30:50 +01:00
parent 3a5ad2a1db
commit f6f59bae69

View File

@@ -1,79 +1,72 @@
self: { lib, pkgs, config, ... }: self:
{
lib,
pkgs,
config,
...
}:
let let
inherit (lib) types mkIf mkOption mkEnableOption; inherit (lib)
types
mkIf
mkOption
mkEnableOption
;
cfg = config.programs.hyprpanel; cfg = config.programs.hyprpanel;
jsonFormat = pkgs.formats.json { }; jsonFormat = pkgs.formats.json { };
# No package option
package = if pkgs ? hyprpanel then pkgs.hyprpanel
else abort ''
******************************************************************************** # No package option
* HyprPanel * package =
*------------------------------------------------------------------------------* if pkgs ? hyprpanel then
* You didn't add the overlay! * pkgs.hyprpanel
* * else
* Either set 'overlay.enable = true' or manually add it to 'nixpkgs.overlays'. * abort ''
* If you use the 'nixosModule' for Home Manager and have 'useGlobalPkgs' set, *
* you will need to add the overlay yourself. * ********************************************************************************
******************************************************************************** * HyprPanel *
''; *------------------------------------------------------------------------------*
* You didn't add the overlay! *
* *
* Either set 'overlay.enable = true' or manually add it to 'nixpkgs.overlays'. *
* If you use the 'nixosModule' for Home Manager and have 'useGlobalPkgs' set, *
* you will need to add the overlay yourself. *
********************************************************************************
'';
# Shorthand lambda for self-documenting options under settings # Shorthand lambda for self-documenting options under settings
mkStrOption = default: mkOption { type = types.str; default = default; }; mkStrOption =
mkIntOption = default: mkOption { type = types.int; default = default; }; default:
mkBoolOption = default: mkOption { type = types.bool; default = default; }; mkOption {
mkStrListOption = default: mkOption { type = types.listOf types.str; default = default; }; type = types.str;
mkFloatOption = default: mkOption { type = types.float; default = default; }; default = default;
};
mkIntOption =
default:
mkOption {
type = types.int;
default = default;
};
mkBoolOption =
default:
mkOption {
type = types.bool;
default = default;
};
mkStrListOption =
default:
mkOption {
type = types.listOf types.str;
default = default;
};
mkFloatOption =
default:
mkOption {
type = types.float;
default = default;
};
# TODO: Please merge https://github.com/Jas-SinghFSU/HyprPanel/pull/497
# Do not ask what these do...
flattenAttrs = attrSet: prefix:
let
process = key: value:
if builtins.isAttrs value then
flattenAttrs value "${prefix}${key}."
else
{ "${prefix}${key}" = value; };
in
builtins.foldl' (acc: key:
acc // process key attrSet.${key}
) {} (builtins.attrNames attrSet);
toNestedValue =
let
escapeString = s: builtins.replaceStrings [ "\"" ] [ "\\\"" ] s;
in
value:
if builtins.isBool value then
if value then "true" else "false"
else if (builtins.isInt value || builtins.isFloat value) then
builtins.toString value
else if builtins.isString value then
"\"" + escapeString value + "\""
else if builtins.isList value then
let
items = builtins.map toNestedValue value;
in
"[\n" + (builtins.concatStringsSep ", " items) + "\n]"
else if builtins.isAttrs value then
let
keys = builtins.attrNames value;
toKeyValue = k: "\"${k}\": ${toNestedValue value.${k}}";
inner = builtins.concatStringsSep ", " (builtins.map toKeyValue keys);
in
"{\n" + inner + "\n}"
else
abort "Unexpected error! Please post a new issue and @benvonh...";
toNestedObject = attrSet:
let
keys = builtins.attrNames attrSet;
kvPairs = builtins.map (k: "\"${k}\": ${toNestedValue attrSet.${k}}") keys;
in
"{\n " + builtins.concatStringsSep ",\n " kvPairs + "\n}";
in in
{ {
options.programs.hyprpanel = { options.programs.hyprpanel = {
@@ -83,17 +76,10 @@ in
systemd.enable = mkEnableOption "systemd integration"; systemd.enable = mkEnableOption "systemd integration";
hyprland.enable = mkEnableOption "Hyprland integration"; hyprland.enable = mkEnableOption "Hyprland integration";
overwrite.enable = mkEnableOption "overwrite config fix"; overwrite.enable = mkEnableOption "overwrite config fix";
theme = mkOption {
type = types.str;
default = "";
example = "catppuccin_mocha";
description = "Theme to import (see ../themes/*.json)";
};
override = mkOption { override = mkOption {
type = types.attrs; type = types.attrs;
default = {}; default = { };
example = '' example = ''
{ {
theme.bar.menus.text = "#123ABC"; theme.bar.menus.text = "#123ABC";
@@ -105,34 +91,33 @@ in
''; '';
}; };
layout = mkOption { settings = {
type = jsonFormat.type; layout = mkOption {
default = null; type = jsonFormat.type;
example = '' default = null;
{ example = ''
"bar.layouts" = { {
"0" = { "bar.layouts" = {
left = [ "dashboard" "workspaces" "windowtitle" ]; "0" = {
middle = [ "media" ]; left = [ "dashboard" "workspaces" "windowtitle" ];
right = [ "volume" "network" "bluetooth" "battery" "systray" "clock" "notifications" ]; middle = [ "media" ];
}; right = [ "volume" "network" "bluetooth" "battery" "systray" "clock" "notifications" ];
"1" = { };
left = [ "dashboard" "workspaces" "windowtitle" ]; "1" = {
middle = [ "media" ]; left = [ "dashboard" "workspaces" "windowtitle" ];
right = [ "volume" "clock" "notifications" ]; middle = [ "media" ];
}; right = [ "volume" "clock" "notifications" ];
"2" = { };
left = [ "dashboard" "workspaces" "windowtitle" ]; "2" = {
middle = [ "media" ]; left = [ "dashboard" "workspaces" "windowtitle" ];
right = [ "volume" "clock" "notifications" ]; middle = [ "media" ];
right = [ "volume" "clock" "notifications" ];
};
}; };
}; };
}; '';
''; description = "https://hyprpanel.com/configuration/panel.html";
description = "https://hyprpanel.com/configuration/panel.html"; };
};
settings = {
bar.autoHide = mkStrOption "never"; bar.autoHide = mkStrOption "never";
bar.battery.hideLabelWhenFull = mkBoolOption false; bar.battery.hideLabelWhenFull = mkBoolOption false;
bar.battery.label = mkBoolOption true; bar.battery.label = mkBoolOption true;
@@ -156,7 +141,16 @@ in
bar.customModules.cava.showIcon = mkBoolOption true; bar.customModules.cava.showIcon = mkBoolOption true;
bar.customModules.cava.icon = mkStrOption ""; bar.customModules.cava.icon = mkStrOption "";
bar.customModules.cava.spaceCharacter = mkStrOption ""; bar.customModules.cava.spaceCharacter = mkStrOption "";
bar.customModules.cava.barCharacters = mkStrListOption [ "" "" "" "" "" "" "" "" ]; bar.customModules.cava.barCharacters = mkStrListOption [
""
""
""
""
""
""
""
""
];
bar.customModules.cava.showActiveOnly = mkBoolOption false; bar.customModules.cava.showActiveOnly = mkBoolOption false;
bar.customModules.cava.bars = mkIntOption 10; bar.customModules.cava.bars = mkIntOption 10;
bar.customModules.cava.channels = mkIntOption 2; bar.customModules.cava.channels = mkIntOption 2;
@@ -362,6 +356,19 @@ in
bar.workspaces.spacing = mkFloatOption 1.0; bar.workspaces.spacing = mkFloatOption 1.0;
bar.workspaces.workspaceMask = mkBoolOption false; bar.workspaces.workspaceMask = mkBoolOption false;
bar.workspaces.workspaces = mkIntOption 5; bar.workspaces.workspaces = mkIntOption 5;
bar.workspaces.workspaceIconMap = mkOption {
type = jsonFormat.type;
default = null;
example = ''
"1": "<U+EEFE>",
"2": "<U+F269>",
"3": "<U+EAC4>",
"4": "<U+EC1B>",
"5": "<U+F02B4>",
"6": "<U+F1FF> ",
"7": "<U+EB1C>"
'';
};
dummy = mkBoolOption true; dummy = mkBoolOption true;
hyprpanel.restartAgs = mkBoolOption true; hyprpanel.restartAgs = mkBoolOption true;
# hyprpanel.restartCommand = mkStrOption "${pkgs.procps}/bin/pkill -u $USER -USR1 hyprpanel; ${package}/bin/hyprpanel"; # hyprpanel.restartCommand = mkStrOption "${pkgs.procps}/bin/pkill -u $USER -USR1 hyprpanel; ${package}/bin/hyprpanel";
@@ -375,15 +382,20 @@ in
menus.clock.weather.unit = mkStrOption "imperial"; menus.clock.weather.unit = mkStrOption "imperial";
menus.dashboard.controls.enabled = mkBoolOption true; menus.dashboard.controls.enabled = mkBoolOption true;
menus.dashboard.directories.enabled = mkBoolOption true; menus.dashboard.directories.enabled = mkBoolOption true;
menus.dashboard.directories.left.directory1.command = mkStrOption "bash -c \"xdg-open $HOME/Downloads/\""; menus.dashboard.directories.left.directory1.command =
mkStrOption "bash -c \"xdg-open $HOME/Downloads/\"";
menus.dashboard.directories.left.directory1.label = mkStrOption "󰉍 Downloads"; menus.dashboard.directories.left.directory1.label = mkStrOption "󰉍 Downloads";
menus.dashboard.directories.left.directory2.command = mkStrOption "bash -c \"xdg-open $HOME/Videos/\""; menus.dashboard.directories.left.directory2.command =
mkStrOption "bash -c \"xdg-open $HOME/Videos/\"";
menus.dashboard.directories.left.directory2.label = mkStrOption "󰉏 Videos"; menus.dashboard.directories.left.directory2.label = mkStrOption "󰉏 Videos";
menus.dashboard.directories.left.directory3.command = mkStrOption "bash -c \"xdg-open $HOME/Projects/\""; menus.dashboard.directories.left.directory3.command =
mkStrOption "bash -c \"xdg-open $HOME/Projects/\"";
menus.dashboard.directories.left.directory3.label = mkStrOption "󰚝 Projects"; menus.dashboard.directories.left.directory3.label = mkStrOption "󰚝 Projects";
menus.dashboard.directories.right.directory1.command = mkStrOption "bash -c \"xdg-open $HOME/Documents/\""; menus.dashboard.directories.right.directory1.command =
mkStrOption "bash -c \"xdg-open $HOME/Documents/\"";
menus.dashboard.directories.right.directory1.label = mkStrOption "󱧶 Documents"; menus.dashboard.directories.right.directory1.label = mkStrOption "󱧶 Documents";
menus.dashboard.directories.right.directory2.command = mkStrOption "bash -c \"xdg-open $HOME/Pictures/\""; menus.dashboard.directories.right.directory2.command =
mkStrOption "bash -c \"xdg-open $HOME/Pictures/\"";
menus.dashboard.directories.right.directory2.label = mkStrOption "󰉏 Pictures"; menus.dashboard.directories.right.directory2.label = mkStrOption "󰉏 Pictures";
menus.dashboard.directories.right.directory3.command = mkStrOption "bash -c \"xdg-open $HOME/\""; menus.dashboard.directories.right.directory3.command = mkStrOption "bash -c \"xdg-open $HOME/\"";
menus.dashboard.directories.right.directory3.label = mkStrOption "󱂵 Home"; menus.dashboard.directories.right.directory3.label = mkStrOption "󱂵 Home";
@@ -410,7 +422,8 @@ in
menus.dashboard.shortcuts.right.shortcut1.command = mkStrOption "sleep 0.5 && hyprpicker -a"; menus.dashboard.shortcuts.right.shortcut1.command = mkStrOption "sleep 0.5 && hyprpicker -a";
menus.dashboard.shortcuts.right.shortcut1.icon = mkStrOption ""; menus.dashboard.shortcuts.right.shortcut1.icon = mkStrOption "";
menus.dashboard.shortcuts.right.shortcut1.tooltip = mkStrOption "Color Picker"; menus.dashboard.shortcuts.right.shortcut1.tooltip = mkStrOption "Color Picker";
menus.dashboard.shortcuts.right.shortcut3.command = mkStrOption "bash -c \"${../scripts/snapshot.sh}\""; menus.dashboard.shortcuts.right.shortcut3.command =
mkStrOption "bash -c \"${../scripts/snapshot.sh}\"";
menus.dashboard.shortcuts.right.shortcut3.icon = mkStrOption "󰄀"; menus.dashboard.shortcuts.right.shortcut3.icon = mkStrOption "󰄀";
menus.dashboard.shortcuts.right.shortcut3.tooltip = mkStrOption "Screenshot"; menus.dashboard.shortcuts.right.shortcut3.tooltip = mkStrOption "Screenshot";
menus.dashboard.stats.enable_gpu = mkBoolOption false; menus.dashboard.stats.enable_gpu = mkBoolOption false;
@@ -441,7 +454,7 @@ in
notifications.monitor = mkIntOption 0; notifications.monitor = mkIntOption 0;
notifications.position = mkStrOption "top right"; notifications.position = mkStrOption "top right";
notifications.showActionsOnHover = mkBoolOption false; notifications.showActionsOnHover = mkBoolOption false;
notifications.ignore = mkStrListOption []; notifications.ignore = mkStrListOption [ ];
notifications.timeout = mkIntOption 7000; notifications.timeout = mkIntOption 7000;
scalingPriority = mkStrOption "gdk"; scalingPriority = mkStrOption "gdk";
tear = mkBoolOption false; tear = mkBoolOption false;
@@ -579,6 +592,12 @@ in
theme.matugen_settings.mode = mkStrOption "dark"; theme.matugen_settings.mode = mkStrOption "dark";
theme.matugen_settings.scheme_type = mkStrOption "tonal-spot"; theme.matugen_settings.scheme_type = mkStrOption "tonal-spot";
theme.matugen_settings.variation = mkStrOption "standard_1"; theme.matugen_settings.variation = mkStrOption "standard_1";
theme.name = mkOption {
type = types.str;
default = "";
example = "catppuccin_mocha";
description = "Theme to import (see ../themes/*.json)";
};
theme.notification.border_radius = mkStrOption "0.6em"; theme.notification.border_radius = mkStrOption "0.6em";
theme.notification.enableShadow = mkBoolOption false; theme.notification.enableShadow = mkBoolOption false;
theme.notification.opacity = mkIntOption 100; theme.notification.opacity = mkIntOption 100;
@@ -606,90 +625,98 @@ in
}; };
}; };
config = let config =
let
theme = theme =
if cfg.theme != "" if cfg.settings.theme.name != "" then
then builtins.fromJSON (builtins.readFile ../themes/${cfg.theme}.json) builtins.fromJSON (builtins.readFile ../themes/${cfg.settings.theme.name}.json)
else {}; else
{ };
flatSet = flattenAttrs (lib.attrsets.recursiveUpdate cfg.settings theme) ""; flatSet = lib.attrsets.recursiveUpdate cfg.settings theme;
mergeSet = flatSet // (flattenAttrs cfg.override ""); mergeSet = flatSet // cfg.override;
fullSet = if cfg.layout == null then mergeSet else mergeSet // cfg.layout; fullSet = if cfg.settings.layout == null then mergeSet else mergeSet // cfg.settings.layout;
finalConfig = toNestedObject fullSet; finalConfig = builtins.toJSON fullSet;
hyprpanel-diff = pkgs.writeShellApplication { hyprpanel-diff = pkgs.writeShellApplication {
runtimeInputs = [ pkgs.colordiff ]; runtimeInputs = [ pkgs.colordiff ];
name = "hyprpanel-diff"; name = "hyprpanel-diff";
text = '' text = ''
cd cd
echo '------------- HyprPanel -------------' echo '------------- HyprPanel -------------'
echo 'Please ignore the layout diff for now' echo 'Please ignore the layout diff for now'
echo '-------------------------------------' echo '-------------------------------------'
colordiff ${config.xdg.configFile.hyprpanel.target} \ colordiff ${config.xdg.configFile.hyprpanel.target} \
${config.xdg.configFile.hyprpanel-swap.target} ${config.xdg.configFile.hyprpanel-swap.target}
''; '';
}; };
in mkIf cfg.enable { in
mkIf cfg.enable {
# nixpkgs.overlays = if cfg.overlay.enable then [ self.overlay ] else null; # nixpkgs.overlays = if cfg.overlay.enable then [ self.overlay ] else null;
nixpkgs.overlays = lib.mkIf cfg.overlay.enable [ self.overlay ]; nixpkgs.overlays = lib.mkIf cfg.overlay.enable [ self.overlay ];
home.packages = [ home.packages = [
package package
hyprpanel-diff hyprpanel-diff
(if pkgs ? nerd-fonts.jetbrains-mono (
then pkgs.nerd-fonts.jetbrains-mono if pkgs ? nerd-fonts.jetbrains-mono then
# NOTE:(benvonh) Remove after next release 25.05 pkgs.nerd-fonts.jetbrains-mono
else pkgs.nerdfonts.override { fonts = [ "JetBrainsMono" ]; }) # NOTE:(benvonh) Remove after next release 25.05
]; else
pkgs.nerdfonts.override { fonts = [ "JetBrainsMono" ]; }
)
];
home.activation = home.activation =
let let
path = "${config.xdg.configFile.hyprpanel.target}"; path = "${config.xdg.configFile.hyprpanel.target}";
in in
mkIf cfg.overwrite.enable { mkIf cfg.overwrite.enable {
hyprpanel = lib.hm.dag.entryBefore [ "writeBoundary" ] '' hyprpanel = lib.hm.dag.entryBefore [ "writeBoundary" ] ''
[[ -L "${path}" ]] || rm -f "${path}" [[ -L "${path}" ]] || rm -f "${path}"
''; '';
}; };
xdg.configFile.hyprpanel = mkIf cfg.config.enable { xdg.configFile.hyprpanel = mkIf cfg.config.enable {
target = "hyprpanel/config.json"; target = "hyprpanel/config.json";
text = finalConfig; text = finalConfig;
# onChange = "${pkgs.procps}/bin/pkill -u $USER -USR1 hyprpanel || true"; # onChange = "${pkgs.procps}/bin/pkill -u $USER -USR1 hyprpanel || true";
onChange = "${package}/bin/hyprpanel r"; onChange = "${package}/bin/hyprpanel r";
};
xdg.configFile.hyprpanel-swap = mkIf cfg.config.enable {
target = "hyprpanel/config.hm.json";
text = finalConfig;
};
# NOTE: Deprecated
# systemd.user.services = mkIf cfg.systemd.enable {
# hyprpanel = {
# Unit = {
# Description = "A Bar/Panel for Hyprland with extensive customizability.";
# Documentation = "https://hyprpanel.com";
# PartOf = [ "graphical-session.target" ];
# After = [ "graphical-session-pre.target" ];
# };
# Service = {
# ExecStart = "${package}/bin/hyprpanel";
# ExecReload = "${pkgs.coreutils}/bin/kill -SIGUSR1 $MAINPID";
# Restart = "on-failure";
# KillMode = "mixed";
# };
# Install = { WantedBy = [ "graphical-session.target" ]; };
# };
# };
warnings = if cfg.systemd.enable then [ "The `systemd.enable` option is now obsolete." ] else [ ];
wayland.windowManager.hyprland.settings.exec-once = mkIf cfg.hyprland.enable [
"${package}/bin/hyprpanel"
];
}; };
xdg.configFile.hyprpanel-swap = mkIf cfg.config.enable {
target = "hyprpanel/config.hm.json";
text = finalConfig;
};
# NOTE: Deprecated
# systemd.user.services = mkIf cfg.systemd.enable {
# hyprpanel = {
# Unit = {
# Description = "A Bar/Panel for Hyprland with extensive customizability.";
# Documentation = "https://hyprpanel.com";
# PartOf = [ "graphical-session.target" ];
# After = [ "graphical-session-pre.target" ];
# };
# Service = {
# ExecStart = "${package}/bin/hyprpanel";
# ExecReload = "${pkgs.coreutils}/bin/kill -SIGUSR1 $MAINPID";
# Restart = "on-failure";
# KillMode = "mixed";
# };
# Install = { WantedBy = [ "graphical-session.target" ]; };
# };
# };
warnings = if cfg.systemd.enable then [ "The `systemd.enable` option is now obsolete." ] else [];
wayland.windowManager.hyprland.settings.exec-once = mkIf cfg.hyprland.enable [ "${package}/bin/hyprpanel" ];
};
} }