Home

Simulating macOS Terminal Keybindings in Alacritty using tmux

In ~/.alacritty.yml, add the following in key_bindings alongside the default macOS bindings:

key_bindings:
  # New tab.
  - { key: T,        mods: Command,       chars: "\x01\x63" }

  # Close tab.
  - { key: W,        mods: Command,       chars: "\x01\x64" }

  # Move one tab right.
  - { key: RBracket, mods: Command|Shift, chars: "\x01\x6e" }

  # Move one tab left.
  - { key: LBracket, mods: Command|Shift, chars: "\x01\x70" }

  # Move to tab x.
  - { key: Key1,     mods: Command,       chars: "\x01\x31" }
  - { key: Key2,     mods: Command,       chars: "\x01\x32" }
  - { key: Key3,     mods: Command,       chars: "\x01\x33" }
  - { key: Key4,     mods: Command,       chars: "\x01\x34" }
  - { key: Key5,     mods: Command,       chars: "\x01\x35" }
  - { key: Key6,     mods: Command,       chars: "\x01\x36" }
  - { key: Key7,     mods: Command,       chars: "\x01\x37" }
  - { key: Key8,     mods: Command,       chars: "\x01\x38" }
  - { key: Key9,     mods: Command,       chars: "\x01\x39" }

Note: this assumes C-a for the tmux prefix. Use "\x02..." for C-b, or see below for others.

This takes care of most bindings as-is, using the default tmux configuration. The only one a bit more tricky to get right is ⌘W. The default binding of C-a x in tmux is close, but always requests a confirmation before closing panes/windows (even if there’s no active process), and moves to the most recently active window rather than simply one to the right as Terminal does. To get this right requires a custom binding and a short script.

First, in tmux.conf add:

bind-key d run-shell "~/.config/tmux/sh/smart-kill-pane”

Then place the following in ~/.config/tmux/sh/smart-kill-pane (or wherever you like), and make sure to mark it as executable:

#!/bin/sh
#
# Smart confirm-before kill-pane command. Only asks for confirmation when
# killing a child process.
set -o errexit -o nounset

tmux_run() (
    pane_pid="$(tmux list-panes -F "#{pane_active}:#{pane_pid}" |
        grep '^1:' |
        cut -c 3-)"
    escaped_cmd="$(echo "$*" | sed 's/;/\\\;/g')"
    if pgrep -P "$pane_pid" >/dev/null; then
        tmux confirm-before -p "kill-pane #P? (y/n)" "run 'tmux $escaped_cmd'"
    else
        tmux "$@"
    fi
)

main() (
    window_list="$(tmux list-windows -F '#{window_active}:#{window_panes}')"
    window_count="$(tmux display-message -p '#{session_windows}')"
    pane_count="$(echo "$window_list" |
        grep '^1:' |
        cut -c 3-)"

    # Mimic Terminal.app's behavior of always moving one tab to the right
    # unless at the end.
    if [ ! "$pane_count" = 1 ] || [ "$window_count" = 1 ]; then
        tmux_run kill-pane
    elif [ "$(echo "$window_list" | tail -n1 | cut -c1)" = 1 ]; then
        tmux_run previous-window\; next-window\; kill-pane
    else
        tmux_run next-window\; previous-window\; kill-pane
    fi
)

main

🔗Explanation

The hex codes listed in the chars field were generated via the xxd -psd command as shown in the following:

$ xxd -psd
^Ac
01630a

This corresponds to:

01 => C-a
63 => c
0a => return

More information can be found in the article listed below.

My full tmux config with a working example is available here.

🔗Resources: