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' local keymap = require 'keyboard.keymaps'
require 'keyboard.yabai' -- require 'keyboard.yabai'
-- General keymap -- General keymap
-- reload config -- reload config
keymap.super { -- keymap.super {
key = 'c', -- key = 'c',
mods = { 'shift' }, -- mods = { 'shift' },
message = 'Reload Hammerspoon config', -- message = 'Reload Hammerspoon config',
fn = function() hs.reload() end, -- 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 = ';', commands = { 'space --layout bsp' } }
yabai_key { key = 'tab', commands = { 'space --focus recent' } } 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 -- navigation
yabai_key { key = 'h', commands = { 'window --focus west', 'display --focus west' }, logic = 'or' } 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' } 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 Promise = require 'promise'
local colors = require 'colors' local colors = require 'colors'
local utils = require 'utils' local utils = require 'utils'
local settings = require 'settings' local settings = require 'settings'
local app_icons = require 'app_icons' local app_icons = require 'app_icons'
local aerospace_cmd = '/opt/homebrew/bin/aerospace'
local function getAllWorkspaces() 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 end
local function getVisibleWorkspaces() 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 end
local function getAllWindows() 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 end
local function getMonitorId(obj) local function getMonitorId(obj)
if obj['monitor-name'] then if obj['monitor-name'] then
if obj['monitor-name'] == 'ZOWIE XL LCD' then if obj['monitor-name'] == 'ZOWIE XL LCD' then
return '2' return 2
elseif obj['monitor-name'] == 'LG ULTRAWIDE' then elseif obj['monitor-name'] == 'LG ULTRAWIDE' then
return '1' return 1
end end
end end
if obj['monitor-appkit-nsscreen-screens-id'] then return obj['monitor-appkit-nsscreen-screens-id'] end if obj['monitor-appkit-nsscreen-screens-id'] then return tonumber(obj['monitor-appkit-nsscreen-screens-id']) or 1 end
return obj['monitor-id'] return tonumber(obj['monitor-id']) or 1
end end
local spaces = {} local spaces = {}
local space_paddings = {} local space_paddings = {}
local brackets = {}
local state = { local state = {
workspaces = {}, workspaces = {},
updating = false, updating = false,
} }
function getState() local function getState()
local newstate = { local newstate = { workspaces = {} }
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] = { newstate.workspaces[workspaceid] = {
monitor = 0, id = workspaceid,
monitor = 1,
active = false, active = false,
empty = true, empty = true,
apps = {}, apps = {},
@ -55,22 +61,24 @@ function getState()
return Promise.all({ getAllWorkspaces(), getVisibleWorkspaces(), getAllWindows() }):thenCall(function(values) return Promise.all({ getAllWorkspaces(), getVisibleWorkspaces(), getAllWindows() }):thenCall(function(values)
local all, visible, apps = values[1], values[2], values[3] local all, visible, apps = values[1], values[2], values[3]
for _, workspace in ipairs(all) do for _, workspace in ipairs(all) do
local workspaceid = workspace['workspace'] local workspaceid = workspace['workspace']
newstate.workspaces[workspaceid]['id'] = workspaceid if newstate.workspaces[workspaceid] then newstate.workspaces[workspaceid]['monitor'] = getMonitorId(workspace) end
newstate.workspaces[workspaceid]['monitor'] = getMonitorId(workspace)
end end
for _, workspace in ipairs(visible) do for _, workspace in ipairs(visible) do
local workspaceid = workspace['workspace'] local workspaceid = workspace['workspace']
newstate.workspaces[workspaceid]['active'] = true if newstate.workspaces[workspaceid] then newstate.workspaces[workspaceid]['active'] = true end
end end
for _, window in ipairs(apps) do for _, window in ipairs(apps) do
local workspaceid = window['workspace'] local workspaceid = window['workspace']
local appname = window['app-name'] local appname = window['app-name']
newstate.workspaces[workspaceid]['apps'][appname] = true if newstate.workspaces[workspaceid] then
newstate.workspaces[workspaceid]['empty'] = false newstate.workspaces[workspaceid]['apps'][appname] = true
newstate.workspaces[workspaceid]['empty'] = false
end
end end
for workspaceid, workspacestate in pairs(newstate.workspaces) do for workspaceid, workspacestate in pairs(newstate.workspaces) do
@ -88,7 +96,6 @@ function getState()
else else
workspacestate['appicons'] = '' workspacestate['appicons'] = ''
end end
-- print(utils.dump(workspacestate))
end end
return newstate return newstate
@ -98,68 +105,26 @@ end
local function updateState() local function updateState()
if not state.updating then if not state.updating then
state.updating = true state.updating = true
return getState():thenCall(function(newstate) return getState()
state.workspaces = newstate.workspaces :thenCall(function(newstate)
state.updating = false state.workspaces = newstate.workspaces
end) state.updating = false
end)
:catch(function(err)
state.updating = false
print('Error updating state: ' .. tostring(err))
end)
end end
return Promise.reject 'State is already updating' return Promise.resolve()
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()
end end
local function syncState() local function syncState()
sbar.animate('tanh', 10, function() sbar.animate('tanh', 10, function()
for workspaceid, workspacestate in pairs(state.workspaces) do for workspaceid, workspacestate in pairs(state.workspaces) do
if not workspacestate['empty'] then if not workspacestate['empty'] or workspacestate['active'] then
spaces[workspaceid]:set { spaces[workspaceid]:set {
drawing = true, drawing = true,
display = workspacestate['monitor'], display = workspacestate['monitor'],
-- label = {
-- string = workspaceid,
-- highlight = workspacestate["active"],
-- },
-- icon = {
-- string = workspaceid,
-- color = colors.white,
-- highlight = workspacestate["active"],
-- },
label = { label = {
string = workspacestate['appicons'], string = workspacestate['appicons'],
highlight = workspacestate['active'], highlight = workspacestate['active'],
@ -170,7 +135,6 @@ local function syncState()
} }
space_paddings[workspaceid]:set { drawing = true } space_paddings[workspaceid]:set { drawing = true }
else else
-- These should be hidden
spaces[workspaceid]:set { spaces[workspaceid]:set {
drawing = false, drawing = false,
display = workspacestate['monitor'], display = workspacestate['monitor'],
@ -184,7 +148,38 @@ end
local function updateStateAndSync() return updateState():thenCall(syncState) 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() getAllWorkspaces()
:thenCall(function(workspaces) :thenCall(function(workspaces)
for _, workspace in ipairs(workspaces) do for _, workspace in ipairs(workspaces) do
@ -192,7 +187,7 @@ function setup()
local display = getMonitorId(workspace) local display = getMonitorId(workspace)
local space = sbar.add('item', 'space.' .. workspaceid, { 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', updates = 'when_shown',
display = display, display = display,
icon = { icon = {
@ -206,11 +201,10 @@ function setup()
highlight_color = colors.blue, highlight_color = colors.blue,
font = 'sketchybar-app-font:Regular:14.0', font = 'sketchybar-app-font:Regular:14.0',
y_offset = -1, y_offset = -1,
-- drawing = false
}, },
padding_left = 1, padding_left = 1,
padding_right = 1, padding_right = 1,
click_script = 'aerospace workspace ' .. workspaceid, click_script = aerospace_cmd .. ' workspace ' .. workspaceid,
}) })
spaces[workspaceid] = space spaces[workspaceid] = space
@ -226,6 +220,8 @@ function setup()
end end
end) end)
:thenCall(function() :thenCall(function()
sbar.add('event', 'aerospace_workspace_change')
local space_window_observer = sbar.add('item', { local space_window_observer = sbar.add('item', {
drawing = false, drawing = false,
updates = true, updates = true,

View file

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

View file

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

View file

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

View file

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

View file

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