nikitabobko / AeroSpace

AeroSpace is an i3-like tiling window manager for macOS
https://nikitabobko.github.io/AeroSpace/guide
MIT License
5.72k stars 90 forks source link

Vim-like Config #406

Open samholmes opened 1 month ago

samholmes commented 1 month ago

I'd like to share my Aerospace config with the community. I don't know where I can catalog my config, so I'll share it here:

# Place a copy of this config to ~/.aerospace.toml
# After that, you can edit ~/.aerospace.toml to your liking

# It's not necessary to copy all keys to your config.
# If the key is missing in your config, "default-config.toml" will serve as a fallback

# You can use it to add commands that run after login to macOS user session.
# 'start-at-login' needs to be 'true' for 'after-login-command' to work
# Available commands: https://nikitabobko.github.io/AeroSpace/commands
after-login-command = []

# You can use it to add commands that run after AeroSpace startup.
# 'after-startup-command' is run after 'after-login-command'
# Available commands : https://nikitabobko.github.io/AeroSpace/commands
after-startup-command = []

# Start AeroSpace at login
start-at-login = true

# Normalizations. See: https://nikitabobko.github.io/AeroSpace/guide#normalization
enable-normalization-flatten-containers = true
enable-normalization-opposite-orientation-for-nested-containers = true

# See: https://nikitabobko.github.io/AeroSpace/guide#layouts
# The 'accordion-padding' specifies the size of accordion padding
# You can set 0 to disable the padding feature
accordion-padding = 30

# Possible values: tiles|accordion
default-root-container-layout = 'accordion'

# Possible values: horizontal|vertical|auto
# 'auto' means: wide monitor (anything wider than high) gets horizontal orientation,
#               tall monitor (anything higher than wide) gets vertical orientation
default-root-container-orientation = 'auto'

# Possible values: (qwerty|dvorak)
# See https://nikitabobko.github.io/AeroSpace/guide#key-mapping
key-mapping.preset = 'qwerty'

# Mouse follows focus when focused monitor changes
# Drop it from your config, if you don't like this behavior
# See https://nikitabobko.github.io/AeroSpace/guide#on-focus-changed-callbacks
# See https://nikitabobko.github.io/AeroSpace/commands#move-mouse
# on-focused-monitor-changed = ['move-mouse window-lazy-center']
# on-focus-changed = ['move-mouse window-force-center']

# Gaps between windows (inner-*) and between monitor edges (outer-*).
# Possible values:
# - Constant:     gaps.outer.top = 8
# - Per monitor:  gaps.outer.top = [{ monitor.main = 16 }, { monitor."some-pattern" = 32 }, 24]
#                 In this example, 24 is a default value when there is no match.
#                 Monitor pattern is the same as for 'workspace-to-monitor-force-assignment'.
#                 See: https://nikitabobko.github.io/AeroSpace/guide#assign-workspaces-to-monitors
[gaps]
inner.horizontal = 0
inner.vertical =   0
outer.left =       0
outer.bottom =     0
outer.top =        0
outer.right =      0

#
# Bindings
#

# 'main' binding mode declaration
# See: https://nikitabobko.github.io/AeroSpace/guide#binding-modes
# 'main' binding mode must be always presented
[mode.main.binding]
ctrl-space = ['mode alt']

# 'alt' binding mode declaration
[mode.alt.binding]
ctrl-space = ['mode alt']
space = ['mode main']
esc = ['mode alt']
backtick = ['reload-config', 'mode main']

slash = 'layout tiles horizontal vertical'
comma = 'layout accordion horizontal vertical'

# See: https://nikitabobko.github.io/AeroSpace/commands#focus
h = ['focus --boundaries-action stop left', 'move-mouse window-force-center']
j = ['focus --boundaries-action stop down', 'move-mouse window-force-center']
k = ['focus --boundaries-action stop up', 'move-mouse window-force-center']
l = ['focus --boundaries-action stop right', 'move-mouse window-force-center']

