sketchybar: add module

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
This commit is contained in:
Austin Horstman 2024-02-11 23:11:53 -06:00
parent c3d48a17aa
commit 5dc3bc3368
11 changed files with 519 additions and 0 deletions

View file

@ -268,6 +268,7 @@ let
./programs/sesh.nix
./programs/sftpman.nix
./programs/sioyek.nix
./programs/sketchybar.nix
./programs/skim.nix
./programs/sm64ex.nix
./programs/smug.nix

View file

@ -0,0 +1,195 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
literalExpression
mkEnableOption
mkOption
types
;
cfg = config.programs.sketchybar;
in
{
meta.maintainers = [ lib.maintainers.khaneliman ];
options.programs.sketchybar = {
enable = mkEnableOption "sketchybar";
package = lib.mkPackageOption pkgs "sketchybar" { };
configType = mkOption {
type = types.enum [
"bash"
"lua"
];
default = "bash";
description = ''
The type of configuration to generate.
Set to "bash" to use the standard bash configuration.
Set to "lua" to use the Lua configuration via SbarLua.
'';
};
config = mkOption {
type = with types; nullOr (either lines path);
default = "";
example = literalExpression ''
# Bash example
#!/usr/bin/env bash
# Define colors
export COLOR_BLACK="0xff181926"
export COLOR_WHITE="0xffcad3f5"
# Configure bar
sketchybar --bar height=32 \
position=top \
padding_left=10 \
padding_right=10 \
color=$COLOR_BLACK
# 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
# Update the bar
sketchybar --update
'';
description = ''
The complete sketchybar configuration content.
This should be written in the language specified by configType (bash or lua).
The appropriate shebang will be automatically added.
'';
};
service = {
enable = mkEnableOption "sketchybar service" // {
default = true;
};
errorLogFile = mkOption {
type = with lib.types; nullOr (either path str);
default = "${config.home.homeDirectory}/Library/Logs/sketchybar/sketchybar.err.log";
defaultText = lib.literalExpression "\${config.home.homeDirectory}/Library/Logs/sketchybar/sketchybar.err.log";
example = "/Users/khaneliman/Library/Logs/sketchybar.log";
description = "Absolute path to log all stderr output.";
};
outLogFile = mkOption {
type = with lib.types; nullOr (either path str);
default = "${config.home.homeDirectory}/Library/Logs/sketchybar/sketchybar.out.log";
defaultText = lib.literalExpression "\${config.home.homeDirectory}/Library/Logs/sketchybar/sketchybar.out.log";
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";
}
];
home.packages = [ cfg.package ];
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";
};
};
};
})
];
}

View file

