235 lines
7.9 KiB
Nix
235 lines
7.9 KiB
Nix
{ config, lib, pkgs, globalInputs, system, ... }:
|
|
|
|
let
|
|
leader = "cmd"; # Change this to experiment with different leader keys (e.g., "cmd", "ctrl")
|
|
in
|
|
{
|
|
# Home Manager configuration for Darwin work laptop
|
|
# Corporate-friendly setup with essential development tools
|
|
|
|
home.username = lib.mkForce "johno";
|
|
home.homeDirectory = lib.mkForce "/Users/johno";
|
|
home.stateVersion = "24.05";
|
|
|
|
# System packages
|
|
home.packages = with pkgs; [
|
|
autoraise
|
|
];
|
|
|
|
# Note: ghostty installed via Homebrew (managed outside of nix)
|
|
|
|
# Auto-start autoraise on login
|
|
launchd.agents.autoraise = {
|
|
enable = true;
|
|
config = {
|
|
ProgramArguments = [
|
|
"${pkgs.autoraise}/bin/AutoRaise"
|
|
"-pollMillis" "50"
|
|
"-delay" "2"
|
|
"-focusDelay" "2"
|
|
];
|
|
RunAtLoad = true;
|
|
KeepAlive = true;
|
|
};
|
|
};
|
|
|
|
# Auto-start aerospace on login
|
|
# NOTE: In 25.11+, this can be simplified to `programs.aerospace.launchd.enable = true`
|
|
launchd.agents.aerospace = {
|
|
enable = true;
|
|
config = {
|
|
Program = "${pkgs.aerospace}/Applications/AeroSpace.app/Contents/MacOS/AeroSpace";
|
|
RunAtLoad = true;
|
|
KeepAlive = true;
|
|
StandardOutPath = "/tmp/aerospace.log";
|
|
StandardErrorPath = "/tmp/aerospace.err.log";
|
|
};
|
|
};
|
|
|
|
# Override Darwin-incompatible settings from base role
|
|
programs.rbw.settings.pinentry = lib.mkForce pkgs.pinentry_mac;
|
|
|
|
# Disable Home Manager from managing shell RC files
|
|
# topsoil/compost will manage these files instead
|
|
programs.bash.enable = lib.mkForce false;
|
|
programs.zsh.enable = lib.mkForce false;
|
|
|
|
# Create a local nix integration file that topsoil-managed configs can source
|
|
home.file.".nix-integration.sh" = {
|
|
text = ''
|
|
# Source Home Manager session variables (nix paths, environment, etc.)
|
|
if [ -e /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh ]; then
|
|
. /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh
|
|
fi
|
|
|
|
# Setup bash completions from nix profiles
|
|
if [[ ! -v BASH_COMPLETION_VERSINFO ]] && [ -n "$NIX_PROFILES" ]; then
|
|
for profile in $NIX_PROFILES; do
|
|
if [ -f "$profile/etc/profile.d/bash_completion.sh" ]; then
|
|
. "$profile/etc/profile.d/bash_completion.sh"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# command-not-found handler
|
|
command_not_found_handle() {
|
|
local p=/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite
|
|
if [ -n "$NIX_PROFILES" ]; then
|
|
for profile in $NIX_PROFILES; do
|
|
if [ -x "$profile/bin/command-not-found" ] && [ -f "$p" ]; then
|
|
"$profile/bin/command-not-found" "$@"
|
|
return $?
|
|
fi
|
|
done
|
|
fi
|
|
echo "$1: command not found" >&2
|
|
return 127
|
|
}
|
|
'';
|
|
};
|
|
|
|
home.file.".nix-integration.zsh" = {
|
|
text = ''
|
|
# Source Home Manager session variables (nix paths, environment, etc.)
|
|
if [ -e /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh ]; then
|
|
. /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh
|
|
fi
|
|
|
|
# Setup zsh completions from nix profiles
|
|
typeset -U path cdpath fpath manpath
|
|
for profile in ''${(z)NIX_PROFILES}; do
|
|
fpath+=($profile/share/zsh/site-functions $profile/share/zsh/$ZSH_VERSION/functions $profile/share/zsh/vendor-completions)
|
|
done
|
|
autoload -U compinit && compinit
|
|
|
|
# command-not-found handler
|
|
command_not_found_handler() {
|
|
local p=/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite
|
|
if [ -n "$NIX_PROFILES" ]; then
|
|
for profile in ''${(z)NIX_PROFILES}; do
|
|
if [ -x "$profile/bin/command-not-found" ] && [ -f "$p" ]; then
|
|
"$profile/bin/command-not-found" "$@"
|
|
return $?
|
|
fi
|
|
done
|
|
fi
|
|
echo "$1: command not found" >&2
|
|
return 127
|
|
}
|
|
'';
|
|
};
|
|
|
|
# Keep SSH and Git disabled to avoid conflicts with work environment
|
|
programs.ssh.enable = lib.mkForce false;
|
|
programs.git.enable = lib.mkForce false;
|
|
programs.rbw.enable = lib.mkForce false;
|
|
|
|
home.shell.enableShellIntegration = true;
|
|
|
|
# TODO: Move this to its own role and/or module
|
|
programs.aerospace = {
|
|
enable = true;
|
|
userSettings.mode.main.binding = {
|
|
"${leader}-slash" = "layout tiles horizontal vertical";
|
|
"${leader}-comma" = "layout accordion horizontal vertical";
|
|
"${leader}-shift-q" = "close";
|
|
"${leader}-shift-f" = "fullscreen";
|
|
"${leader}-h" = "focus left";
|
|
"${leader}-j" = "focus down";
|
|
"${leader}-k" = "focus up";
|
|
"${leader}-l" = "focus right";
|
|
"${leader}-shift-h" = "move left";
|
|
"${leader}-shift-j" = "move down";
|
|
"${leader}-shift-k" = "move up";
|
|
"${leader}-shift-l" = "move right";
|
|
"${leader}-minus" = "resize smart -50";
|
|
"${leader}-equal" = "resize smart +50";
|
|
"${leader}-1" = "workspace 1";
|
|
"${leader}-2" = "workspace 2";
|
|
"${leader}-3" = "workspace 3";
|
|
"${leader}-4" = "workspace 4";
|
|
"${leader}-5" = "workspace 5";
|
|
"${leader}-6" = "workspace 6";
|
|
"${leader}-7" = "workspace 7";
|
|
"${leader}-8" = "workspace 8";
|
|
"${leader}-9" = "workspace 9";
|
|
"${leader}-0" = "workspace 10";
|
|
"${leader}-shift-1" = "move-node-to-workspace 1";
|
|
"${leader}-shift-2" = "move-node-to-workspace 2";
|
|
"${leader}-shift-3" = "move-node-to-workspace 3";
|
|
"${leader}-shift-4" = "move-node-to-workspace 4";
|
|
"${leader}-shift-5" = "move-node-to-workspace 5";
|
|
"${leader}-shift-6" = "move-node-to-workspace 6";
|
|
"${leader}-shift-7" = "move-node-to-workspace 7";
|
|
"${leader}-shift-8" = "move-node-to-workspace 8";
|
|
"${leader}-shift-9" = "move-node-to-workspace 9";
|
|
"${leader}-shift-0" = "move-node-to-workspace 10";
|
|
"${leader}-tab" = "workspace-back-and-forth";
|
|
"${leader}-shift-tab" = "move-workspace-to-monitor --wrap-around next";
|
|
|
|
"${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
|
|
'';
|
|
|
|
"${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
|
|
'';
|
|
|
|
"${leader}-shift-e" = "exec-and-forget zsh --login -c \"emacsclient -c -n\"";
|
|
|
|
# Service mode: Deliberate aerospace window management
|
|
"${leader}-i" = "mode service";
|
|
|
|
# Passthrough mode: Temporarily disable aerospace to use macOS shortcuts
|
|
# Press Cmd-P, then use any macOS shortcut (like Cmd-K in Slack), then press Cmd-P again to exit
|
|
"${leader}-p" = "mode passthrough";
|
|
};
|
|
|
|
# Service mode: For deliberate aerospace window management operations
|
|
userSettings.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"];
|
|
|
|
"${leader}-shift-h" = ["join-with left" "mode main"];
|
|
"${leader}-shift-j" = ["join-with down" "mode main"];
|
|
"${leader}-shift-k" = ["join-with up" "mode main"];
|
|
"${leader}-shift-l" = ["join-with right" "mode main"];
|
|
};
|
|
|
|
# Passthrough mode: All shortcuts pass through to macOS
|
|
# This mode has minimal bindings - just ways to exit back to main mode
|
|
userSettings.mode.passthrough.binding = {
|
|
esc = "mode main";
|
|
"${leader}-p" = "mode main"; # Toggle back with same key (Cmd-P)
|
|
};
|
|
};
|
|
|
|
home.roles = {
|
|
base.enable = true;
|
|
development.enable = true;
|
|
};
|
|
|
|
imports = [
|
|
./roles
|
|
./modules/emacs
|
|
./modules/kubectl
|
|
./modules/tmux
|
|
];
|
|
}
|