c = ['move-mouse window-force-center']

# See: https://nikitabobko.github.io/AeroSpace/commands#move
shift-h = 'move left'
shift-j = 'move down'
shift-k = 'move up'
shift-l = 'move right'

# See: https://nikitabobko.github.io/AeroSpace/commands#resize
minus = 'resize smart -64'
equal = 'resize smart +64'
shift-minus = 'resize smart -128'
shift-equal = 'resize smart +128'

# See: https://nikitabobko.github.io/AeroSpace/commands#workspace
u = 'workspace prev'
i = 'workspace next'
shift-u = 'move-node-to-workspace prev'
shift-i = 'move-node-to-workspace next'
1 = 'workspace 1'
2 = 'workspace 2'
3 = 'workspace 3'
4 = 'workspace 4'
5 = 'workspace 5'
6 = 'workspace 6'
7 = 'workspace 7'
8 = 'workspace 8'
9 = 'workspace 9'
0 = 'workspace 10'
p = ['focus-monitor prev', 'move-mouse window-force-center']
n = ['focus-monitor next', 'move-mouse window-force-center']
shift-p = 'move-workspace-to-monitor prev'
shift-n = 'move-workspace-to-monitor next'

# See: https://nikitabobko.github.io/AeroSpace/commands#move-node-to-workspace
shift-1 = 'move-node-to-workspace 1'
shift-2 = 'move-node-to-workspace 2'
shift-3 = 'move-node-to-workspace 3'
shift-4 = 'move-node-to-workspace 4'
shift-5 = 'move-node-to-workspace 5'
shift-6 = 'move-node-to-workspace 6'
shift-7 = 'move-node-to-workspace 7'
shift-8 = 'move-node-to-workspace 8'
shift-9 = 'move-node-to-workspace 9'
shift-0 = 'move-node-to-workspace 10'

# See: https://nikitabobko.github.io/AeroSpace/commands#workspace-back-and-forth
tab = 'workspace-back-and-forth'
# See: https://nikitabobko.github.io/AeroSpace/commands#move-workspace-to-monitor
shift-tab = 'move-workspace-to-monitor --wrap-around next'

shift-r = ['flatten-workspace-tree', 'mode alt'] # reset layout
#s = ['layout sticky tiling', 'mode alt'] # sticky is not yet supported https://github.com/nikitabobko/AeroSpace/issues/2
f = ['fullscreen'] # Toggle between fullscreen
shift-f = ['layout floating tiling', 'mode alt'] # Toggle between floating and tiling layout

# See: https://nikitabobko.github.io/AeroSpace/commands#mode
r =  'mode resize'
semicolon = 'mode spacial'
w = 'mode workspace'

[mode.resize.binding]
ctrl-space = ['mode binding']
space = 'mode main'
esc = 'mode alt'
r = 'mode alt'
h = ['resize width -64']
j = ['resize height -64']
k = ['resize height +64']
l = ['resize width +64']
shift-h = ['resize width -8']
shift-j = ['resize height -8']
shift-k = ['resize height +8']
shift-l = ['resize width +8']

[mode.spacial.binding]
ctrl-space = ['mode special']
space = 'mode main'
esc = 'mode alt'
h = ['join-with left', 'mode alt']
j = ['join-with down', 'mode alt']
k = ['join-with up', 'mode alt']
l = ['join-with right', 'mode alt']

[mode.workspace.binding]
ctrl-space = ['mode wordspace']
space = 'mode main'
esc = 'mode alt'
w = 'mode alt'
h = ['workspace prev']
l = ['workspace next']
j = ['focus-monitor next']
k = ['focus-monitor prev']
shift-h = ['move-node-to-workspace prev']
shift-l = ['move-node-to-workspace next']
shift-k = ['move-node-to-monitor prev']
shift-j = ['move-node-to-monitor next']

#
# Application-specific configurations (optional)
#

