feat: aerospace config

This commit is contained in:
Ray Andrew 2025-11-29 15:34:43 -06:00
parent 6a7fcef09d
commit 572d3bfa80
Signed by: rayandrew
SSH key fingerprint: SHA256:XYrYrxF0Z3A72n8P/p6mqPRNQZT22F88XcLsG+kX4xw
10 changed files with 626 additions and 412 deletions

View file

@ -0,0 +1,104 @@
config-version = 2
after-startup-command = [
"workspace 10",
"layout h_accordion",
"workspace-back-and-forth"
]
persistent-workspaces = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
enable-normalization-flatten-containers = false
enable-normalization-opposite-orientation-for-nested-containers = false
on-focused-monitor-changed = ['move-mouse monitor-lazy-center']
exec-on-workspace-change = ['/bin/bash', '-c',
'/run/current-system/sw/bin/sketchybar --trigger aerospace_workspace_change FOCUSED_WORKSPACE=$AEROSPACE_FOCUSED_WORKSPACE PREV_WORKSPACE=$AEROSPACE_PREV_WORKSPACE && /etc/profiles/per-user/rayandrew/bin/aerospace-scratchpad hook pull-window $AEROSPACE_PREV_WORKSPACE $AEROSPACE_FOCUSED_WORKSPACE'
]
[gaps]
inner.horizontal = [{ monitor.'^built-in retina display$' = 10 }, 15]
inner.vertical = [{ monitor.'^built-in retina display$' = 10 }, 15]
outer.left = [{ monitor.'^built-in retina display$' = 5 }, 15]
outer.right = [{ monitor.'^built-in retina display$' = 5 }, 15]
outer.bottom = [{ monitor.'^built-in retina display$' = 5 }, 15]
outer.top = [{ monitor.'^built-in retina display$' = 15 }, 50]
[mode.main.binding]
alt-enter = 'exec-and-forget open -na Ghostty'
alt-h = 'focus --boundaries-action wrap-around-the-workspace left'
alt-j = 'focus --boundaries-action wrap-around-the-workspace down'
alt-k = 'focus --boundaries-action wrap-around-the-workspace up'
alt-l = 'focus --boundaries-action wrap-around-the-workspace right'
alt-shift-h = 'move --boundaries all-monitors-outer-frame left'
alt-shift-j = 'move --boundaries all-monitors-outer-frame down'
alt-shift-k = 'move --boundaries all-monitors-outer-frame up'
alt-shift-l = 'move --boundaries all-monitors-outer-frame right'
alt-v = 'split vertical'
alt-shift-v = 'split horizontal'
alt-f = 'fullscreen'
alt-s = 'layout v_accordion'
alt-e = 'layout tiles horizontal vertical'
alt-space = 'layout floating tiling'
alt-1 = 'workspace 1'
alt-2 = 'workspace 2'
alt-3 = 'workspace 3'
alt-4 = 'workspace 4'
alt-5 = 'workspace 5'
alt-6 = 'workspace 6'
alt-7 = 'workspace 7'
alt-8 = 'workspace 8'
alt-9 = 'workspace 9'
alt-0 = 'workspace 10'
alt-shift-1 = 'move-node-to-workspace 1'
alt-shift-2 = 'move-node-to-workspace 2'
alt-shift-3 = 'move-node-to-workspace 3'
alt-shift-4 = 'move-node-to-workspace 4'
alt-shift-5 = 'move-node-to-workspace 5'
alt-shift-6 = 'move-node-to-workspace 6'
alt-shift-7 = 'move-node-to-workspace 7'
alt-shift-8 = 'move-node-to-workspace 8'
alt-shift-9 = 'move-node-to-workspace 9'
alt-shift-0 = 'move-node-to-workspace 10'
alt-shift-semicolon = 'mode service'
alt-r = 'mode resize'
cmd-ctrl-1 = "exec-and-forget aerospace-scratchpad show Finder"
[mode.resize.binding]
h = 'resize width -50'
j = 'resize height +50'
k = 'resize height -50'
l = 'resize width +50'
enter = 'mode main'
esc = 'mode main'
[mode.service.binding]
c = ['reload-config', 'mode main']
r = ['flatten-workspace-tree', 'mode main']
f = ['layout floating tiling', 'mode main']
backspace = ['close-all-windows-but-current', 'mode main']
alt-shift-h = ['join-with left', 'mode main']
alt-shift-j = ['join-with down', 'mode main']
alt-shift-k = ['join-with up', 'mode main']
alt-shift-l = ['join-with right', 'mode main']
[[on-window-detected]]
if.app-id = 'com.apple.finder'
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.ActivityMonitor'
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.1password.1password'
run = ['layout floating']

View file

@ -1,12 +1,12 @@
local keymap = require 'keyboard.keymaps'
require 'keyboard.yabai'
-- require 'keyboard.yabai'
-- General keymap
-- reload config
keymap.super {
key = 'c',
mods = { 'shift' },
message = 'Reload Hammerspoon config',
fn = function() hs.reload() end,
}
-- keymap.super {
-- key = 'c',
-- mods = { 'shift' },
-- message = 'Reload Hammerspoon config',
-- fn = function() hs.reload() end,
-- }

