diff --git a/modules/misc/news/2025/05/2025-05-22_18-47-11.nix b/modules/misc/news/2025/05/2025-05-22_18-47-11.nix new file mode 100644 index 000000000..4ffc64ec0 --- /dev/null +++ b/modules/misc/news/2025/05/2025-05-22_18-47-11.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: +{ + time = "2025-05-22T23:47:11+00:00"; + condition = pkgs.stdenv.hostPlatform.isDarwin; + message = '' + A new sketchybar module has been added. + + - Simple configuration with a single `config` option that accepts the + configuration as lines, a file, or a directory. + - Support for both bash and lua configuration types + - `extraLuaPackages` option for additional Lua dependencies + - `extraPackages` option for additional runtime dependencies + - Integrated launchd service management + ''; +} diff --git a/modules/programs/sketchybar.nix b/modules/programs/sketchybar.nix index fb046cfc8..719527012 100644 --- a/modules/programs/sketchybar.nix +++ b/modules/programs/sketchybar.nix @@ -23,6 +23,13 @@ in package = lib.mkPackageOption pkgs "sketchybar" { }; + finalPackage = mkOption { + type = types.package; + readOnly = true; + internal = true; + description = "Resulting customized sketchybar package."; + }; + configType = mkOption { type = types.enum [ "bash" @@ -77,6 +84,38 @@ in ''; }; + sbarLuaPackage = lib.mkPackageOption pkgs "sbarlua" { + nullable = true; + extraDescription = "Required when using a lua configuration."; + }; + + luaPackage = lib.mkPackageOption pkgs "lua5_4" { + nullable = true; + extraDescription = "Lua interpreter to use when configType is lua."; + }; + + extraLuaPackages = mkOption { + type = with types; functionTo (listOf package); + default = _: [ ]; + defaultText = literalExpression "ps: [ ]"; + example = literalExpression "luaPkgs: with luaPkgs; [ luautf8 ]"; + description = '' + The extra Lua packages required for your plugins to work. + This option accepts a function that takes a Lua package set as an argument, + and selects the required Lua packages from this package set. + See the example for more info. + ''; + }; + + extraPackages = mkOption { + type = with lib.types; listOf package; + default = [ ]; + example = literalExpression "[ pkgs.jq ]"; + description = '' + Extra packages to add to PATH for the sketchybar service. + ''; + }; + service = { enable = mkEnableOption "sketchybar service" // { default = true; @@ -97,99 +136,122 @@ in example = "/Users/khaneliman/Library/Logs/sketchybar.log"; description = "Absolute path to log all stdout output."; }; - - sbarLuaPackage = lib.mkPackageOption pkgs "sbarlua" { - nullable = true; - extraDescription = "Required when using a lua configuration."; - }; - - extraLuaPackages = mkOption { - type = with types; functionTo (listOf package); - default = _: [ ]; - defaultText = literalExpression "ps: [ ]"; - example = literalExpression "luaPkgs: with luaPkgs; [ luautf8 ]"; - description = '' - The extra Lua packages required for your plugins to work. - This option accepts a function that takes a Lua package set as an argument, - and selects the required Lua packages from this package set. - See the example for more info. - ''; - }; - - extraPackages = mkOption { - type = with lib.types; listOf package; - default = [ ]; - example = literalExpression "[ pkgs.jq ]"; - description = '' - Extra packages to add to PATH for the sketchybar service. - ''; - }; }; }; - config = lib.mkMerge [ - (lib.mkIf cfg.enable { - assertions = [ - { - assertion = !(cfg.configType == "lua" && cfg.sbarLuaPackage == null); - message = "When configType is set to \"lua\", sbarLuaPackage must be specified"; + config = lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "programs.sketchybar" pkgs lib.platforms.darwin) + { + assertion = !(cfg.configType == "lua" && cfg.sbarLuaPackage == null); + message = "When configType is set to \"lua\", service.sbarLuaPackage must be specified"; + } + ]; + + programs.sketchybar.finalPackage = + let + resolvedExtraLuaPackages = cfg.extraLuaPackages pkgs.lua54Packages; + + pathPackages = + [ cfg.package ] + ++ cfg.extraPackages + ++ lib.optional (cfg.configType == "lua" && cfg.luaPackage != null) cfg.luaPackage; + + luaPaths = lib.filter (x: x != "") [ + (lib.optionalString (cfg.configType == "lua" && resolvedExtraLuaPackages != [ ]) ( + lib.concatMapStringsSep ";" pkgs.lua54Packages.getLuaPath resolvedExtraLuaPackages + )) + (lib.optionalString (cfg.configType == "lua" && cfg.sbarLuaPackage != null) ( + pkgs.lua54Packages.getLuaPath cfg.sbarLuaPackage + )) + (lib.optionalString (cfg.configType == "lua" && cfg.config != null && cfg.config.source != null) ( + let + configDir = "${config.xdg.configHome}/sketchybar"; + in + "${configDir}/?.lua;${configDir}/?/init.lua;${configDir}/?/?.lua" + )) + ]; + + luaCPaths = lib.filter (x: x != "") [ + (lib.optionalString (cfg.configType == "lua" && resolvedExtraLuaPackages != [ ]) ( + lib.concatMapStringsSep ";" pkgs.lua54Packages.getLuaCPath resolvedExtraLuaPackages + )) + (lib.optionalString (cfg.configType == "lua" && cfg.sbarLuaPackage != null) ( + pkgs.lua54Packages.getLuaCPath cfg.sbarLuaPackage + )) + ]; + + makeWrapperArgs = lib.flatten ( + lib.filter (x: x != [ ]) [ + (lib.optional (pathPackages != [ ]) [ + "--prefix" + "PATH" + ":" + "${lib.makeBinPath pathPackages}" + ]) + + (lib.optional (luaPaths != [ ]) [ + "--prefix" + "LUA_PATH" + ";" + "${lib.concatStringsSep ";" luaPaths}" + ]) + + (lib.optional (luaCPaths != [ ]) [ + "--prefix" + "LUA_CPATH" + ";" + "${lib.concatStringsSep ";" luaCPaths}" + ]) + ] + ); + + hasWrapperArgs = makeWrapperArgs != [ ]; + in + if hasWrapperArgs then + pkgs.symlinkJoin { + name = "sketchybar"; + paths = [ cfg.package ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/sketchybar ${lib.escapeShellArgs makeWrapperArgs} + ''; } - ]; + else + cfg.package; - home.packages = [ cfg.package ]; + home.packages = [ cfg.finalPackage ]; - xdg.configFile."sketchybar/sketchybarrc".source = lib.mkIf (cfg.config != "") ( - pkgs.writeTextFile { - name = "sketchybarrc"; - text = - if cfg.configType == "lua" then - '' - #!/usr/bin/env lua - -- Generated by home-manager - ${cfg.config} - '' - else - '' - #!/usr/bin/env bash - # Generated by home-manager - ${cfg.config} - ''; - executable = true; - } - ); - }) + xdg.configFile."sketchybar/sketchybarrc".source = lib.mkIf (cfg.config != "") ( + pkgs.writeTextFile { + name = "sketchybarrc"; + text = + if cfg.configType == "lua" then + '' + #!/usr/bin/env lua + -- Generated by home-manager + ${cfg.config} + '' + else + '' + #!/usr/bin/env bash + # Generated by home-manager + ${cfg.config} + ''; + executable = true; + } + ); - (lib.mkIf cfg.service.enable { - assertions = [ - (lib.hm.assertions.assertPlatform "programs.sketchybar" pkgs lib.platforms.darwin) - ]; - - launchd.agents.sketchybar = - let - resolvedExtraLuaPackages = cfg.service.extraLuaPackages pkgs.lua54Packages; - in - { - enable = true; - config = { - Program = lib.getExe cfg.package; - ProcessType = "Interactive"; - KeepAlive = true; - RunAtLoad = true; - StandardErrorPath = cfg.service.errorLogFile; - StandardOutPath = cfg.service.outLogFile; - EnvironmentVariables = - { - PATH = (lib.concatMapStringsSep ":" (p: "${p}/bin") ([ cfg.package ] ++ cfg.service.extraPackages)); - } - // lib.optionalAttrs - (cfg.configType == "lua" && (cfg.sbarLuaPackage != null || cfg.extraLuaPackages != (_: [ ]))) - { - LUA_CPATH = "${ - lib.concatMapStringsSep ";" pkgs.lua54Packages.getLuaCPath resolvedExtraLuaPackages - };${cfg.sbarLuaPackage}/lib/lua/${pkgs.lua.luaversion}/?.so"; - }; - }; - }; - }) - ]; + launchd.agents.sketchybar = { + enable = cfg.service.enable; + config = { + Program = lib.getExe cfg.finalPackage; + ProcessType = "Interactive"; + KeepAlive = true; + RunAtLoad = true; + StandardErrorPath = cfg.service.errorLogFile; + StandardOutPath = cfg.service.outLogFile; + }; + }; + }; } diff --git a/tests/modules/programs/sketchybar/default.nix b/tests/modules/programs/sketchybar/default.nix index b158ac10c..0b77ac430 100644 --- a/tests/modules/programs/sketchybar/default.nix +++ b/tests/modules/programs/sketchybar/default.nix @@ -1,5 +1,4 @@ { - # Combined tests with built-in validation sketchybar = ./sketchybar.nix; # Bash configuration with validation sketchybar-lua-config = ./sketchybar-lua-config.nix; # Lua configuration with validation sketchybar-invalid-lua-config = ./sketchybar-invalid-lua-config.nix; # Tests error on missing sbarLua diff --git a/tests/modules/programs/sketchybar/sketchybar-invalid-lua-config.nix b/tests/modules/programs/sketchybar/sketchybar-invalid-lua-config.nix index dadc55c6b..4e0b55675 100644 --- a/tests/modules/programs/sketchybar/sketchybar-invalid-lua-config.nix +++ b/tests/modules/programs/sketchybar/sketchybar-invalid-lua-config.nix @@ -2,22 +2,27 @@ { programs.sketchybar = { enable = true; - package = config.lib.test.mkStubPackage { }; + package = config.lib.test.mkStubPackage { + name = "sketchybar"; + buildScript = '' + mkdir -p $out/bin + touch $out/bin/sketchybar + chmod 755 $out/bin/sketchybar + ''; + }; # Test case for lua configuration without sbarLuaPackage configType = "lua"; - # sbarLuaPackage intentionally not set + sbarLuaPackage = null; - variables = { - PADDING = 3; - }; - - config.bar = { - height = 30; - }; + config = '' + -- Basic lua config + local sbar = require("sbarlua") + sbar.bar:set({ height = 30 }) + ''; }; test.asserts.assertions.expected = [ - "When configType is set to \"lua\", sbarLuaPackage must be specified" + "When configType is set to \"lua\", service.sbarLuaPackage must be specified" ]; } diff --git a/tests/modules/programs/sketchybar/sketchybar-lua-config.nix b/tests/modules/programs/sketchybar/sketchybar-lua-config.nix index e96bc32a9..80db975d3 100644 --- a/tests/modules/programs/sketchybar/sketchybar-lua-config.nix +++ b/tests/modules/programs/sketchybar/sketchybar-lua-config.nix @@ -14,58 +14,54 @@ in { programs.sketchybar = { enable = true; - package = config.lib.test.mkStubPackage { }; + package = config.lib.test.mkStubPackage { + name = "sketchybar"; + buildScript = '' + mkdir -p $out/bin + touch $out/bin/sketchybar + chmod 755 $out/bin/sketchybar + ''; + }; configType = "lua"; + sbarLuaPackage = pkgsSbarlua; - variables = { - PADDING = 3; - FONT = "SF Pro"; - COLOR = "0xff0000ff"; - # Test more complex values - ITEMS = [ - "calendar" - "cpu" - "memory" - ]; - SETTINGS = { - refresh_freq = 1; - enable_logging = true; - }; - }; - - config = { - bar = { - height = 30; - position = "top"; - padding_left = 10; - padding_right = 10; - blur_radius = 20; - corner_radius = 9; - }; - - defaults = { - "icon.font" = "$FONT"; - "icon.color" = "$COLOR"; - "background.height" = 24; - "label.padding" = "$PADDING"; - "popup.background.border_width" = 2; - "popup.background.corner_radius" = 9; - }; - }; - - extraConfig = '' + config = '' -- This is a test Lua configuration + local sbar = require("sbarlua") + + -- Configure bar + sbar.bar:set({ + height = 30, + position = "top", + padding_left = 10, + padding_right = 10, + blur_radius = 20, + corner_radius = 9, + }) + + -- Configure defaults + sbar.defaults:set({ + ["icon.font"] = "SF Pro", + ["icon.color"] = "0xff0000ff", + ["background.height"] = 24, + ["popup.background.border_width"] = 2, + ["popup.background.corner_radius"] = 9, + }) + + -- Add items sbar:add("item", "cpu", { position = "right", update_freq = 1, - script = "./scripts/cpu.lua" + script = "./scripts/cpu.lua", }) -- Subscribe to events sbar:subscribe("cpu", "system_woke") - ''; + + -- Update the bar + sbar:update()''; }; # Validate the generated Lua configuration file diff --git a/tests/modules/programs/sketchybar/sketchybar-service-expected.plist b/tests/modules/programs/sketchybar/sketchybar-service-expected.plist index a01c60434..d29337e75 100644 --- a/tests/modules/programs/sketchybar/sketchybar-service-expected.plist +++ b/tests/modules/programs/sketchybar/sketchybar-service-expected.plist @@ -2,11 +2,6 @@ - EnvironmentVariables - - PATH - /@sketchybar@/bin:/@jq@/bin - KeepAlive Label diff --git a/tests/modules/programs/sketchybar/sketchybar-service-integration.nix b/tests/modules/programs/sketchybar/sketchybar-service-integration.nix index 2fecd69ba..c4de01c76 100644 --- a/tests/modules/programs/sketchybar/sketchybar-service-integration.nix +++ b/tests/modules/programs/sketchybar/sketchybar-service-integration.nix @@ -9,7 +9,11 @@ let self: super: { sketchybar = config.lib.test.mkStubPackage { name = "sketchybar"; - outPath = "/@sketchybar@"; + buildScript = '' + mkdir -p $out/bin + touch $out/bin/sketchybar + chmod 755 $out/bin/sketchybar + ''; }; jq = config.lib.test.mkStubPackage { outPath = "/@jq@"; }; } @@ -21,23 +25,22 @@ in package = hmPkgs.sketchybar; configType = "bash"; - variables = { - PADDING = "3"; - FONT = "SF Pro"; - COLOR = "0xff0000ff"; - }; + config = '' + #!/usr/bin/env bash - config.bar = { - height = 30; - position = "top"; - padding_left = 10; - padding_right = 10; - }; + # Configure bar + sketchybar --bar height=30 \ + position=top \ + padding_left=10 \ + padding_right=10 + + # Update the bar + sketchybar --update + ''; # Enable the integrated service service = { enable = true; - extraPackages = [ hmPkgs.jq ]; errorLogFile = "/home/hm-user/Library/Logs/sketchybar/sketchybar.err.log"; outLogFile = "/home/hm-user/Library/Logs/sketchybar/sketchybar.out.log"; }; diff --git a/tests/modules/programs/sketchybar/sketchybar.nix b/tests/modules/programs/sketchybar/sketchybar.nix index e67d0f307..ede133a2b 100644 --- a/tests/modules/programs/sketchybar/sketchybar.nix +++ b/tests/modules/programs/sketchybar/sketchybar.nix @@ -3,45 +3,42 @@ { programs.sketchybar = { enable = true; - package = config.lib.test.mkStubPackage { }; + package = config.lib.test.mkStubPackage { + name = "sketchybar"; + buildScript = '' + mkdir -p $out/bin + touch $out/bin/sketchybar + chmod 755 $out/bin/sketchybar + ''; + }; configType = "bash"; - variables = { - PADDING = "3"; - FONT = "SF Pro"; - COLOR = "0xff0000ff"; - }; + config = '' + # Define colors + export COLOR_BLACK="0xff181926" + export COLOR_WHITE="0xffcad3f5" - config = { - bar = { - height = 30; - position = "top"; - padding_left = 10; - padding_right = 10; - }; + # Configure bar + sketchybar --bar height=32 \ + position=top \ + padding_left=10 \ + padding_right=10 \ + color=$COLOR_BLACK - defaults = { - "icon.font" = "$FONT"; - "icon.color" = "$COLOR"; - "background.height" = 24; - }; - }; + # Configure default values + sketchybar --default icon.font="SF Pro:Bold:14.0" \ + icon.color=$COLOR_WHITE \ + label.font="SF Pro:Bold:14.0" \ + label.color=$COLOR_WHITE - plugins = [ - { - name = "clock"; - placement = "right"; - script = "./scripts/clock.sh"; - update_freq = 1; - } - ]; + # Add items to the bar + sketchybar --add item clock right \ + --set clock script="date '+%H:%M'" \ + update_freq=10 - extraConfig = '' - # This is a test configuration - sketchybar --add item cpu right \ - --set cpu script="$PLUGIN_DIR/cpu.sh" \ - --subscribe cpu system_woke + # Update the bar + sketchybar --update ''; }; diff --git a/tests/modules/programs/sketchybar/sketchybarrc.bash b/tests/modules/programs/sketchybar/sketchybarrc.bash index 8cc3b48f0..5a9f511be 100644 --- a/tests/modules/programs/sketchybar/sketchybarrc.bash +++ b/tests/modules/programs/sketchybar/sketchybarrc.bash @@ -1,26 +1,27 @@ -export COLOR=0xff0000ff -export FONT=SF Pro -export PADDING=3 +#!/usr/bin/env bash +# Generated by home-manager +# Define colors +export COLOR_BLACK="0xff181926" +export COLOR_WHITE="0xffcad3f5" -sketchybar --bar \ -height=30 \ -padding_left=10 \ -padding_right=10 \ -position=top +# Configure bar +sketchybar --bar height=32 \ + position=top \ + padding_left=10 \ + padding_right=10 \ + color=$COLOR_BLACK -sketchybar --default \ -background.height=24 \ -icon.color=$COLOR \ -icon.font=$FONT +# Configure default values +sketchybar --default icon.font="SF Pro:Bold:14.0" \ + icon.color=$COLOR_WHITE \ + label.font="SF Pro:Bold:14.0" \ + label.color=$COLOR_WHITE +# Add items to the bar +sketchybar --add item clock right \ + --set clock script="date '+%H:%M'" \ + update_freq=10 -sketchybar --add item clock right --set clock script=./scripts/clock.sh update_freq=1 +# Update the bar +sketchybar --update - -# This is a test configuration -sketchybar --add item cpu right \ - --set cpu script="$PLUGIN_DIR/cpu.sh" \ - --subscribe cpu system_woke - - -sketchybar --update \ No newline at end of file diff --git a/tests/modules/programs/sketchybar/sketchybarrc.lua b/tests/modules/programs/sketchybar/sketchybarrc.lua index 77c363417..5efc05fe5 100644 --- a/tests/modules/programs/sketchybar/sketchybarrc.lua +++ b/tests/modules/programs/sketchybar/sketchybarrc.lua @@ -1,52 +1,36 @@ #!/usr/bin/env lua -- Generated by home-manager +-- This is a test Lua configuration local sbar = require("sbarlua") --- Set variables -sbar.variables["COLOR"] = "0xff0000ff" -sbar.variables["FONT"] = "SF Pro" -sbar.variables["ITEMS"] = { - "calendar", - "cpu", - "memory" -} -sbar.variables["PADDING"] = 3 -sbar.variables["SETTINGS"] = { - ["enable_logging"] = true, - ["refresh_freq"] = 1 -} - -- Configure bar sbar.bar:set({ - ["blur_radius"] = 20, - ["corner_radius"] = 9, - ["height"] = 30, - ["padding_left"] = 10, - ["padding_right"] = 10, - ["position"] = "top" + height = 30, + position = "top", + padding_left = 10, + padding_right = 10, + blur_radius = 20, + corner_radius = 9, }) -- Configure defaults sbar.defaults:set({ + ["icon.font"] = "SF Pro", + ["icon.color"] = "0xff0000ff", ["background.height"] = 24, - ["icon.color"] = "$COLOR", - ["icon.font"] = "$FONT", - ["label.padding"] = "$PADDING", ["popup.background.border_width"] = 2, - ["popup.background.corner_radius"] = 9 + ["popup.background.corner_radius"] = 9, }) --- Extra configuration --- This is a test Lua configuration +-- Add items sbar:add("item", "cpu", { position = "right", update_freq = 1, - script = "./scripts/cpu.lua" + script = "./scripts/cpu.lua", }) -- Subscribe to events sbar:subscribe("cpu", "system_woke") - -- Update the bar sbar:update()