# [[on-window-detected]]
# if.app-id = 'com.apple.reminders'
# run = 'layout floating'

One single command to switch to alt mode: ctrl+space. Then once in alt mode hjkl keys to navigate windows. Hold shift with these keys to move window. Switch to resize mode with r. Switch to workspace mode with w. Backtick always refreshes config. There's special mode with ;, which allows you to merge windows.

Let me know what you all think of this setup.

I'm loving Aerospace! I'm happy to contribute some fixes and features where I can, but I'd have to orient myself to the swift project a bit more.

ctruett commented 1 month ago

Thanks -- I really like this! I made a few modifications that felt more "vimmy" to me:

  1. Added mode main to the end of every command so it switches back to the default mode after executing.
  2. Set ctrl-a as the keybind for window selection / manipulation
samholmes commented 1 month ago

@ctruett By adding mode main (or mode alt) at the end of other commands in a mode, that makes the mode more like a vim "motion" rather than a mode. That's fine I suppose, but some modes can be sticky (more like VISUAL mode in vim is sticky).

I don't know what you mean by ctrl-a for "selection/manipulation"?

Once Aerospace CLI performs better, I'll switch to using skhd for binding so that way I can run a command when entering a mode to make some visual change to my desktop so that way it's obvious when one is in a sticky mode and there would be less need to rely on motions.

AlexBurdu commented 1 week ago

This is great, thanks! I borrowed some of your ideas in my config.

thewinger commented 1 week ago

Once Aerospace CLI performs better, I'll switch to using skhd for binding so that way I can run a command when entering a mode to make some visual change to my desktop so that way it's obvious when one is in a sticky mode and there would be less need to rely on motions.

I did something like this but with Sketchybar, when entering a mode other than main sketchybar turns red and the name of the mode appears in the bar.

thewinger commented 1 week ago

Finally have my config based on your Vim-like config in a place I'm happy: Config

samholmes commented 1 week ago

Here's my latest config since original post:

# Less confusing to start with tiles then to start with accordion when there are a lot of windows
default-root-container-layout = 'tiles'

# Possible values: horizontal|vertical|auto
# 'auto' means: wide monitor (anything wider than high) gets horizontal orientation,
#               tall monitor (anything higher than wide) gets vertical orientation
default-root-container-orientation = 'auto'

# Possible values: (qwerty|dvorak)
# See https://nikitabobko.github.io/AeroSpace/guide#key-mapping
key-mapping.preset = 'qwerty'

# See: https://nikitabobko.github.io/AeroSpace/guide#layouts
# The 'accordion-padding' specifies the size of accordion padding
# You can set 0 to disable the padding feature
accordion-padding = 8

# Mouse follows focus when focused monitor changes
# Drop it from your config, if you don't like this behavior
# See https://nikitabobko.github.io/AeroSpace/guide#on-focus-changed-callbacks
# See https://nikitabobko.github.io/AeroSpace/commands#move-mouse
# on-focused-monitor-changed = ['move-mouse window-lazy-center']
# on-focus-changed = ['move-mouse window-force-center']

# Gaps between windows (inner-*) and between monitor edges (outer-*).
# Possible values:
# - Constant:     gaps.outer.top = 8
# - Per monitor:  gaps.outer.top = [{ monitor.main = 16 }, { monitor."some-pattern" = 32 }, 24]
#                 In this example, 24 is a default value when there is no match.
#                 Monitor pattern is the same as for 'workspace-to-monitor-force-assignment'.
#                 See: https://nikitabobko.github.io/AeroSpace/guide#assign-workspaces-to-monitors
[gaps]
inner.horizontal = 0
inner.vertical =   0
outer.left =       0
outer.bottom =     0
outer.top =        0
outer.right =      0

#
# Bindings
#