View file

@ -63,6 +63,17 @@ yabai_key { key = "'", commands = { 'space --layout stack' } }
yabai_key { key = ';', commands = { 'space --layout bsp' } }
yabai_key { key = 'tab', commands = { 'space --focus recent' } }
-- toggle between bsp and stack layout
keymap.super {
key = 's',
message = 'Toggle layout (bsp/stack)',
fn = function()
local current_type = yabai_query('--spaces --space', "'.type'")
local new_layout = current_type == 'bsp' and 'stack' or 'bsp'
os.execute(yabai_cmd .. ' -m space --layout ' .. new_layout)
end,
}
-- navigation
yabai_key { key = 'h', commands = { 'window --focus west', 'display --focus west' }, logic = 'or' }
yabai_key { key = 'j', commands = { 'window --focus south', 'display --focus south' }, logic = 'or' }

View file

@ -1,51 +1,57 @@
-- https://github.com/Tnixc/nix-config/blob/main/home/programs/aerospace-sketchybar/sbar-config-libs/items/aerospaces.lua
local Promise = require 'promise'
local colors = require 'colors'
local utils = require 'utils'
local settings = require 'settings'
local app_icons = require 'app_icons'
local aerospace_cmd = '/opt/homebrew/bin/aerospace'
local function getAllWorkspaces()
return utils.sbarExecP "aerospace list-workspaces --all --format '%{workspace}%{monitor-appkit-nsscreen-screens-id}%{monitor-id}%{monitor-name}' --json"
return utils.sbarExecP(
aerospace_cmd .. " list-workspaces --all --format '%{workspace}%{monitor-appkit-nsscreen-screens-id}%{monitor-id}%{monitor-name}' --json"
)
end
local function getVisibleWorkspaces()
return utils.sbarExecP "aerospace list-workspaces --visible --monitor all --format '%{workspace}%{monitor-appkit-nsscreen-screens-id}%{monitor-id}%{monitor-name}' --json"
return utils.sbarExecP(
aerospace_cmd .. " list-workspaces --visible --monitor all --format '%{workspace}%{monitor-appkit-nsscreen-screens-id}%{monitor-id}%{monitor-name}' --json"
)
end
local function getAllWindows()
return utils.sbarExecP "aerospace list-windows --all --format '%{app-name}%{window-title}%{workspace}%{monitor-id}%{monitor-appkit-nsscreen-screens-id}%{monitor-name}' --json"
return utils.sbarExecP(
aerospace_cmd
.. " list-windows --all --format '%{app-name}%{window-title}%{workspace}%{monitor-id}%{monitor-appkit-nsscreen-screens-id}%{monitor-name}' --json"
)
end
local function getMonitorId(obj)
if obj['monitor-name'] then
if obj['monitor-name'] == 'ZOWIE XL LCD' then
return '2'
return 2
elseif obj['monitor-name'] == 'LG ULTRAWIDE' then
return '1'
return 1
end
end
if obj['monitor-appkit-nsscreen-screens-id'] then return obj['monitor-appkit-nsscreen-screens-id'] end
return obj['monitor-id']
if obj['monitor-appkit-nsscreen-screens-id'] then return tonumber(obj['monitor-appkit-nsscreen-screens-id']) or 1 end
return tonumber(obj['monitor-id']) or 1
end
local spaces = {}
local space_paddings = {}
local brackets = {}
local state = {
workspaces = {},
updating = false,
}
function getState()
local newstate = {
workspaces = {},
}
local function getState()
local newstate = { workspaces = {} }
for workspaceid, space in pairs(spaces) do
-- Pre-initialize all workspaces from the spaces table
for workspaceid, _ in pairs(spaces) do
newstate.workspaces[workspaceid] = {
monitor = 0,
id = workspaceid,
monitor = 1,
active = false,
empty = true,
apps = {},
@ -55,22 +61,24 @@ function getState()
return Promise.all({ getAllWorkspaces(), getVisibleWorkspaces(), getAllWindows() }):thenCall(function(values)
local all, visible, apps = values[1], values[2], values[3]
for _, workspace in ipairs(all) do
local workspaceid = workspace['workspace']
newstate.workspaces[workspaceid]['id'] = workspaceid
newstate.workspaces[workspaceid]['monitor'] = getMonitorId(workspace)
if newstate.workspaces[workspaceid] then newstate.workspaces[workspaceid]['monitor'] = getMonitorId(workspace) end
end
for _, workspace in ipairs(visible) do
local workspaceid = workspace['workspace']
newstate.workspaces[workspaceid]['active'] = true
if newstate.workspaces[workspaceid] then newstate.workspaces[workspaceid]['active'] = true end
end
for _, window in ipairs(apps) do
local workspaceid = window['workspace']
local appname = window['app-name']
newstate.workspaces[workspaceid]['apps'][appname] = true
newstate.workspaces[workspaceid]['empty'] = false
if newstate.workspaces[workspaceid] then
newstate.workspaces[workspaceid]['apps'][appname] = true
newstate.workspaces[workspaceid]['empty'] = false
end
end
for workspaceid, workspacestate in pairs(newstate.workspaces) do
@ -88,7 +96,6 @@ function getState()
else
workspacestate['appicons'] = ''
end
-- print(utils.dump(workspacestate))
end
return newstate
@ -98,68 +105,26 @@ end
local function updateState()
if not state.updating then
state.updating = true
return getState():thenCall(function(newstate)
state.workspaces = newstate.workspaces
state.updating = false
end)
return getState()
:thenCall(function(newstate)
state.workspaces = newstate.workspaces
state.updating = false
end)
:catch(function(err)
state.updating = false
print('Error updating state: ' .. tostring(err))
end)
end
return Promise.reject 'State is already updating'
end
local function highlightSpace(space, space_padding, space_bracket, selected)
space:set {
drawing = true,
icon = { highlight = selected },
label = { highlight = selected },
-- background = { border_color = selected and colors.white or colors.bg2 }
}
space_padding:set {
drawing = true,
}
if space_bracket then
space_bracket:set {
-- background = { border_color = selected and colors.grey or colors.bg2 },
}
end
end
local function onActiveSpaceChange(env)
local focused_workspace = env.FOCUSED_WORKSPACE
local last_workspace = env.PREV_WORKSPACE
-- print("aerospace_workspace_change from " .. last_workspace .. " to " .. focused_workspace)
local space = spaces[focused_workspace]
local space_padding = space_paddings[focused_workspace]
local prev_space = spaces[last_workspace]
local prev_space_padding = space_paddings[last_workspace]
sbar.animate('tanh', 10, function()
highlightSpace(space, space_padding, nil, true)
if state.workspaces[last_workspace]['monitor'] == state.workspaces[focused_workspace]['monitor'] then
highlightSpace(prev_space, prev_space_padding, nil, false)
end
end)
updateState()
return Promise.resolve()
end
local function syncState()
sbar.animate('tanh', 10, function()
for workspaceid, workspacestate in pairs(state.workspaces) do
if not workspacestate['empty'] then
if not workspacestate['empty'] or workspacestate['active'] then
spaces[workspaceid]:set {
drawing = true,
display = workspacestate['monitor'],
-- label = {
-- string = workspaceid,
-- highlight = workspacestate["active"],
-- },
-- icon = {
-- string = workspaceid,
-- color = colors.white,
-- highlight = workspacestate["active"],
-- },
label = {
string = workspacestate['appicons'],
highlight = workspacestate['active'],
@ -170,7 +135,6 @@ local function syncState()
}
space_paddings[workspaceid]:set { drawing = true }
else
-- These should be hidden
spaces[workspaceid]:set {
drawing = false,
display = workspacestate['monitor'],
@ -184,7 +148,38 @@ end
local function updateStateAndSync() return updateState():thenCall(syncState) end
function setup()
local function onActiveSpaceChange(env)
local focused_workspace = env.FOCUSED_WORKSPACE
local prev_workspace = env.PREV_WORKSPACE
-- Immediately show the focused workspace with animation
if spaces[focused_workspace] then
sbar.animate('tanh', 10, function()
spaces[focused_workspace]:set {
drawing = true,
icon = { highlight = true },
label = { highlight = true },
}
space_paddings[focused_workspace]:set { drawing = true }
if spaces[prev_workspace] then
spaces[prev_workspace]:set {
icon = { highlight = false },
label = { highlight = false },
}
-- Hide previous workspace if it's empty
if state.workspaces[prev_workspace] and state.workspaces[prev_workspace]['empty'] then
spaces[prev_workspace]:set { drawing = false }
space_paddings[prev_workspace]:set { drawing = false }
end
end
end)
end
updateStateAndSync()
end
local function setup()
getAllWorkspaces()
:thenCall(function(workspaces)
for _, workspace in ipairs(workspaces) do
@ -192,7 +187,7 @@ function setup()
local display = getMonitorId(workspace)
local space = sbar.add('item', 'space.' .. workspaceid, {
drawing = false, -- default to not showing the space -- we'll show if it has windows or is activated
drawing = false,
updates = 'when_shown',
display = display,
icon = {
@ -206,11 +201,10 @@ function setup()
highlight_color = colors.blue,
font = 'sketchybar-app-font:Regular:14.0',
y_offset = -1,
-- drawing = false
},
padding_left = 1,
padding_right = 1,
click_script = 'aerospace workspace ' .. workspaceid,
click_script = aerospace_cmd .. ' workspace ' .. workspaceid,
})
spaces[workspaceid] = space
@ -226,6 +220,8 @@ function setup()
end
end)
:thenCall(function()
sbar.add('event', 'aerospace_workspace_change')
local space_window_observer = sbar.add('item', {
drawing = false,
updates = true,

View file

@ -22,6 +22,7 @@ local function load_module_if_program_exists(module_name, binary_path)
end
require 'items.apple'
-- require 'items.aerospace'
load_module_if_program_exists('items.aerospace', '/opt/homebrew/bin/aerospace')
load_module_if_program_exists('items.yabai', '/etc/profiles/per-user/rayandrew/bin/yabai')
require 'items.front_app'

View file

@ -1,8 +1,9 @@
{
pkgs,
lib,
config,
home-dir,
dots,
pkgs,
inputs,
...
}:
@ -13,305 +14,310 @@ in
options.custom.gui = with lib; {
aerospace = {
enable = mkEnableOption "Enable aerospace";
logFile = mkOption {
type = types.str;
default = "${home-dir}/Library/Logs/aerospace.log";
description = "Filepath of log output";
};
# logFile = mkOption {
# type = types.str;
# default = "${home-dir}/Library/Logs/aerospace.log";
# description = "Filepath of log output";
# };
};
};
config = lib.mkIf cfg.enable {
launchd.user.agents.aerospace.serviceConfig = {
StandardErrorPath = cfg.logFile;
StandardOutPath = cfg.logFile;
};
services.aerospace = {
enable = true;
# package = pkgs.custom.aerospace;
settings = {
enable-normalization-flatten-containers = false;
enable-normalization-opposite-orientation-for-nested-containers = false;
accordion-padding = 0;
on-focused-monitor-changed = [ "move-mouse monitor-lazy-center" ];
default-root-container-layout = "tiles";
default-root-container-orientation = "auto";
after-startup-command = [
"workspace 10"
"layout h_accordion"
"workspace-back-and-forth"
];
gaps = {
inner = {
horizontal = 15;
vertical = 15;
};
outer = {
left = 10;
bottom = 5;
top = [
{ monitor."LG ULTRAWIDE" = 50; }
{ monitor."ZOWIE XL LCD" = 50; }
12
];
right = 10;
};
};
mode = {
main = {
binding = {
alt-enter =
let
script = pkgs.writeText "ghostty.applescript" ''
do shell script "open -n -a Ghostty"
'';
in
"exec-and-forget osascript ${script}";
# alt-enter = "exec-and-forget \"open -n -a /Applications/Slack.app\"";
alt-shift-f = "fullscreen";
alt-shift-q = "close --quit-if-last-window";
alt-space = "layout floating tiling";
alt-e = "layout tiles horizontal vertical";
alt-t = "layout h_accordion";
alt-s = "layout v_accordion";
alt-v = "split vertical";
alt-shift-v = "split horizontal";
# alt-v = "join-with down";
# alt-shift-v = "join-with right";
alt-h = "focus --boundaries-action wrap-around-the-workspace left";
alt-l = "focus --boundaries-action wrap-around-the-workspace right";
alt-j = "focus --boundaries-action wrap-around-the-workspace down";
alt-k = "focus --boundaries-action wrap-around-the-workspace up";
alt-shift-h = "move left";
alt-shift-l = "move right";
alt-shift-j = "move down";
alt-shift-k = "move up";
cmd-h = [ ]; # Disable "hide application"
cmd-alt-h = [ ]; # Disable "hide others"
cmd-q = [ ]; # Disable "quit"
cmd-shift-q = [ ]; # Disable "logout"
alt-1 = "workspace 1";
alt-2 = "workspace 2";
alt-3 = "workspace 3";
alt-4 = "workspace 4";
alt-5 = "workspace 5";
alt-6 = "workspace 6";
alt-7 = "workspace 7";
alt-8 = "workspace 8";
alt-9 = "workspace 9";
alt-0 = "workspace 10";
alt-shift-1 = [
"move-node-to-workspace 1"
# "workspace 1"
];
alt-shift-2 = [
"move-node-to-workspace 2"
# "workspace 2"
];
alt-shift-3 = [
"move-node-to-workspace 3"
# "workspace 3"
];
alt-shift-4 = [
"move-node-to-workspace 4"
# "workspace 4"
];
alt-shift-5 = [
"move-node-to-workspace 5"
# "workspace 5"
];
alt-shift-6 = [
"move-node-to-workspace 6"
# "workspace 6"
];
alt-shift-7 = [
"move-node-to-workspace 7"
# "workspace 7"
];
alt-shift-8 = [
"move-node-to-workspace 8"
# "workspace 8"
];
alt-shift-9 = [
"move-node-to-workspace 9"
# "workspace 9"
];
alt-shift-0 = [
"move-node-to-workspace 10"
# "workspace 10"
];
alt-shift-c = "reload-config";
alt-tab = "workspace-back-and-forth";
alt-shift-tab = "move-workspace-to-monitor --wrap-around next";
alt-r = "mode resize";
alt-shift-semicolon = "mode service";
};
};
service = {
binding = {
esc = [
"reload-config"
"mode main"
];
r = [
"flatten-workspace-tree"
"mode main"
];
f = [
"layout floating tiling"
"mode main"
];
backspace = [
"close-all-windows-but-current"
"mode main"
];
alt-shift-h = [
"join-with left"
"mode main"
];
alt-shift-j = [
"join-with down"
"mode main"
];
alt-shift-k = [
"join-with up"
"mode main"
];
alt-shift-l = [
"join-with right"
"mode main"
];
# down = "volume down";
# up = "volume up";
# shift-down = [ "volume set 0" "mode main" ];
};
};
resize = {
binding = {
h = "resize width -50";
j = "resize height +50";
k = "resize height -50";
l = "resize width +50";
enter = "mode main";
esc = "mode main";
};
};
};
workspace-to-monitor-force-assignment = {
"1" = "main";
"2" = "main";
"3" = "main";
"4" = "main";
"5" = "main";
"6" = "main";
"7" = [
"2"
"main"
];
"8" = "main";
"9" = "main";
"10" = [
"2"
"main"
];
};
on-window-detected = [
# workspace
# media
{
"if".app-id = "com.spotify.client";
run = [ "move-node-to-workspace 7" ];
}
# browser
{
"if".app-id = "app.zen-browser.zen";
run = [ "move-node-to-workspace 10" ];
}
{
"if".app-id = "com.kagi.kagimacOS";
run = [
"move-node-to-workspace 10"
];
}
# {
# "if".app-id = "com.openai.chat";
# run = [
# "move-node-to-workspace 10"
# ];
# }
# {
# "if".app-id = "app.mozilla.firefox";
# run = [ "move-node-to-workspace 10" ];
# }
# {
# "if".app-id = "com.google.Chrome";
# run = [ "move-node-to-workspace 10" ];
# }
# {
# "if".app-id = "org.chromium.Chromium";
# run = [ "move-node-to-workspace 10" ];
# }
# communications
{
"if".app-id = "com.tinyspeck.slackmacgap";
run = [ "move-node-to-workspace 9" ];
}
{
"if".app-id = "com.microsoft.teams2";
run = [ "move-node-to-workspace 9" ];
}
# special app's layout
## tiling
{
"if".app-id = "com.mitchellh.ghostty";
run = [ "layout tiling" ];
}
## floating
{
"if".app-id = "com.renfei.SnippetsLab";
run = [ "layout floating" ];
}
{
"if".app-id = "com.colliderli.iina";
run = [ "layout tiling" ];
}
{
"if".app-id = "com.apple.ActivityMonitor";
run = [ "layout floating" ];
}
{
"if".app-id = "com.apple.calculator";
run = [ "layout floating" ];
}
{
"if".app-id = "com.apple.finder";
run = [ "layout floating" ];
}
{
"if".app-id = "com.1password.1password";
run = [ "layout floating" ];
}
{
"if".app-id = "com.chabomakers.Antinote";
run = [ "layout floating" ];
}
];
};
};
hm.home.packages = [
inputs.aerospace-scratchpad.packages.${pkgs.stdenv.hostPlatform.system}.default
];
hm.xdg.configFile."aerospace".source =
config.hm.lib.file.mkOutOfStoreSymlink "${dots}/config/aerospace";
# launchd.user.agents.aerospace.serviceConfig = {
# StandardErrorPath = cfg.logFile;
# StandardOutPath = cfg.logFile;
# };
#
# services.aerospace = {
# enable = true;
# # package = pkgs.custom.aerospace;
# settings = {
# enable-normalization-flatten-containers = false;
# enable-normalization-opposite-orientation-for-nested-containers = false;
# accordion-padding = 0;
# on-focused-monitor-changed = [ "move-mouse monitor-lazy-center" ];
# default-root-container-layout = "tiles";
# default-root-container-orientation = "auto";
# after-startup-command = [
# "workspace 10"
# "layout h_accordion"
# "workspace-back-and-forth"
# ];
#
# gaps = {
# inner = {
# horizontal = 15;
# vertical = 15;
# };
# outer = {
# left = 10;
# bottom = 5;
# top = [
# { monitor."LG ULTRAWIDE" = 50; }
# { monitor."ZOWIE XL LCD" = 50; }
# 12
# ];
# right = 10;
# };
# };
#
# mode = {
# main = {
# binding = {
# alt-enter =
# let
# script = pkgs.writeText "ghostty.applescript" ''
# do shell script "open -n -a Ghostty"
# '';
# in
# "exec-and-forget osascript ${script}";
#
# # alt-enter = "exec-and-forget \"open -n -a /Applications/Slack.app\"";
#
# alt-shift-f = "fullscreen";
# alt-shift-q = "close --quit-if-last-window";
# alt-space = "layout floating tiling";
# alt-e = "layout tiles horizontal vertical";
# alt-t = "layout h_accordion";
# alt-s = "layout v_accordion";
# alt-v = "split vertical";
# alt-shift-v = "split horizontal";
# # alt-v = "join-with down";
# # alt-shift-v = "join-with right";
# alt-h = "focus --boundaries-action wrap-around-the-workspace left";
# alt-l = "focus --boundaries-action wrap-around-the-workspace right";
# alt-j = "focus --boundaries-action wrap-around-the-workspace down";
# alt-k = "focus --boundaries-action wrap-around-the-workspace up";
# alt-shift-h = "move left";
# alt-shift-l = "move right";
# alt-shift-j = "move down";
# alt-shift-k = "move up";
#
# cmd-h = [ ]; # Disable "hide application"
# cmd-alt-h = [ ]; # Disable "hide others"
# cmd-q = [ ]; # Disable "quit"
# cmd-shift-q = [ ]; # Disable "logout"
#
# alt-1 = "workspace 1";
# alt-2 = "workspace 2";
# alt-3 = "workspace 3";
# alt-4 = "workspace 4";
# alt-5 = "workspace 5";
# alt-6 = "workspace 6";
# alt-7 = "workspace 7";
# alt-8 = "workspace 8";
# alt-9 = "workspace 9";
# alt-0 = "workspace 10";
#
# alt-shift-1 = [
# "move-node-to-workspace 1"
# # "workspace 1"
# ];
# alt-shift-2 = [
# "move-node-to-workspace 2"
# # "workspace 2"
# ];
# alt-shift-3 = [
# "move-node-to-workspace 3"
# # "workspace 3"
# ];
# alt-shift-4 = [
# "move-node-to-workspace 4"
# # "workspace 4"
# ];
# alt-shift-5 = [
# "move-node-to-workspace 5"
# # "workspace 5"
# ];
# alt-shift-6 = [
# "move-node-to-workspace 6"
# # "workspace 6"
# ];
# alt-shift-7 = [
# "move-node-to-workspace 7"
# # "workspace 7"
# ];
# alt-shift-8 = [
# "move-node-to-workspace 8"
# # "workspace 8"
# ];
# alt-shift-9 = [
# "move-node-to-workspace 9"
# # "workspace 9"
# ];
# alt-shift-0 = [
# "move-node-to-workspace 10"
# # "workspace 10"
# ];
#
# alt-shift-c = "reload-config";
# alt-tab = "workspace-back-and-forth";
# alt-shift-tab = "move-workspace-to-monitor --wrap-around next";
# alt-r = "mode resize";
# alt-shift-semicolon = "mode service";
# };
# };
#
# service = {
# binding = {
# esc = [
# "reload-config"
# "mode main"
# ];
# r = [
# "flatten-workspace-tree"
# "mode main"
# ];
# f = [
# "layout floating tiling"
# "mode main"
# ];
# backspace = [
# "close-all-windows-but-current"
# "mode main"
# ];
#
# alt-shift-h = [
# "join-with left"
# "mode main"
# ];
# alt-shift-j = [
# "join-with down"
# "mode main"
# ];
# alt-shift-k = [
# "join-with up"
# "mode main"
# ];
# alt-shift-l = [
# "join-with right"
# "mode main"
# ];
#
# # down = "volume down";
# # up = "volume up";
# # shift-down = [ "volume set 0" "mode main" ];
# };
# };
#
# resize = {
# binding = {
# h = "resize width -50";
# j = "resize height +50";
# k = "resize height -50";
# l = "resize width +50";
# enter = "mode main";
# esc = "mode main";
# };
# };
# };
#
# workspace-to-monitor-force-assignment = {
# "1" = "main";
# "2" = "main";
# "3" = "main";
# "4" = "main";
# "5" = "main";
# "6" = "main";
# "7" = [
# "2"
# "main"
# ];
# "8" = "main";
# "9" = "main";
# "10" = [
# "2"
# "main"
# ];
# };
#
# on-window-detected = [
# # workspace
# # media
# {
# "if".app-id = "com.spotify.client";
# run = [ "move-node-to-workspace 7" ];
# }
# # browser
# {
# "if".app-id = "app.zen-browser.zen";
# run = [ "move-node-to-workspace 10" ];
# }
# {
# "if".app-id = "com.kagi.kagimacOS";
# run = [
# "move-node-to-workspace 10"
# ];
# }
# # {
# # "if".app-id = "com.openai.chat";
# # run = [
# # "move-node-to-workspace 10"
# # ];
# # }
# # {
# # "if".app-id = "app.mozilla.firefox";
# # run = [ "move-node-to-workspace 10" ];
# # }
# # {
# # "if".app-id = "com.google.Chrome";
# # run = [ "move-node-to-workspace 10" ];
# # }
# # {
# # "if".app-id = "org.chromium.Chromium";
# # run = [ "move-node-to-workspace 10" ];
# # }
# # communications
# {
# "if".app-id = "com.tinyspeck.slackmacgap";
# run = [ "move-node-to-workspace 9" ];
# }
# {
# "if".app-id = "com.microsoft.teams2";
# run = [ "move-node-to-workspace 9" ];
# }
# # special app's layout
# ## tiling
# {
# "if".app-id = "com.mitchellh.ghostty";
# run = [ "layout tiling" ];
# }
# ## floating
# {
# "if".app-id = "com.renfei.SnippetsLab";
# run = [ "layout floating" ];
# }
# {
# "if".app-id = "com.colliderli.iina";
# run = [ "layout tiling" ];
# }
# {
# "if".app-id = "com.apple.ActivityMonitor";
# run = [ "layout floating" ];
# }
# {
# "if".app-id = "com.apple.calculator";
# run = [ "layout floating" ];
# }
# {
# "if".app-id = "com.apple.finder";
# run = [ "layout floating" ];
# }
# {
# "if".app-id = "com.1password.1password";
# run = [ "layout floating" ];
# }
# {
# "if".app-id = "com.chabomakers.Antinote";
# run = [ "layout floating" ];
# }
# ];
# };
# };
};
}

View file

@ -65,6 +65,7 @@
marta = mkEnableOption "Enable marta";
valgrind = mkEnableOption "Enable valgrind";
hammerspoon = mkEnableOption "Enable hammerspoon";
aerospace = mkEnableOption "Enable aerospace";
};
config = lib.mkMerge [
@ -80,10 +81,11 @@
"homebrew/homebrew-createzap" = inputs.homebrew-createzap;
"d12frosted/homebrew-emacs-plus" = inputs.homebrew-emacs-plus;
"brewsci/homebrew-bio" = inputs.homebrew-brewsci-bio;
"nikitabobko/tap" = inputs.homebrew-nikitabobko;
# "LouisBrunner/valgrind" = inputs.homebrew-valgrind;
}
];
mutableTaps = false; # true to enable valgrind
mutableTaps = true; # true to enable valgrind
};
homebrew = {
enable = true;
@ -201,7 +203,7 @@
})
(lib.mkIf config.custom.brew.ice {
homebrew.casks = [
"jordanbaird-ice"
"jordanbaird-ice@beta"
];
})
(lib.mkIf config.custom.brew.contexts {
@ -382,5 +384,10 @@
"hammerspoon"
];
})
(lib.mkIf config.custom.brew.aerospace {
homebrew.casks = [
"aerospace"
];
})
];
}

