tmux mit vim und 80 Columns Breite im Split-Layout
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 anpassenAlt+c: Pane schließen und Layout wieder anpassenAlt+j,Alt+k: Die Panes im bzw. gegen den Uhrzeigersinn rotierenAlt+Enter: Die aktuell ausgewählte Pane auf Position 0 schiebenAlt+r: Das Layout wieder anpassen, falls es durcheinander geraten ist (etwa weil man die Shell mitCtrl+dgeschlossen 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:
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
viminstallieren (Doku dazu jeweils bei GitHub) - tmuxline im
viminstallieren und einmalig mit:TmuxlineSnapshot $HOME/.tmuxcolors.confdie Farben ins Heimverzeichnis schreiben lassen - In der
$HOME/.tmux.confnoch 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.