@ -334,6 +334,7 @@ import nmtSrc {
./modules/launchd
./modules/programs/aerospace
./modules/programs/element-desktop/darwin.nix
./modules/programs/sketchybar
./modules/services/borgmatic-darwin
./modules/services/emacs-darwin
./modules/services/espanso-darwin

View file

@ -0,0 +1,7 @@
{
# 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
sketchybar-service-integration = ./sketchybar-service-integration.nix; # Service integration with validation
}

View file

@ -0,0 +1,23 @@
{ config, ... }:
{
programs.sketchybar = {
enable = true;
package = config.lib.test.mkStubPackage { };
# Test case for lua configuration without sbarLuaPackage
configType = "lua";
# sbarLuaPackage intentionally not set
variables = {
PADDING = 3;
};
config.bar = {
height = 30;
};
};
test.asserts.assertions.expected = [
"When configType is set to \"lua\", sbarLuaPackage must be specified"
];
}

View file

@ -0,0 +1,77 @@
{ config, pkgs, ... }:
let
pkgsSbarlua = pkgs.writeTextFile {
name = "sbarlua";
destination = "/bin/sbarlua";
executable = true;
text = ''
#!/bin/sh
echo "SbarLua mock"
'';
};
in
{
programs.sketchybar = {
enable = true;
package = config.lib.test.mkStubPackage { };
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 = ''
-- This is a test Lua configuration
sbar:add("item", "cpu", {
position = "right",
update_freq = 1,
script = "./scripts/cpu.lua"
})
-- Subscribe to events
sbar:subscribe("cpu", "system_woke")
'';
};
# Validate the generated Lua configuration file
nmt.script = ''
assertFileContent \
home-files/.config/sketchybar/sketchybarrc \
${./sketchybarrc.lua}
'';
}

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/@sketchybar@/bin:/@jq@/bin</string>
</dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>org.nix-community.home.sketchybar</string>
<key>ProcessType</key>
<string>Interactive</string>
<key>Program</key>
<string>/@sketchybar@/bin/sketchybar</string>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/home/hm-user/Library/Logs/sketchybar/sketchybar.err.log</string>
<key>StandardOutPath</key>
<string>/home/hm-user/Library/Logs/sketchybar/sketchybar.out.log</string>
</dict>
</plist>

View file

@ -0,0 +1,59 @@
{
config,
pkgs,
...
}:
let
hmPkgs = pkgs.extend (
self: super: {
sketchybar = config.lib.test.mkStubPackage {
name = "sketchybar";
outPath = "/@sketchybar@";
};
jq = config.lib.test.mkStubPackage { outPath = "/@jq@"; };
}
);
in
{
programs.sketchybar = {
enable = true;
package = hmPkgs.sketchybar;
configType = "bash";
variables = {
PADDING = "3";
FONT = "SF Pro";
COLOR = "0xff0000ff";
};
config.bar = {
height = 30;
position = "top";
padding_left = 10;
padding_right = 10;
};
# 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";
};
};
# Change home directory for the test
home.homeDirectory = "/home/hm-user";
# Validate the generated config files
nmt.script = ''
# Verify config file exists
assertFileExists home-files/.config/sketchybar/sketchybarrc
# Verify service file exists and matches expected content
serviceFile=LaunchAgents/org.nix-community.home.sketchybar.plist
assertFileExists "$serviceFile"
assertFileContent "$serviceFile" ${./sketchybar-service-expected.plist}
'';
}

View file

@ -0,0 +1,53 @@
{ config, ... }:
{
programs.sketchybar = {
enable = true;
package = config.lib.test.mkStubPackage { };
configType = "bash";
variables = {
PADDING = "3";
FONT = "SF Pro";
COLOR = "0xff0000ff";
};
config = {
bar = {
height = 30;
position = "top";
padding_left = 10;
padding_right = 10;
};
defaults = {
"icon.font" = "$FONT";
"icon.color" = "$COLOR";
"background.height" = 24;
};
};
plugins = [
{
name = "clock";
placement = "right";
script = "./scripts/clock.sh";
update_freq = 1;
}
];
extraConfig = ''
# This is a test configuration
sketchybar --add item cpu right \
--set cpu script="$PLUGIN_DIR/cpu.sh" \
--subscribe cpu system_woke
'';
};
nmt.script = ''
assertFileContent \
home-files/.config/sketchybar/sketchybarrc \
${./sketchybarrc.bash}
'';
}

View file

@ -0,0 +1,26 @@
export COLOR=0xff0000ff
export FONT=SF Pro
export PADDING=3
sketchybar --bar \
height=30 \
padding_left=10 \
padding_right=10 \
position=top
sketchybar --default \
background.height=24 \
icon.color=$COLOR \
icon.font=$FONT
sketchybar --add item clock right --set clock script=./scripts/clock.sh update_freq=1
# This is a test configuration
sketchybar --add item cpu right \
--set cpu script="$PLUGIN_DIR/cpu.sh" \
--subscribe cpu system_woke
sketchybar --update

View file

@ -0,0 +1,52 @@
#!/usr/bin/env lua
-- Generated by home-manager
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"
})
-- Configure defaults
sbar.defaults:set({
["background.height"] = 24,
["icon.color"] = "$COLOR",
["icon.font"] = "$FONT",
["label.padding"] = "$PADDING",
["popup.background.border_width"] = 2,
["popup.background.corner_radius"] = 9
})
-- Extra configuration
-- This is a test Lua configuration
sbar:add("item", "cpu", {
position = "right",
update_freq = 1,
script = "./scripts/cpu.lua"
})
-- Subscribe to events
sbar:subscribe("cpu", "system_woke")
-- Update the bar
sbar:update()