Skip to content

Instantly share code, notes, and snippets.

@ethan-leba
Last active March 13, 2024 13:34
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ethan-leba/760054f36a2f7c144c6b06ab6458fae6 to your computer and use it in GitHub Desktop.
Save ethan-leba/760054f36a2f7c144c6b06ab6458fae6 to your computer and use it in GitHub Desktop.
Yabai + Emacs seamless window movement

Yabai + Emacs window movement integration

This is a short guide to setting up unified window movement bindings with Yabai + SKHD and Emacs, inspired by this tmux-vim movement guide. Short video demo here.

For example, if there’s if Emacs is in focus and there’s an Emacs window to the left, then that window will be focused with the binding. Otherwise, the next application to the left will be focused. In this guide I’m using alt - HJKL, but you can substitute those with whatever you’d like.

The solution

  1. Configure SKHD to passthrough the movement keys when Emacs is focused.
  2. Add custom yabai window movement commands to Emacs load-path or config.
  3. Add matching bindings to Emacs config.
  4. Profit!

SKHD

Add the following snippet to your .skhdrc file:

alt - h [
  *      : yabai -m window --focus west
  "Emacs" ~
]
alt - l  [
  *      : yabai -m window --focus east
  "Emacs" ~
]
alt - k  [
  *      : yabai -m window --focus north
  "Emacs" ~
]
alt - j  [
  *      : yabai -m window --focus south
  "Emacs" ~
]

SKHD will now allow the above keys to pass through to Emacs when focused.

Emacs yabai functions

Next add the following functions to your emacs config:

(defun yabai-move-on-error (direction move-fn)
  (interactive)
  (condition-case nil
      (funcall move-fn)
    (user-error (start-process "yabai" nil "yabai" "-m" "window" "--focus" direction))))

(defun yabai-window-left ()
  (interactive)
  (yabai-move-on-error "west" #'windmove-left))

(defun yabai-window-right ()
  (interactive)
  (yabai-move-on-error "east" #'windmove-right))

(defun yabai-window-up ()
  (interactive)
  (yabai-move-on-error "north" #'windmove-up))

(defun yabai-window-down ()
  (interactive)
  (yabai-move-on-error "south" #'windmove-down))

These functions will attempt to move in a given direction, but if a user-error is signaled (meaning there’s no emacs window in that direction) a yabai movement command will be issued instead.

Emacs bindings

Finally, you can add in matching key bindings with global-set-key, or define-key, or map!, etc…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment