My development stack is Neovim on tmux on mosh on kitty on GNOME on Fedora.
GNOME, tmux, and Neovim compose a nested set of windows and tabs. Kitty also provides tabs, but I don’t usually use them, since my tmux is remote and kitty’s tabs would be local.
Problem
I navigate between these layers directionally with these bindings:
-
GNOME:
super-hjkl
to switch desktop windows, thanks to the Focus changer extension. -
Neovim:
ctrl-hjkl
to switch Vim splits, andshift-hl
to switch buffer tabs. These bindings are from LazyVim, as a convenient alternative to the longerctrl-w hjkl
and:bn
/:bN
defaults, respectively. -
tmux:
ctrl-a np
to switch windows, andctrl-a hjkl
to switch panes.
I’m annoyed by the inefficiency of the three-key sequence to switch
windows in tmux, since it’s something that I do a lot, and the other layers have
simpler bindings. I’ve decided that super-np
would suit, since that modifier
is never used by TUI apps, because super
as a modifier doesn’t correspond to
any terminal codes.
Solution
Since super-n
and super-p
can’t be interpreted directly by terminal
programs, I need kitty to translate them. That looks like this in my
kitty config:
# .config/kitty/kitty.conf
map --when-focus-on title:tmux super+p send_text all \x01p
map --when-focus-on title:tmux super+n send_text all \x01n
map --when-focus-on title:tmux super+shift+p send_text all \x01P
map --when-focus-on title:tmux super+shift+n send_text all \x01N
When the window title contains tmux
then map super-n
to ctrl-a n
for the
next tab, likewise p
for the previous tab.
Also map super-shift-n
and super-shift-p
to rearrange tabs.
Here’s the corresponding config in my tmux config:
# .tmux.conf
set -g prefix C-a
unbind C-b
bind C-a send-prefix
bind n next
bind p prev
bind P swap-window -d -t -
bind N swap-window -d -t +
# Default setting with tmux: prepended for kitty to match.
set-option -g set-titles-string "tmux:#S:#I:#W - \"#T\" #{session_alerts}"
set-option -g set-titles on
Finally, I had to unbind super-n
and super-p
from their default
functions in GNOME, otherwise kitty doesn’t receive them. Those functions were
“Focus the current notification” and “Forget everything you know about my
carefully arranged monitors,” respectively. I decided I don’t need the former
(we’ll see if I assign a different key in the future), and nobody
wants the latter (it’s an unfortunate historical artifact from some Windows
laptop keyboards).
Getting rid of those:
gsettings set org.gnome.shell.keybindings focus-active-notification '[]'
gsettings set org.gnome.mutter.keybindings switch-monitor '["XF86Display"]'
Bonus
Tangentially, if you want kitty’s default binding of ctrl-shift-u
to show the
kitty Unicode picker,
you have to kill that GNOME binding, too. You can run ibus-setup
or this
one-liner:
dconf write /desktop/ibus/panel/emoji/unicode-hotkey '@as []'
Enjoy! ∿