View file

@ -1,5 +1,24 @@
{
"nodes": {
"aerospace-scratchpad": {
"inputs": {
"nixpkgs": "nixpkgs",
"utils": "utils"
},
"locked": {
"lastModified": 1764407814,
"narHash": "sha256-IiOWUqodFqzy4PhU6LcziwoJbbFR0AfaOBJDO83/mHM=",
"owner": "cristianoliveira",
"repo": "aerospace-scratchpad",
"rev": "d039cd49e2a15144c9a766509abe1b7f59eb6b04",
"type": "github"
},
"original": {
"owner": "cristianoliveira",
"repo": "aerospace-scratchpad",
"type": "github"
}
},
"brew-src": {
"flake": false,
"locked": {
@ -103,7 +122,7 @@
},
"flake-utils": {
"inputs": {
"systems": "systems"
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
@ -141,7 +160,7 @@
},
"flake-utils_3": {
"inputs": {
"systems": "systems_3"
"systems": "systems_4"
},
"locked": {
"lastModified": 1731533236,
@ -161,7 +180,7 @@
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"nixpkgs": "nixpkgs_2",
"zig": "zig",
"zon2nix": "zon2nix"
},
@ -343,6 +362,22 @@
"type": "github"
}
},
"homebrew-nikitabobko": {
"flake": false,
"locked": {
"lastModified": 1764022179,
"narHash": "sha256-OQJ6Wx6Pi61uu46I7xaHpeiTavDQp1ZLVbHJGR1NL20=",
"owner": "nikitabobko",
"repo": "homebrew-tap",
"rev": "80dfd269edca8bc2ec5d83dbd332863cf684f753",
"type": "github"
},
"original": {
"owner": "nikitabobko",
"repo": "homebrew-tap",
"type": "github"
}
},
"homebrew-valgrind": {
"flake": false,
"locked": {
@ -364,8 +399,8 @@
"cl-nix-lite": "cl-nix-lite",
"flake-compat": "flake-compat_3",
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_3",
"systems": "systems_2",
"nixpkgs": "nixpkgs_4",
"systems": "systems_3",
"treefmt-nix": "treefmt-nix"
},
"locked": {
@ -459,20 +494,22 @@
},
"nixpkgs": {
"locked": {
"lastModified": 315532800,
"narHash": "sha256-sV6pJNzFkiPc6j9Bi9JuHBnWdVhtKB/mHgVmMPvDFlk=",
"rev": "82c2e0d6dde50b17ae366d2aa36f224dc19af469",
"type": "tarball",
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.11pre877938.82c2e0d6dde5/nixexprs.tar.xz"
"lastModified": 1747762468,
"narHash": "sha256-I8l6r639PrDpEpAFgY64GmuQ+4NK+nxqAoSUnAEKw9E=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6bd7ba77ef6015853d67a89bd59f01b2880e9050",
"type": "github"
},
"original": {
"type": "tarball",
"url": "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz"
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-firefox-darwin": {
"inputs": {
"nixpkgs": "nixpkgs_6"
"nixpkgs": "nixpkgs_7"
},
"locked": {
"lastModified": 1764291786,
@ -489,6 +526,19 @@
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 315532800,
"narHash": "sha256-sV6pJNzFkiPc6j9Bi9JuHBnWdVhtKB/mHgVmMPvDFlk=",
"rev": "82c2e0d6dde50b17ae366d2aa36f224dc19af469",
"type": "tarball",
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.11pre877938.82c2e0d6dde5/nixexprs.tar.xz"
},
"original": {
"type": "tarball",
"url": "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1758360447,
"narHash": "sha256-XDY3A83bclygHDtesRoaRTafUd80Q30D/Daf9KSG6bs=",
@ -501,7 +551,7 @@
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
}
},
"nixpkgs_3": {
"nixpkgs_4": {
"locked": {
"lastModified": 1732617236,
"narHash": "sha256-PYkz6U0bSEaEB1al7O1XsqVNeSNS+s3NVclJw7YC43w=",
@ -517,7 +567,7 @@
"type": "github"
}
},
"nixpkgs_4": {
"nixpkgs_5": {
"locked": {
"lastModified": 1754340878,
"narHash": "sha256-lgmUyVQL9tSnvvIvBp7x1euhkkCho7n3TMzgjdvgPoU=",
@ -533,7 +583,7 @@
"type": "github"
}
},
"nixpkgs_5": {
"nixpkgs_6": {
"locked": {
"lastModified": 1764242076,
"narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=",
@ -549,7 +599,7 @@
"type": "github"
}
},
"nixpkgs_6": {
"nixpkgs_7": {
"locked": {
"lastModified": 1746683680,
"narHash": "sha256-+5zk+UbG0+GQlKt+gIKm+OhlYvHmkAHFXvf7hl1HDeM=",
@ -565,7 +615,7 @@
"type": "github"
}
},
"nixpkgs_7": {
"nixpkgs_8": {
"locked": {
"lastModified": 1763806073,
"narHash": "sha256-FHsEKDvfWpzdADWj99z7vBk4D716Ujdyveo5+A048aI=",
@ -583,6 +633,7 @@
},
"root": {
"inputs": {
"aerospace-scratchpad": "aerospace-scratchpad",
"disko": "disko",
"ghostty": "ghostty",
"git-hooks": "git-hooks",
@ -592,13 +643,14 @@
"homebrew-core": "homebrew-core",
"homebrew-createzap": "homebrew-createzap",
"homebrew-emacs-plus": "homebrew-emacs-plus",
"homebrew-nikitabobko": "homebrew-nikitabobko",
"homebrew-valgrind": "homebrew-valgrind",
"mac-app-util": "mac-app-util",
"nix-darwin": "nix-darwin",
"nix-homebrew": "nix-homebrew",
"nix-index-database": "nix-index-database",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_5",
"nixpkgs": "nixpkgs_6",
"nixpkgs-firefox-darwin": "nixpkgs-firefox-darwin",
"sops-nix": "sops-nix",
"treefmt-nix": "treefmt-nix_2",
@ -663,6 +715,21 @@
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1689347925,
"narHash": "sha256-ozenz5bFe1UUqOn7f60HRmgc01BgTGIKZ4Xl+HbocGQ=",
@ -677,7 +744,7 @@
"type": "github"
}
},
"systems_3": {
"systems_4": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
@ -694,7 +761,7 @@
},
"treefmt-nix": {
"inputs": {
"nixpkgs": "nixpkgs_4"
"nixpkgs": "nixpkgs_5"
},
"locked": {
"lastModified": 1755934250,
@ -730,10 +797,28 @@
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"yazi": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_7",
"nixpkgs": "nixpkgs_8",
"rust-overlay": "rust-overlay"
},
"locked": {
@ -802,7 +887,7 @@
},
"zon2nix": {
"inputs": {
"nixpkgs": "nixpkgs_2"
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1758405547,

View file

@ -40,8 +40,11 @@
homebrew-brewsci-bio.flake = false;
homebrew-valgrind.url = "github:LouisBrunner/homebrew-valgrind";
homebrew-valgrind.flake = false;
homebrew-nikitabobko.url = "github:nikitabobko/homebrew-tap";
homebrew-nikitabobko.flake = false;
# tools
aerospace-scratchpad.url = "github:cristianoliveira/aerospace-scratchpad";
yazi.url = "github:sxyazi/yazi";
};

View file

@ -5,10 +5,10 @@
{
custom = {
gui = {
aerospace.enable = false;
aerospace.enable = true;
sketchybar.enable = true;
jankyborders.enable = true;
yabai.enable = true;
yabai.enable = false;
};
brew = {
zen-browser = false;
@ -64,6 +64,7 @@
marta = true;
valgrind = true;
hammerspoon = true;
aerospace = true;
};
};