* 25.11: Simplify aerospace launchd config and remove menu bar hiding Remove mbedtls_2 workaround for dolphin packages Re-enable packages after NixOS 25.11 upgrade Add --unsupported-gpu flag to Sway for zix790prors compatibility Fix deprecated package names for NixOS 25.11 Upgrade NixOS to 25.11 and fix Jovian module organization
737 lines
26 KiB
Nix
737 lines
26 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.home.roles.aerospace;
|
|
in
|
|
{
|
|
options.home.roles.aerospace = {
|
|
enable = mkEnableOption "AeroSpace tiling window manager for macOS";
|
|
|
|
leader = mkOption {
|
|
type = types.str;
|
|
default = "cmd";
|
|
description = "Leader key for aerospace shortcuts (e.g., 'cmd', 'ctrl', 'alt')";
|
|
example = "ctrl";
|
|
};
|
|
|
|
launchd.enable = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = "Whether to enable launchd agent for auto-starting aerospace";
|
|
};
|
|
|
|
userSettings = mkOption {
|
|
type = types.attrs;
|
|
default = {};
|
|
description = ''
|
|
Additional aerospace configuration settings to merge with defaults.
|
|
Use this to override or extend the default configuration on a per-machine basis.
|
|
'';
|
|
example = literalExpression ''
|
|
{
|
|
mode.main.binding."''${leader}-custom" = "custom-command";
|
|
}
|
|
'';
|
|
};
|
|
|
|
autoraise = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = "Whether to enable autoraise (auto-focus window on hover)";
|
|
};
|
|
|
|
pollMillis = mkOption {
|
|
type = types.int;
|
|
default = 50;
|
|
description = "Polling interval in milliseconds";
|
|
};
|
|
|
|
delay = mkOption {
|
|
type = types.int;
|
|
default = 2;
|
|
description = "Delay before raising window";
|
|
};
|
|
|
|
focusDelay = mkOption {
|
|
type = types.int;
|
|
default = 2;
|
|
description = "Delay before focusing window";
|
|
};
|
|
};
|
|
|
|
enableSpansDisplays = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Configure macOS Spaces to span displays (required for aerospace multi-monitor support).
|
|
Sets com.apple.spaces.spans-displays to true.
|
|
|
|
NOTE: This was previously set at the system level in modules/aerospace.nix,
|
|
but has been moved to home-manager for better modularity.
|
|
'';
|
|
};
|
|
|
|
ctrlShortcuts = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Remap common macOS Cmd shortcuts to Ctrl equivalents for all operations.
|
|
This makes macOS behave more like Linux.
|
|
|
|
Shortcuts remapped globally:
|
|
- Ctrl+N: New Window
|
|
- Ctrl+T: New Tab
|
|
- Ctrl+W: Close Tab
|
|
- Ctrl+S: Save / Save As
|
|
- Ctrl+O: Open
|
|
- Ctrl+F: Find
|
|
- Ctrl+H: Find and Replace
|
|
- Ctrl+P: Print
|
|
- Ctrl+C/V/X: Copy/Paste/Cut
|
|
- Ctrl+Z: Undo
|
|
|
|
NOTE: Terminal emulators like Ghostty require per-app overrides (configured separately)
|
|
to preserve Ctrl+C as SIGINT instead of Copy.
|
|
'';
|
|
};
|
|
};
|
|
|
|
sketchybar = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = "Whether to enable SketchyBar status bar";
|
|
};
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
# Only apply on Darwin systems
|
|
assertions = [
|
|
{
|
|
assertion = pkgs.stdenv.isDarwin;
|
|
message = "Aerospace role is only supported on macOS (Darwin) systems";
|
|
}
|
|
];
|
|
|
|
# Configure macOS preferences via targets.darwin.defaults
|
|
targets.darwin.defaults = mkMerge [
|
|
# Spaces span displays (required for multi-monitor aerospace)
|
|
(mkIf cfg.enableSpansDisplays {
|
|
"com.apple.spaces" = {
|
|
spans-displays = true;
|
|
};
|
|
})
|
|
|
|
# Ctrl shortcuts to make macOS behave more like Linux
|
|
(mkIf cfg.ctrlShortcuts.enable {
|
|
NSGlobalDomain.NSUserKeyEquivalents = {
|
|
# Window/Tab operations
|
|
"New Window" = "^n";
|
|
"New Tab" = "^t";
|
|
"Close Tab" = "^w";
|
|
# File operations
|
|
"Save" = "^s";
|
|
"Save As…" = "^$s"; # Ctrl+Shift+S
|
|
"Open" = "^o";
|
|
"Open…" = "^o";
|
|
# Find operations
|
|
"Find" = "^f";
|
|
"Find…" = "^f";
|
|
"Find and Replace" = "^h";
|
|
"Find and Replace…" = "^h";
|
|
# Print
|
|
"Print" = "^p";
|
|
"Print…" = "^p";
|
|
# Clipboard operations
|
|
"Copy" = "^c";
|
|
"Paste" = "^v";
|
|
"Cut" = "^x";
|
|
# Undo/Redo
|
|
"Undo" = "^z";
|
|
"Redo" = "^$z"; # Ctrl+Shift+Z
|
|
};
|
|
})
|
|
|
|
# Ghostty-specific overrides to preserve terminal behavior
|
|
# Remap clipboard operations back to Cmd (macOS default) so Ctrl+C remains SIGINT
|
|
(mkIf cfg.ctrlShortcuts.enable {
|
|
"com.mitchellh.ghostty".NSUserKeyEquivalents = {
|
|
# Remap back to Cmd for clipboard operations
|
|
"Copy" = "@c"; # Cmd+C
|
|
"Paste" = "@v"; # Cmd+V
|
|
"Cut" = "@x"; # Cmd+X
|
|
"Undo" = "@z"; # Cmd+Z
|
|
"Redo" = "@$z"; # Cmd+Shift+Z
|
|
};
|
|
})
|
|
];
|
|
|
|
# Install aerospace package and optional tools if enabled
|
|
home.packages = [ pkgs.aerospace ]
|
|
++ optionals cfg.autoraise.enable [ pkgs.autoraise ]
|
|
++ optionals cfg.sketchybar.enable [ pkgs.sketchybar pkgs.sketchybar-app-font ];
|
|
|
|
# Enable and configure aerospace
|
|
programs.aerospace.enable = true;
|
|
programs.aerospace.launchd.enable = cfg.launchd.enable;
|
|
programs.aerospace.userSettings = mkMerge [
|
|
# Default configuration with leader key substitution
|
|
{
|
|
# Disable normalizations for i3-like behavior
|
|
enable-normalization-flatten-containers = false;
|
|
enable-normalization-opposite-orientation-for-nested-containers = false;
|
|
|
|
mode.main.binding = {
|
|
"${cfg.leader}-w" = "layout accordion horizontal"; # tabbed
|
|
"${cfg.leader}-s" = "layout accordion vertical"; # stacking
|
|
"${cfg.leader}-e" = "layout tiles horizontal vertical"; # tiles, toggles orientation
|
|
"${cfg.leader}-shift-q" = "close";
|
|
"${cfg.leader}-shift-f" = "fullscreen";
|
|
"${cfg.leader}-h" = "focus left";
|
|
"${cfg.leader}-j" = "focus down";
|
|
"${cfg.leader}-k" = "focus up";
|
|
"${cfg.leader}-l" = "focus right";
|
|
"${cfg.leader}-shift-h" = "move left";
|
|
"${cfg.leader}-shift-j" = "move down";
|
|
"${cfg.leader}-shift-k" = "move up";
|
|
"${cfg.leader}-shift-l" = "move right";
|
|
"${cfg.leader}-r" = "mode resize";
|
|
"${cfg.leader}-1" = "workspace 1";
|
|
"${cfg.leader}-2" = "workspace 2";
|
|
"${cfg.leader}-3" = "workspace 3";
|
|
"${cfg.leader}-4" = "workspace 4";
|
|
"${cfg.leader}-5" = "workspace 5";
|
|
"${cfg.leader}-6" = "workspace 6";
|
|
"${cfg.leader}-7" = "workspace 7";
|
|
"${cfg.leader}-8" = "workspace 8";
|
|
"${cfg.leader}-9" = "workspace 9";
|
|
"${cfg.leader}-0" = "workspace 10";
|
|
"${cfg.leader}-shift-1" = "move-node-to-workspace 1";
|
|
"${cfg.leader}-shift-2" = "move-node-to-workspace 2";
|
|
"${cfg.leader}-shift-3" = "move-node-to-workspace 3";
|
|
"${cfg.leader}-shift-4" = "move-node-to-workspace 4";
|
|
"${cfg.leader}-shift-5" = "move-node-to-workspace 5";
|
|
"${cfg.leader}-shift-6" = "move-node-to-workspace 6";
|
|
"${cfg.leader}-shift-7" = "move-node-to-workspace 7";
|
|
"${cfg.leader}-shift-8" = "move-node-to-workspace 8";
|
|
"${cfg.leader}-shift-9" = "move-node-to-workspace 9";
|
|
"${cfg.leader}-shift-0" = "move-node-to-workspace 10";
|
|
"${cfg.leader}-tab" = "workspace-back-and-forth";
|
|
"${cfg.leader}-shift-tab" = "move-workspace-to-monitor --wrap-around next";
|
|
|
|
"${cfg.leader}-enter" = ''
|
|
exec-and-forget osascript <<'APPLESCRIPT'
|
|
tell application "Ghostty"
|
|
activate
|
|
tell application "System Events"
|
|
keystroke "n" using {command down}
|
|
end tell
|
|
end tell
|
|
APPLESCRIPT
|
|
'';
|
|
|
|
"${cfg.leader}-shift-enter" = ''
|
|
exec-and-forget osascript <<'APPLESCRIPT'
|
|
tell application "Google Chrome"
|
|
set newWindow to make new window
|
|
activate
|
|
tell newWindow to set index to 1
|
|
end tell
|
|
APPLESCRIPT
|
|
'';
|
|
|
|
"${cfg.leader}-shift-e" = "exec-and-forget zsh --login -c \"emacsclient -c -n\"";
|
|
|
|
# Service mode: Deliberate aerospace window management
|
|
"${cfg.leader}-i" = "mode service";
|
|
|
|
# Passthrough mode: Temporarily disable aerospace to use macOS shortcuts
|
|
"${cfg.leader}-p" = "mode passthrough";
|
|
};
|
|
|
|
# Resize mode: For window resizing operations
|
|
mode.resize.binding = {
|
|
h = "resize width -50";
|
|
j = "resize height +50";
|
|
k = "resize height -50";
|
|
l = "resize width +50";
|
|
|
|
minus = "resize smart -50";
|
|
equal = "resize smart +50";
|
|
|
|
esc = "mode main";
|
|
enter = "mode main";
|
|
};
|
|
|
|
# Service mode: For deliberate aerospace window management operations
|
|
mode.service.binding = {
|
|
esc = ["reload-config" "mode main"];
|
|
r = ["flatten-workspace-tree" "mode main"]; # reset layout
|
|
f = ["layout floating tiling" "mode main"]; # Toggle between floating and tiling layout
|
|
backspace = ["close-all-windows-but-current" "mode main"];
|
|
|
|
"${cfg.leader}-shift-h" = ["join-with left" "mode main"];
|
|
"${cfg.leader}-shift-j" = ["join-with down" "mode main"];
|
|
"${cfg.leader}-shift-k" = ["join-with up" "mode main"];
|
|
"${cfg.leader}-shift-l" = ["join-with right" "mode main"];
|
|
};
|
|
|
|
# Passthrough mode: All shortcuts pass through to macOS
|
|
mode.passthrough.binding = {
|
|
esc = "mode main";
|
|
"${cfg.leader}-p" = "mode main";
|
|
};
|
|
|
|
# SketchyBar integration - notify bar of workspace changes
|
|
exec-on-workspace-change = mkIf cfg.sketchybar.enable [
|
|
"/bin/bash" "-c"
|
|
"${pkgs.sketchybar}/bin/sketchybar --trigger aerospace_workspace_change FOCUSED=$AEROSPACE_FOCUSED_WORKSPACE PREV=$AEROSPACE_PREV_WORKSPACE"
|
|
];
|
|
}
|
|
# Gaps configuration - prevent windows from overlapping SketchyBar
|
|
(mkIf cfg.sketchybar.enable {
|
|
gaps = {
|
|
outer = {
|
|
top = 0;
|
|
bottom = 40;
|
|
left = 0;
|
|
right = 0;
|
|
};
|
|
};
|
|
})
|
|
cfg.userSettings
|
|
];
|
|
|
|
# Launchd agent for autoraise
|
|
launchd.agents.autoraise = mkIf cfg.autoraise.enable {
|
|
enable = true;
|
|
config = {
|
|
ProgramArguments = [
|
|
"${pkgs.autoraise}/bin/AutoRaise"
|
|
"-pollMillis" (toString cfg.autoraise.pollMillis)
|
|
"-delay" (toString cfg.autoraise.delay)
|
|
"-focusDelay" (toString cfg.autoraise.focusDelay)
|
|
];
|
|
RunAtLoad = true;
|
|
KeepAlive = true;
|
|
};
|
|
};
|
|
|
|
# SketchyBar configuration
|
|
home.file.".config/sketchybar/sketchybarrc" = mkIf cfg.sketchybar.enable {
|
|
executable = true;
|
|
onChange = "${pkgs.sketchybar}/bin/sketchybar --reload";
|
|
text = ''
|
|
#!/bin/bash
|
|
|
|
# Plugin directory
|
|
PLUGIN_DIR="$HOME/.config/sketchybar/plugins"
|
|
|
|
# Colors - i3/sway theme with exact color matching
|
|
# Focused window/workspace color from i3/sway
|
|
FOCUSED=0xff285577
|
|
|
|
# Background colors matching i3blocks bar
|
|
BAR_BG=0xcc000000 # Semi-transparent black
|
|
ITEM_BG=0xff333333 # Dark gray for inactive items
|
|
|
|
# Text colors
|
|
TEXT=0xffffffff # White text
|
|
GRAY=0xff888888 # Muted text for inactive items
|
|
|
|
# Accent colors for warnings
|
|
WARNING=0xffff9900
|
|
CRITICAL=0xff900000
|
|
|
|
# Configure the bar appearance
|
|
${pkgs.sketchybar}/bin/sketchybar --bar \
|
|
position=bottom \
|
|
height=32 \
|
|
color=$BAR_BG \
|
|
border_width=0 \
|
|
corner_radius=0 \
|
|
padding_left=10 \
|
|
padding_right=10
|
|
|
|
# Set default properties for all items
|
|
# Using monospace font to match waybar's Fira Code styling
|
|
${pkgs.sketchybar}/bin/sketchybar --default \
|
|
updates=when_shown \
|
|
icon.font="SF Mono:Regular:13.0" \
|
|
icon.color=$TEXT \
|
|
icon.padding_left=4 \
|
|
icon.padding_right=4 \
|
|
label.font="SF Mono:Regular:13.0" \
|
|
label.color=$TEXT \
|
|
label.padding_left=4 \
|
|
label.padding_right=4 \
|
|
padding_left=4 \
|
|
padding_right=4 \
|
|
background.corner_radius=5 \
|
|
background.height=24
|
|
|
|
# Register aerospace workspace change event
|
|
${pkgs.sketchybar}/bin/sketchybar --add event aerospace_workspace_change
|
|
|
|
# Create workspace indicators for workspaces 1-10
|
|
for sid in 1 2 3 4 5 6 7 8 9 10; do
|
|
# Display "0" for workspace 10
|
|
if [ "$sid" = "10" ]; then
|
|
display="0"
|
|
else
|
|
display="$sid"
|
|
fi
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --add item space.$sid left \
|
|
--subscribe space.$sid aerospace_workspace_change \
|
|
--set space.$sid \
|
|
update_freq=2 \
|
|
width=32 \
|
|
background.color=$ITEM_BG \
|
|
background.corner_radius=5 \
|
|
background.height=20 \
|
|
background.drawing=on \
|
|
icon="$display" \
|
|
icon.padding_left=13 \
|
|
icon.padding_right=11 \
|
|
icon.align=center \
|
|
label.drawing=off \
|
|
click_script="${pkgs.aerospace}/bin/aerospace workspace $sid" \
|
|
script="$PLUGIN_DIR/aerospace.sh $sid"
|
|
done
|
|
|
|
# Separator after workspaces
|
|
${pkgs.sketchybar}/bin/sketchybar --add item separator_left left \
|
|
--set separator_left \
|
|
icon="" \
|
|
label="" \
|
|
background.drawing=off \
|
|
padding_left=10 \
|
|
padding_right=10
|
|
|
|
# System monitoring modules (right side)
|
|
# Note: Items added to 'right' appear in reverse order (last added = leftmost)
|
|
# Adding in reverse to get: disk | cpu | memory | battery | volume | calendar
|
|
${pkgs.sketchybar}/bin/sketchybar --add item calendar right \
|
|
--set calendar \
|
|
icon="📅" \
|
|
update_freq=30 \
|
|
background.color=$ITEM_BG \
|
|
background.drawing=on \
|
|
script="$PLUGIN_DIR/calendar.sh"
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --add item separator_media right \
|
|
--set separator_media \
|
|
icon="|" \
|
|
label="" \
|
|
background.drawing=off \
|
|
padding_left=5 \
|
|
padding_right=5
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --add item volume right \
|
|
--set volume \
|
|
background.color=$ITEM_BG \
|
|
background.drawing=on \
|
|
script="$PLUGIN_DIR/volume.sh" \
|
|
--subscribe volume volume_change
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --add item battery right \
|
|
--set battery \
|
|
update_freq=120 \
|
|
background.color=$ITEM_BG \
|
|
background.drawing=on \
|
|
script="$PLUGIN_DIR/battery.sh" \
|
|
--subscribe battery system_woke power_source_change
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --add item separator_sys right \
|
|
--set separator_sys \
|
|
icon="|" \
|
|
label="" \
|
|
background.drawing=off \
|
|
padding_left=5 \
|
|
padding_right=5
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --add item memory right \
|
|
--set memory \
|
|
update_freq=5 \
|
|
icon="🐏" \
|
|
background.color=$ITEM_BG \
|
|
background.drawing=on \
|
|
script="$PLUGIN_DIR/memory.sh"
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --add item cpu right \
|
|
--set cpu \
|
|
update_freq=2 \
|
|
icon="🧠" \
|
|
background.color=$ITEM_BG \
|
|
background.drawing=on \
|
|
script="$PLUGIN_DIR/cpu.sh"
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --add item disk right \
|
|
--set disk \
|
|
update_freq=60 \
|
|
icon="💾" \
|
|
background.color=$ITEM_BG \
|
|
background.drawing=on \
|
|
script="$PLUGIN_DIR/disk.sh"
|
|
|
|
# Menu bar extras / system tray items (rightmost)
|
|
# Note: Requires Screen Recording permission for SketchyBar in System Settings
|
|
# Use 'sketchybar --query default_menu_items' to discover available items
|
|
|
|
# Bluetooth
|
|
${pkgs.sketchybar}/bin/sketchybar --add alias "Control Center,Bluetooth" right \
|
|
--set "Control Center,Bluetooth" \
|
|
alias.update_freq=1 \
|
|
padding_left=0 \
|
|
padding_right=0
|
|
|
|
# WiFi
|
|
${pkgs.sketchybar}/bin/sketchybar --add alias "Control Center,WiFi" right \
|
|
--set "Control Center,WiFi" \
|
|
alias.update_freq=1 \
|
|
padding_left=0 \
|
|
padding_right=0
|
|
|
|
# Add other menu bar apps as discovered
|
|
# Common examples:
|
|
# - Cloudflare WARP: --add alias "Cloudflare WARP,Item-0" right
|
|
# - Notion Calendar: --add alias "Notion Calendar,Item-0" right
|
|
# Run 'sketchybar --query default_menu_items' to find exact names
|
|
|
|
# Update the bar
|
|
${pkgs.sketchybar}/bin/sketchybar --update
|
|
'';
|
|
};
|
|
|
|
# SketchyBar aerospace workspace plugin
|
|
home.file.".config/sketchybar/plugins/aerospace.sh" = mkIf cfg.sketchybar.enable {
|
|
executable = true;
|
|
text = ''
|
|
#!/bin/bash
|
|
|
|
# Colors
|
|
FOCUSED_COLOR=0xff285577
|
|
ITEM_BG=0xff333333
|
|
TEXT=0xffffffff
|
|
GRAY=0xff555555
|
|
|
|
# Get the currently focused workspace directly from aerospace
|
|
# Trim whitespace to ensure clean comparison
|
|
FOCUSED=$(${pkgs.aerospace}/bin/aerospace list-workspaces --focused | tr -d ' \n\r')
|
|
|
|
# Get list of empty workspaces
|
|
EMPTY_WORKSPACES=$(${pkgs.aerospace}/bin/aerospace list-workspaces --monitor all --empty)
|
|
|
|
# Get workspace number - from $1 if provided (event-triggered), otherwise extract from $NAME (routine update)
|
|
# $NAME is always available (e.g., "space.1", "space.2", etc.)
|
|
# $1 is only available when called via event trigger with positional argument
|
|
if [ -n "$1" ]; then
|
|
WORKSPACE_NUM=$(echo "$1" | tr -d ' \n\r')
|
|
else
|
|
# Extract number from item name: "space.1" -> "1", "space.10" -> "10"
|
|
WORKSPACE_NUM=$(echo "$NAME" | sed 's/space\.//')
|
|
fi
|
|
|
|
# Check if workspace has windows (is NOT empty)
|
|
IS_EMPTY=false
|
|
if echo "$EMPTY_WORKSPACES" | grep -q "^$WORKSPACE_NUM$"; then
|
|
IS_EMPTY=true
|
|
fi
|
|
|
|
# Check if this workspace is focused
|
|
IS_FOCUSED=false
|
|
if [ "$WORKSPACE_NUM" = "$FOCUSED" ]; then
|
|
IS_FOCUSED=true
|
|
fi
|
|
|
|
# Determine display value (workspace 10 displays as "0")
|
|
if [ "$WORKSPACE_NUM" = "10" ]; then
|
|
DISPLAY="0"
|
|
else
|
|
DISPLAY="$WORKSPACE_NUM"
|
|
fi
|
|
|
|
# Determine visibility and styling
|
|
# Always show focused workspace (even if empty) with fixed width
|
|
# Hide non-focused empty workspaces by setting width to 0 (collapsed)
|
|
# Show non-focused non-empty workspaces with fixed width and inactive styling
|
|
|
|
if [ "$IS_FOCUSED" = "true" ]; then
|
|
# Focused workspace - always show with focused styling
|
|
${pkgs.sketchybar}/bin/sketchybar --set space.$WORKSPACE_NUM \
|
|
icon="$DISPLAY" \
|
|
width=32 \
|
|
icon.padding_left=13 \
|
|
icon.padding_right=11 \
|
|
icon.align=center \
|
|
background.color=$FOCUSED_COLOR \
|
|
background.drawing=on \
|
|
icon.color=$TEXT
|
|
elif [ "$IS_EMPTY" = "true" ]; then
|
|
# Empty workspace (not focused) - hide by collapsing width and clearing content
|
|
# Using width=0 + empty icon/label instead of drawing=off because drawing=off doesn't reliably re-show items
|
|
${pkgs.sketchybar}/bin/sketchybar --set space.$WORKSPACE_NUM \
|
|
icon="" \
|
|
label="" \
|
|
width=0 \
|
|
icon.padding_left=0 \
|
|
icon.padding_right=0 \
|
|
background.drawing=off
|
|
else
|
|
# Non-empty workspace (not focused) - show with inactive styling
|
|
${pkgs.sketchybar}/bin/sketchybar --set space.$WORKSPACE_NUM \
|
|
icon="$DISPLAY" \
|
|
width=32 \
|
|
icon.padding_left=13 \
|
|
icon.padding_right=11 \
|
|
icon.align=center \
|
|
background.color=$ITEM_BG \
|
|
background.drawing=on \
|
|
icon.color=$GRAY
|
|
fi
|
|
'';
|
|
};
|
|
|
|
# SketchyBar CPU monitoring plugin
|
|
home.file.".config/sketchybar/plugins/cpu.sh" = mkIf cfg.sketchybar.enable {
|
|
executable = true;
|
|
text = ''
|
|
#!/bin/bash
|
|
|
|
CORE_COUNT=$(sysctl -n machdep.cpu.thread_count)
|
|
CPU_INFO=$(ps -eo pcpu,user)
|
|
CPU_SYS=$(echo "$CPU_INFO" | grep -v $(whoami) | sed "s/[^ 0-9\.]//g" | awk "{sum+=\$1} END {print sum/(100.0 * $CORE_COUNT)}")
|
|
CPU_USER=$(echo "$CPU_INFO" | grep $(whoami) | sed "s/[^ 0-9\.]//g" | awk "{sum+=\$1} END {print sum/(100.0 * $CORE_COUNT)}")
|
|
CPU_PERCENT="$(echo "$CPU_SYS $CPU_USER" | awk '{printf "%.0f\n", ($1 + $2)*100}')"
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --set $NAME label="$CPU_PERCENT%"
|
|
'';
|
|
};
|
|
|
|
# SketchyBar memory monitoring plugin
|
|
home.file.".config/sketchybar/plugins/memory.sh" = mkIf cfg.sketchybar.enable {
|
|
executable = true;
|
|
text = ''
|
|
#!/bin/bash
|
|
|
|
MEMORY_STATS=$(vm_stat)
|
|
PAGES_FREE=$(echo "$MEMORY_STATS" | grep "Pages free" | awk '{print $3}' | tr -d '.')
|
|
PAGES_ACTIVE=$(echo "$MEMORY_STATS" | grep "Pages active" | awk '{print $3}' | tr -d '.')
|
|
PAGES_INACTIVE=$(echo "$MEMORY_STATS" | grep "Pages inactive" | awk '{print $3}' | tr -d '.')
|
|
PAGES_WIRED=$(echo "$MEMORY_STATS" | grep "Pages wired down" | awk '{print $4}' | tr -d '.')
|
|
PAGES_COMPRESSED=$(echo "$MEMORY_STATS" | grep "Pages stored in compressor" | awk '{print $5}' | tr -d '.')
|
|
|
|
TOTAL_PAGES=$((PAGES_FREE + PAGES_ACTIVE + PAGES_INACTIVE + PAGES_WIRED + PAGES_COMPRESSED))
|
|
USED_PAGES=$((PAGES_ACTIVE + PAGES_INACTIVE + PAGES_WIRED + PAGES_COMPRESSED))
|
|
MEMORY_PERCENT=$((USED_PAGES * 100 / TOTAL_PAGES))
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --set $NAME label="$MEMORY_PERCENT%"
|
|
'';
|
|
};
|
|
|
|
# SketchyBar disk monitoring plugin
|
|
home.file.".config/sketchybar/plugins/disk.sh" = mkIf cfg.sketchybar.enable {
|
|
executable = true;
|
|
text = ''
|
|
#!/bin/bash
|
|
|
|
DISK_USAGE=$(df -H / | grep -v Filesystem | awk '{print $5}')
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --set $NAME label="$DISK_USAGE"
|
|
'';
|
|
};
|
|
|
|
# SketchyBar battery monitoring plugin
|
|
home.file.".config/sketchybar/plugins/battery.sh" = mkIf cfg.sketchybar.enable {
|
|
executable = true;
|
|
text = ''
|
|
#!/bin/bash
|
|
|
|
PERCENTAGE=$(pmset -g batt | grep -Eo "\d+%" | cut -d% -f1)
|
|
CHARGING=$(pmset -g batt | grep 'AC Power')
|
|
|
|
if [ "$PERCENTAGE" = "" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Select icon based on battery level
|
|
case ''${PERCENTAGE} in
|
|
9[0-9]|100) ICON="🔋"
|
|
;;
|
|
[6-8][0-9]) ICON="🔋"
|
|
;;
|
|
[3-5][0-9]) ICON="🔋"
|
|
;;
|
|
[1-2][0-9]) ICON="🔋"
|
|
;;
|
|
*) ICON="🪫"
|
|
esac
|
|
|
|
# Show charging icon if connected to power
|
|
if [[ $CHARGING != "" ]]; then
|
|
ICON="⚡"
|
|
fi
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --set $NAME icon="$ICON" label="''${PERCENTAGE}%"
|
|
'';
|
|
};
|
|
|
|
# SketchyBar volume monitoring plugin
|
|
home.file.".config/sketchybar/plugins/volume.sh" = mkIf cfg.sketchybar.enable {
|
|
executable = true;
|
|
text = ''
|
|
#!/bin/bash
|
|
|
|
if [ "$SENDER" = "volume_change" ]; then
|
|
VOLUME=$(osascript -e "output volume of (get volume settings)")
|
|
MUTED=$(osascript -e "output muted of (get volume settings)")
|
|
|
|
if [ "$MUTED" = "true" ]; then
|
|
ICON="🔇"
|
|
LABEL=""
|
|
else
|
|
case $VOLUME in
|
|
[6-9][0-9]|100) ICON="🔊"
|
|
;;
|
|
[3-5][0-9]) ICON="🔉"
|
|
;;
|
|
*) ICON="🔈"
|
|
esac
|
|
LABEL="$VOLUME%"
|
|
fi
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --set $NAME icon="$ICON" label="$LABEL"
|
|
fi
|
|
'';
|
|
};
|
|
|
|
# SketchyBar calendar/clock plugin
|
|
home.file.".config/sketchybar/plugins/calendar.sh" = mkIf cfg.sketchybar.enable {
|
|
executable = true;
|
|
text = ''
|
|
#!/bin/bash
|
|
|
|
${pkgs.sketchybar}/bin/sketchybar --set $NAME label="$(date '+%Y-%m-%d %H:%M')"
|
|
'';
|
|
};
|
|
|
|
# Launchd agent for auto-starting sketchybar
|
|
launchd.agents.sketchybar = mkIf cfg.sketchybar.enable {
|
|
enable = true;
|
|
config = {
|
|
ProgramArguments = [ "${pkgs.sketchybar}/bin/sketchybar" ];
|
|
RunAtLoad = true;
|
|
KeepAlive = true;
|
|
StandardOutPath = "/tmp/sketchybar.log";
|
|
StandardErrorPath = "/tmp/sketchybar.err.log";
|
|
};
|
|
};
|
|
};
|
|
}
|