config.phundrak.com/docs/tmux.org

292 lines
11 KiB
Org Mode
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#+title: Tmux
#+setupfile: headers
#+property: header-args:tmux :mkdirp yes :lexical t :exports code
#+property: header-args:tmux+ :tangle ~/.config/tmux/tmux.conf
#+property: header-args:tmux+ :mkdirp yes :noweb yes
* Tmux
Tmux is one of the widest known terminal multiplexers along with
=screen=. I find it useful when I dont want to bother with panes in my
[[https://sw.kovidgoyal.net/kitty/][kitty]] terminal.
Be aware this configuration is mostly keybinds.
** Setting sane configurations
By default, Tmux does not support all the colours your terminal may
support, so we need to tell it to set true colours..
#+begin_src tmux
set-option -sa terminal-overrides ",xterm*:Tc"
#+end_src
We can also tell it to enable mouse support. That way, we will be able
to click on Tmux elements and scroll in its panes!
#+begin_src tmux
set -g mouse on
#+end_src
Finally, Ill set ~vi-mode~ for some sane movements.
#+begin_src tmux
set-window-option -g mode-keys vi
#+end_src
** Windows and panes configuration
Although I agree in computer science most things should begin with
zero, I find it quite weird to see my first window and my first pane
to be labelled with it rather than one. So, lets pull a Lua on Tmux
and force it to begin with 1 instead of 0.
#+begin_src tmux
set -g base-index 1
set -g pane-base-index 1
set-window-option -g pane-base-index 1
set-option -g renumber-windows on
#+end_src
** Plugins!
Using [[https://github.com/tmux-plugins/tpm][TPM]], we can use plugins in Tmux! The way I installed it is very simple:
#+begin_src bash
mkdir -p ~/.config/tmux/
git clone https://github.com/tmux-plugins/tpm.git ~/.config/tmux/tpm
#+end_src
Heres a list of the plugins that I use.
#+name: plugins
| Plugin | Why |
|-----------------------+------------------------------------------------------|
| tpm | TPM itself |
| tmux-sensible | Better defaults I cant be bothered to change myself |
| tmux-yank | Better copy/pasting |
| tmux-prefix-highlight | Tell me which prefix Im using |
| tmux-resurrect | Persist tmux sessions across system restarts |
| nordtheme/tmux | Nord theme for Tmux! |
#+begin_src emacs-lisp :var plugins=plugins[,0] :exports code :wrap src tmux
(mapconcat (lambda (plugin)
(format "set -g @plugin '%s'"
(if (string-match-p (quote "/") plugin)
plugin
(concat "tmux-plugins/" plugin))))
plugins
"\n")
#+end_src
#+RESULTS:
#+begin_src tmux
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-yank'
set -g @plugin 'tmux-plugins/tmux-prefix-highlight'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'nordtheme/tmux'
#+end_src
Lets run TPM right after that.
#+begin_src tmux
run '~/.config/tmux/tpm/tpm'
#+end_src
For restoring processes with =tmux-resurrect=, we must add additional
programs in the =@resurrect-processes= variable. These are:
#+name: resurrect-processes-list
- ="~ncmpcpp -q"=
- =btop=
- =ssh=
#+name: resurrect-processes
#+begin_src emacs-lisp :var processes=resurrect-processes-list :exports none :cache yes
(mapconcat (lambda (process) (string-replace "=" "" process))
processes
" ")
#+end_src
#+RESULTS[4f72312f2da98c81eff2b092779a59c993fa19e2]: resurrect-processes
: "~ncmpcpp -q" btop ssh
#+begin_src tmux :noweb yes
set -g @resurrect-processes '<<resurrect-processes()>>'
#+end_src
** Keybindings
Firstly, I dont like prefixing all of my keybindings with ~C-b~, thats
what I use in ~insert-mode~ in Emacs to make the cursor go back. So
instead, lets set meta with space as my prefix.
#+begin_src tmux
unbind C-b
set -g prefix M-Space
bind M-Space send-prefix
#+end_src
Now, I will only add few keybindings on the root prefix that actually
do something immediately, I will mostly add keybindings that will lead
to other prefixes; I prefer by far to have keychords that are a bit
lengthy and mnemonic than some obscure “ ~C-M-&~ is for doing this and
that”.
#+name: std-prefix
| Keybinding | Command | Prefix to go to |
|------------+------------------+-----------------|
| =«= | select-window -p | |
| =»= | select-window -n | |
| =Tab= | | windows |
| =w= | | pane |
| =y= | | copy-mode |
Note I am using the key =w= to access the pane prefix because of how
used to Emacs I am, and in Emacs terminology panes are windows while
tmux windows would be tabs.
#+name: gen-keybinds
#+begin_src emacs-lisp :var keybinds=std-prefix :var prefix="prefix" :exports none
(mapconcat (lambda (keybind)
(format "bind-key -T %s %s %s"
prefix
(string-replace "=" "" (car keybind))
(let* ((command (nth 1 keybind))
(command (if (string= "" command) nil command))
(goto-prefix (nth 2 keybind))
(goto-prefix (if (or (null goto-prefix)
(string= "" goto-prefix))
nil
(concat "switch-client -T " goto-prefix))))
(if (and command goto-prefix)
(concat command "\\; " goto-prefix)
(or command goto-prefix)))))
keybinds
"\n")
#+end_src
#+RESULTS[3e58a076aacba87d1cca87db849460e4c2414e94]: gen-keybinds
: bind-key -T prefix « select-window -p
: bind-key -T prefix » select-window -n
: bind-key -T prefix Tab switch-client -T windows
: bind-key -T prefix w switch-client -T pane
: bind-key -T prefix y switch-client -T copy-mode
#+begin_src tmux
<<gen-keybinds()>>
#+end_src
*** Panes
As you will see not only here but also lower, I am not using the usual
=hjkl= to navigate around since I am using the [[https://bepo.fr][bépo]] layout. I use
instead the =ctsr= keys.
Below are the keybindings living in the =pane= prefix. Note that calls to
=split-window= have a =-c "#{pane_current_path}"= argument so new panes
open in the same directory as the directory I am currently in.
#+name: pane-prefix
| Keybinding | Command | Prefix to go to |
|------------+-------------------------------------------+-----------------|
| =/= | split-window -h -c "#{pane-current_path}" | |
| =-= | split-window -v -c "#{pane-current_path}" | |
| =c= | select-pane -L | |
| =t= | select-pane -D | |
| =s= | select-pane -U | |
| =r= | select-pane -R | |
| =f= | resize-pane -Z | |
| =.= | | pane-resize |
#+begin_src tmux
<<gen-keybinds(keybinds=pane-prefix, prefix="pane")>>
#+end_src
When it comes to resizing the panes, the keybindings are in their own
prefix referenced above: =pane-resize=. All keybindings will lead to the
same prefix again, which enables the user to type for instance =M-Space
w . r r r r r= in order to call repetitively =resize-pane -R 5=. Hitting
any key that is not part of the current prefix will get us out of it.
#+name: pane-resize-prefix
| Keybinding | Command | Prefix to go to |
|------------+------------------+-----------------|
| c | resize-pane -L 5 | pane-resize |
| t | resize-pane -D 5 | pane-resize |
| s | resize-pane -U 5 | pane-resize |
| r | resize-pane -R 5 | pane-resize |
| C | resize-pane -L | pane-resize |
| T | resize-pane -D | pane-resize |
| S | resize-pane -U | pane-resize |
| R | resize-pane -R | pane-resize |
#+begin_src tmux
<<gen-keybinds(keybinds=pane-resize-prefix, prefix="pane-resize")>>
#+end_src
*** Windows
Since windows are more akin to tabs in Emacs, and I am way more used
to it than Tmux, all keybinds are prefixed with a =Tab=, itself prefixed
with the main prefix.
#+name: windows-prefix
| Keybinding | Command |
|------------+-----------------|
| c | new-window |
| n | next-window |
| p | previous-window |
#+begin_src tmux
<<gen-keybinds(keybinds=windows-prefix, prefix="windows")>>
#+end_src
In order to access more easily the different windows, I want to be
able to type =<prefix> TAB <window number>=. However, Im using the bépo
layout, numbers are available only when pressing shift. Otherwise, the
characters typed are ="«»()@+-/*= (from 1 to 0).
#+begin_src emacs-lisp :wrap src tmux :exports code
(let ((keybinds "")
(keys '("\\\"" "«" "»" "(" ")" "@" "+" "-" "/" "*")))
(dotimes (i (length keys) keybinds)
(setq keybinds (string-trim
(concat keybinds
"\n"
(format "bind-key -T windows %s select-window -t :=%d"
(nth i keys)
(1+ i)))))))
#+end_src
#+RESULTS:
#+begin_src tmux
bind-key -T windows \" select-window -t :=1
bind-key -T windows « select-window -t :=2
bind-key -T windows » select-window -t :=3
bind-key -T windows ( select-window -t :=4
bind-key -T windows ) select-window -t :=5
bind-key -T windows @ select-window -t :=6
bind-key -T windows + select-window -t :=7
bind-key -T windows - select-window -t :=8
bind-key -T windows / select-window -t :=9
bind-key -T windows * select-window -t :=10
#+end_src
*** Copy in vi mode
Tmux has a nice mode for vim keybindings users: =copy-mode-vi= which
allows moving the cursor around in the pane, select some stuff, and
copy it. But first, I need to unbind some keys:
#+begin_src tmux
unbind -T copy-mode-vi H
unbind -T copy-mode-vi J
unbind -T copy-mode-vi K
unbind -T copy-mode-vi L
unbind -T copy-mode-vi h
unbind -T copy-mode-vi j
unbind -T copy-mode-vi k
unbind -T copy-mode-vi l
#+end_src
#+name: copy-mode-vi-prefix
| Keybinding | Command |
|------------+----------------------------------------|
| v | send-keys -X begin-selection |
| C-v | send-keys -X rectangle-toggle |
| y | send-keys -X copy-selection-and-cancel |
| C | send-keys -X top-line |
| J | send-keys -X jump-to-backward |
| S | send-keys -X scroll-up |
| R | send-keys -X bottom-line |
| T | send-keys -X scroll-down |
| c | send-keys -X cursor-left |
| t | send-keys -X cursor-down |
| s | send-keys -X cursor-up |
| r | send-keys -X cursor-right |
#+begin_src tmux
<<gen-keybinds(keybinds=copy-mode-vi-prefix, prefix="copy-mode-vi")>>
#+end_src