Ich verwende gern tmux mit vim und einigen Terminals nebeneinander. Dabei gefällt mir das folgende Layout am besten:

+-----------------------------------+------------------+
|                                   |  Pane 1          |
|    Pane 0                         |  bash            |
|    VIM                            |  80 chars        |
|    Alles minus 80 Chars           |                  |
|                                   +------------------+
|                                   |  Pane 2          |
|                                   |  bash            |
|                                   |  80 chars        |
|                                   |                  |
|                                   +------------------+
|                                   |  Pane 3          |
|                                   |  bash            |
|                                   |  80 chars        |
|                                   |                  |
+-----------------------------------+------------------+

Das Vollbild-Terminal ist in mehrere tmux-Panes eingeteilt: Ein Haupt-Pane, in dem der Editor läuft (und da seine eigenen Splits macht) und mehrere kleinere Panes, in denen jeweils eine Shell läuft, in der dann SSH, Git oder sonst was passiert. Diese sollen bitte die standardmäßigen 80 Zeichen breit sein. Deren Anzahl steigt und fällt je nach Bedarf. Wenn ein Terminal mal in voller Größe gebraucht wird, um breite Diffs anzuzeigen oder bei anderen Dingen mit Platzbedarf, kann in das Terminal hinein gezoomt werden.

Weil das natürlich niemand von Hand immer auf die richtige Größe ziehen will, vor allem wenn man am Laptop arbeitet und der verschieden große Monitore (HD, 1440p) nochmal angesteckt haben kann, muss man das Anpassen der Breite natürlich automatisieren Zwischen den Splits in vim und den Panes in tmux kann ich mit Hilfe von Ctrl-hjkl navigieren.

Damit das alles auch farblich schön zusammen passt, passt sich die Statuszeile von tmux automatisch dem Farbschema von vim (mit dem airline-Plugin) an.

Automatisch die Breite anpassen

Leider hat tmux keine eingebaute Funktion zur Festsetzung der Breite einer Pane auf eine Anzahl von Columns (d.h. Zeichen), nur Prozente. Ein Shellscript hilft bei der Berechnung der Differenz zu den gewünschten 80 Zeichen:

$HOME/.local/bin/sizetmux.sh, adaptiert von StackOverflow:

#!/bin/bash

WANTED=80

CURRENT=$(tmux list-panes | awk -F"[ x:\\\[\\\]]+" '/^1:/{print $2}')
if [[ "${CURRENT}" -gt "${WANTED}" ]];
then
    ((DIFFERENCE = "${CURRENT}" - "${WANTED}"))
    tmux resize-pane -R -t 1 "${DIFFERENCE}"
elif [[ "${CURRENT}" -lt "${WANTED}" ]];
then
    ((DIFFERENCE = "${WANTED}" -"${CURRENT}"))
    tmux resize-pane -L -t 1 "${DIFFERENCE}"
fi

Das Script ist relativ einfach: Ist Pane 1 breiter als 80 Zeichen, wird sie um die Differenz verkleinert, sonst vergrößert, bei 80 Zeichen passiert nichts. Es reicht hier, Pane 1 zu verändern - die Breite von Pane 0 ergibt sich aus der Differenz zur Bildschirmbreite und alle weiteren Panes sind gleich breit wie Pane 1.

$HOME/.tmux.conf (Auszug)

# Create new pane in current directory
bind -n M-n split-window -t :.0 -c "#{pane_current_path}" \;\
        swap-pane -s :.0 -t :.1 \;\
        select-layout main-vertical \;\
        run "~/sizetmux.sh"

# Kill pane
bind -n M-c kill-pane -t :. \;\
        select-layout main-vertical \;\
        run "~/sizetmux.sh" \;\
        select-pane -t :.+

# Rotate counterclockwise
bind -n M-j rotate-window -U \; select-pane -t 0

# Rotate clockwise
bind -n M-k rotate-window -D \; select-pane -t 0

# Focus selected pane
bind -n M-Enter swap-pane -s :. -t :.0 \; select-pane -t :.0

# Refresh layout
bind -n M-r select-layout main-vertical \;\
        run "~/sizetmux.sh"

Daraus ergeben sich dann die Tastenkombinationen, mit denen das oben beschriebene Layout hergestellt wird:

  • Alt+n: weitere Pane öffnen und Layout anpassen
  • Alt+c: Pane schließen und Layout wieder anpassen
  • Alt+j, Alt+k: Die Panes im bzw. gegen den Uhrzeigersinn rotieren
  • Alt+Enter: Die aktuell ausgewählte Pane auf Position 0 schieben
  • Alt+r: Das Layout wieder anpassen, falls es durcheinander geraten ist (etwa weil man die Shell mit Ctrl+d geschlossen hat

Außerdem gelten die normalen Shortcuts von tmux weiter: die zum Wechseln der aktuell fokussierten Pane und auch Ctrl+b z, bei der eine Pane auf ganzer Höhe und Breite des Terminals angezeigt wird.

vim-Integration: Navigation

Damit es sich möglichst uniform anfühlt, habe ich mir die Tastenkombinationen zum Wechseln zwischen Splits im vim-Fenster und tmux-Panes angeglichen und mit einem Script für vim integriert:

vim-tmux-navigator

Weil tmux per default nicht die gleichen Buchstaben bei den Tastenkombinationen verwendet wie vim, habe ich das auch noch in der .tmux.conf angeglichen. Die Buchstaben von vim machen ohnehin mehr Sinn.

$HOME/.tmux.conf (Auszug)

is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
    | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind-key -n C-H if-shell "$is_vim" "send-keys C-h"  "select-pane -L"
bind-key -n C-J if-shell "$is_vim" "send-keys C-j"  "select-pane -D"
bind-key -n C-K if-shell "$is_vim" "send-keys C-k"  "select-pane -U"
bind-key -n C-L if-shell "$is_vim" "send-keys C-l"  "select-pane -R"
bind-key -n C-\ if-shell "$is_vim" "send-keys C-\\" "select-pane -l"

Ab dann gelten also die Navigation Ctrl + Richtung sowohl in vim als auch in tmux

vim und tmux optisch angleichen: statusline

In meinem vim verwende ich airline um eine hübsche Leiste zu haben, passend zu meinem restlichen Theme auch mit solarized-Design. Um das gleiche Design auch mit tmux zu bekommen, sind drei Dinge notwendig:

  • airline und airline-themes im vim installieren (Doku dazu jeweils bei GitHub)
  • tmuxline im vim installieren und einmalig mit :TmuxlineSnapshot $HOME/.tmuxcolors.conf die Farben ins Heimverzeichnis schreiben lassen
  • In der $HOME/.tmux.conf noch oben einfügen: source-file $HOME/.tmuxcolors.conf

Startet man jetzt tmux und darin vim neu, sollte man jeweils die gleiche (nicht die selbe!) Statuszeile vorfinden.