# All possible keys:
# - Letters.        a, b, c, ..., z
# - Numbers.        0, 1, 2, ..., 9
# - Keypad numbers. keypad0, keypad1, keypad2, ..., keypad9
# - F-keys.         f1, f2, ..., f20
# - Special keys.   minus, equal, period, comma, slash, backslash, quote, semicolon, backtick,
#                   leftSquareBracket, rightSquareBracket, space, enter, esc, backspace, tab
# - Keypad special. keypadClear, keypadDecimalMark, keypadDivide, keypadEnter, keypadEqual,
#                   keypadMinus, keypadMultiply, keypadPlus
# - Arrows.         left, down, up, right

# All possible modifiers: cmd, alt, ctrl, shift

# All possible commands: https://nikitabobko.github.io/AeroSpace/commands

# 'main' binding mode declaration
# See: https://nikitabobko.github.io/AeroSpace/guide#binding-modes
# 'main' binding mode must be always presented
[mode.main.binding]
ctrl-alt-cmd-space = ['mode alt']

# ctrl-alt-cmd-h = ['focus --boundaries-action stop left', 'move-mouse window-force-center']
# ctrl-alt-cmd-j = ['focus --boundaries-action stop down', 'move-mouse window-force-center']
# ctrl-alt-cmd-k = ['focus --boundaries-action stop up', 'move-mouse window-force-center']
# ctrl-alt-cmd-l = ['focus --boundaries-action stop right', 'move-mouse window-force-center']
# ctrl-alt-cmd-u = 'workspace prev'
# ctrl-alt-cmd-i = 'workspace next'
# ctrl-alt-cmd-p = ['focus-monitor prev', 'move-mouse window-force-center']
# ctrl-alt-cmd-n = ['focus-monitor next', 'move-mouse window-force-center']

[mode.alt.binding]
# ctrl-alt-cmd-space = ['mode main']
space = ['mode main']
esc = ['mode main']
backtick = ['reload-config', 'mode main']

# You can uncomment this line to open up terminal with alt + enter shortcut
# See: https://nikitabobko.github.io/AeroSpace/commands#exec-and-forget
# alt-enter = 'exec-and-forget open -n /System/Applications/Utilities/Terminal.app'

# See: https://nikitabobko.github.io/AeroSpace/commands#layout
slash = 'layout horizontal vertical'
quote = 'layout tiles accordion'

#
# Navigation
#

# See: https://nikitabobko.github.io/AeroSpace/commands#focus
h = ['focus --boundaries-action stop left', 'move-mouse window-force-center']
j = ['focus --boundaries-action stop down', 'move-mouse window-force-center']
k = ['focus --boundaries-action stop up', 'move-mouse window-force-center']
l = ['focus --boundaries-action stop right', 'move-mouse window-force-center']
u = 'workspace prev'
i = 'workspace next'
p = ['focus-monitor prev', 'move-mouse window-force-center']
n = ['focus-monitor next', 'move-mouse window-force-center']

ctrl-alt-cmd-h = ['workspace prev']
ctrl-alt-cmd-l = ['workspace next']
ctrl-alt-cmd-k = ['focus-monitor prev', 'move-mouse window-force-center']
ctrl-alt-cmd-j = ['focus-monitor next', 'move-mouse window-force-center']

c = ['move-mouse window-force-center']

# See: https://nikitabobko.github.io/AeroSpace/commands#workspace
1 = 'workspace 1'
2 = 'workspace 2'
3 = 'workspace 3'
4 = 'workspace 4'
5 = 'workspace 5'
6 = 'workspace 6'
7 = 'workspace 7'
8 = 'workspace 8'
9 = 'workspace 9'

# See: https://nikitabobko.github.io/AeroSpace/commands#workspace-back-and-forth
tab = 'workspace-back-and-forth'

#
# Moving
#

# See: https://nikitabobko.github.io/AeroSpace/commands#move
shift-h = 'move left'
shift-j = 'move down'
shift-k = 'move up'
shift-l = 'move right'
shift-u = 'move-node-to-workspace prev'
shift-i = 'move-node-to-workspace next'
shift-p = 'move-workspace-to-monitor prev'
shift-n = 'move-workspace-to-monitor next'
ctrl-alt-cmd-shift-h = ['move-node-to-workspace prev']
ctrl-alt-cmd-shift-l = ['move-node-to-workspace next']
ctrl-alt-cmd-shift-k = ['move-workspace-to-monitor prev']
ctrl-alt-cmd-shift-j = ['move-workspace-to-monitor next']

# See: https://nikitabobko.github.io/AeroSpace/commands#move-node-to-workspace
shift-1 = 'move-node-to-workspace 1'
shift-2 = 'move-node-to-workspace 2'
shift-3 = 'move-node-to-workspace 3'
shift-4 = 'move-node-to-workspace 4'
shift-5 = 'move-node-to-workspace 5'
shift-6 = 'move-node-to-workspace 6'
shift-7 = 'move-node-to-workspace 7'
shift-8 = 'move-node-to-workspace 8'
shift-9 = 'move-node-to-workspace 9'

# See: https://nikitabobko.github.io/AeroSpace/commands#move-workspace-to-monitor
shift-tab = 'move-workspace-to-monitor --wrap-around next'

#
# Resizing
#

# See: https://nikitabobko.github.io/AeroSpace/commands#resize
minus = 'resize smart -64'
equal = 'resize smart +64'
shift-minus = 'resize smart -128'
shift-equal = 'resize smart +128'

#
# Other
#

shift-r = ['flatten-workspace-tree', 'mode alt'] # reset layout
#s = ['layout sticky tiling', 'mode alt'] # sticky is not yet supported https://github.com/nikitabobko/AeroSpace/issues/2
# Toggle Maximize window
m = ['fullscreen']
# Float window
f = ['layout floating']
# Tile window
t = ['layout tiling']

#
# Modes
#

# See: https://nikitabobko.github.io/AeroSpace/commands#mode
r =  'mode resize'
semicolon = 'mode spacial'
w = 'mode workspace'

#
# Resize Mode
#

[mode.resize.binding]
# ctrl-alt-cmd-space = ['mode binding']
space = 'mode main'
esc = 'mode alt'
r = 'mode alt'
h = ['resize width -64']
j = ['resize height -64']
k = ['resize height +64']
l = ['resize width +64']
shift-h = ['resize width -8']
shift-j = ['resize height -8']
shift-k = ['resize height +8']
shift-l = ['resize width +8']

[mode.spacial.binding]
# ctrl-alt-cmd-space = ['mode special']
space = 'mode main'
esc = 'mode alt'
h = ['join-with left', 'mode alt']
j = ['join-with down', 'mode alt']
k = ['join-with up', 'mode alt']
l = ['join-with right', 'mode alt']

[mode.workspace.binding]
# ctrl-alt-cmd-space = ['mode workspace']
space = 'mode main'
esc = 'mode alt'
w = 'mode alt'
h = ['workspace prev', 'move-mouse window-force-center']
l = ['workspace next', 'move-mouse window-force-center']
j = ['focus-monitor next', 'move-mouse window-force-center']
k = ['focus-monitor prev', 'move-mouse window-force-center']
shift-h = ['move-node-to-workspace prev']
shift-l = ['move-node-to-workspace next']
shift-k = ['move-node-to-monitor prev']
shift-j = ['move-node-to-monitor next']

#
# Application-specific configurations
#

# [[on-window-detected]]
# run = 'layout floating'

[[on-window-detected]]
if.app-name-regex-substring = 'Code - Insiders|Warp|Xcode|Simulator'
run = ['layout tiling', 'move-node-to-workspace 2']

[[on-window-detected]]
if.app-name-regex-substring = 'Sublime Merge'
run = ['layout tiling', 'move-node-to-workspace 3']

[[on-window-detected]]
if.app-name-regex-substring = 'Slack|Mailspring|Calendar|zoom.us'
run = ['layout tiling', 'move-node-to-workspace 4']

[[on-window-detected]]
if.app-name-regex-substring = 'Signal|Discord|Messages'
run = ['layout tiling', 'move-node-to-workspace 5']

Notable changes:

# Possible values: tiles|accordion
default-root-container-layout = 'tiles'

# Just subtle enough to notice a window is apart of an accordion
accordion-padding = 8

# Changed from ctrl-space to a "hyper key", ctrl-alt-cmd. 
# I configured Caps Lock to be hyper using Karabiner-Elements.
[mode.main.binding]
ctrl-alt-cmd-space = ['mode alt']

[mode.alt.binding]
# Space always exits all modes
space = ['mode main']
# Escape only exists one level
esc = ['mode main']

# Slash only rotates between horizontal and vertical layouts
slash = 'layout horizontal vertical'
# Quote toggles between tiles and accordion (because " ' is printed on the 
# same key, so it made sense to me)
quote = 'layout tiles accordion'

# These are new for 'alt mode' to make it easier to move around workspaces and
# monitors
ctrl-alt-cmd-h = ['workspace prev']
ctrl-alt-cmd-l = ['workspace next']
ctrl-alt-cmd-k = ['focus-monitor prev', 'move-mouse window-force-center']
ctrl-alt-cmd-j = ['focus-monitor next', 'move-mouse window-force-center']

# Because I don't include shift in my hyper key configuration, I can chord with it
# to move windows between workspaces and monitors.
ctrl-alt-cmd-shift-h = ['move-node-to-workspace prev']
ctrl-alt-cmd-shift-l = ['move-node-to-workspace next']
ctrl-alt-cmd-shift-k = ['move-workspace-to-monitor prev']
ctrl-alt-cmd-shift-j = ['move-workspace-to-monitor next']

shift-r = ['flatten-workspace-tree', 'mode alt'] # reset layout

# Fullscreen is under 'm' for "Maximize"
m = ['fullscreen']

# No more toggling for these commands
f = ['layout floating']
t = ['layout tiling']

[mode.workspace.binding]
# Rely on 'move-mouse window-force-center' command for cursor adjustment instead
# of the buggy on window focus events.
h = ['workspace prev', 'move-mouse window-force-center']
l = ['workspace next', 'move-mouse window-force-center']
j = ['focus-monitor next', 'move-mouse window-force-center']
k = ['focus-monitor prev', 'move-mouse window-force-center']

# I love using if.app-name-regex-substring to match the app name to assign it
# to a specific workspace. It's easier to add new things here without needing to
# get the app ID.
[[on-window-detected]]
if.app-name-regex-substring = 'Code - Insiders|Warp|Xcode|Simulator'
run = ['layout tiling', 'move-node-to-workspace 2']

[[on-window-detected]]
if.app-name-regex-substring = 'Sublime Merge'
run = ['layout tiling', 'move-node-to-workspace 3']

[[on-window-detected]]
if.app-name-regex-substring = 'Slack|Mailspring|Calendar|zoom.us'
run = ['layout tiling', 'move-node-to-workspace 4']

[[on-window-detected]]
if.app-name-regex-substring = 'Signal|Discord|Messages'
run = ['layout tiling', 'move-node-to-workspace 5']
pkazmier commented 2 days ago

I just discovered aerospace yesterday and am loving it. The alt key chords are tough on me, which is why I like the modal ideas presented here. I prefer your first version better I think, but I’ll noodle on this a bit this weekend to think of an optimal layout for myself. Thanks again.

samholmes commented 2 days ago

I just discovered aerospace yesterday and am loving it. The alt key chords are tough on me, which is why I like the modal ideas presented here. I prefer your first version better I think, but I’ll noodle on this a bit this weekend to think of an optimal layout for myself. Thanks again.

Thanks! Do note that you'd need to configure hyper-key using Karabiner to make Cap-Lock the hyper key. Otherwise, you could opt for just ctrl as the modifier key, but this ensures less conflicts with other programs which may use curl-space (although not so likely).