#+TITLE: Notes on Using Tmux

A collection of notes around how I (ab)use and configure tmux:
this is a live document, edited as I refine my workflows. 

This is not an introduction to tmux, but more a set of
workflows of using it. I assume a familiarity with what tmux is, and
perhaps that you already use it.

* Some Terms
I always find myself somewhat befuddled when reading the man page for
tmux; here's a list of the most important words:
- Sessions: different workspaces, generally identified by numbers
- Windows: one tab inside a session
- Panes: the parts of windows, each representing one shell instance

* Dual Wielding Tmuxes (tmuxen?)
I generally work in a shell on my laptop and as well as on development
servers; and occasionally multiple devservers. To reduce the number
of keyboard shortcuts I need to remember, I prefer to use a simple
Terminal Emulator and rely on Tmux to manage all state for me.

To be able to send share run commands with some sanity, I bind
Ctrl-b as my prefix-key for laptop tmux; and Ctrl-a as the prefix
for all devserver tmuxes.

In general this flow has worked out remarkably well for me: I only
need to remember one style of keyboard shortcuts to manipulate and add
terminals, and my sessions persist against X-server restarts.

The fact that tmux works as a very sane window-manager is a
significant bonus. I use dwm as my non-terminal window manager, and
things work out fairly smoothly.

* Emacs integration
I used to rely heavily on emamux to have a shell in parallel to my
emacs session, but that doesn't work from a graphical emacs session.

Instead, I've written my own custom snippet to run commands on the
last active tmux pane using tmux send-keys:

#+begin_src emacs-lisp
(setq tr--last-command nil)

(defun tr (command)
  "Run the specified command in the currently active tmux pane"
  (interactive "sCommand: ")
  (setq tr--last-command command)
  (call-process "tmux" nil nil nil "send-keys" command "Enter"))

(defun trr ()
  "Re-run the previous command"
  (interactive)
  (if tr--last-command
      (call-process "tmux" nil nil nil "send-keys" tr--last-command "Enter")
    (message "No available previous command!")))

(global-set-key (kbd "C-c x") 'tr)
(global-set-key (kbd "C-c r") 'trr)
#+end_src

It's fairly trivial, but remarkably speeds up iteration because I can
easily trigger tests, builds and other shenanigans without having to
navigate away from emacs: and I can use it in any scenario without
having to go through a complex set up process first.

* My current configuration
I've customized tmux a little bit to make it more convenient: it
started out as a direct copy from a blog post , and I've tweaked it
significantly over the years.

I'll only describe my additional customization:

** Mouse support
 Tmux has excellent mouse support: I've even used it to surprise my
 co-workers on occasion.

Round trip time was a little bit high while I was trying to resize a
pane -- so it looked more as if I wished something existed, and he
started laughing. A few seconds later it actually resized, and he was
astonished.

#+begin_src 
set-option -g mouse on
#+end_src

** Vim Bindings
As the title says: being able to use v in copy mode or / to search
forwards and ? to search backwards feels normal.

Similarly, using C-b h/j/k/l for navigating windows just works in my
head; to the point  I no longer consciously think about it. 

#+begin_src 
set -g status-keys vi
set -g mode-keys vi

# Better window navigation
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
#+end_src

** Minimalist UI
I prefer a line on the top with minimal formatting, including no
visible "-" and "|" in the separators.

#+begin_src 
# Custom status line
set-option -g status-left '-- #[fg=colour253]#S - '
set-window-option -g window-status-format '#[fg=colour244]#I/#[fg=colour253] #W '
set-window-option -g window-status-current-format '#[fg=colour244]#I/#[fg=colour253,bg=colour238] #W '
set-option -g status-right '#[fg=colour250] %Y-%m-%d #[fg=colour254]%H.%M'
set-option -g status-bg colour234
set-option -g status-fg colour007
set-option -g status-position top

# Custom split colours
set -g pane-active-border-style bg=colour234,fg=colour234
set -g pane-border-style bg=colour234,fg=colour234
#+end_src

file:../static/images/tmux.png

** Large scroll back
For me, one of tmux's super powers is to be able to scroll back
through output easily, particularly while looking at something with
fairly spammy logs and forgetting to pipe it through less , tee,or saving it
to a file. 

#+begin_src
# More scroll back!
set-option -g history-limit 10000
#+end_src

** Nicer colors
 To be perfectly honest I'm not sure if this is required anymore, but
 it did help emacs within tmux work better for me.
#+begin_src 
# Force 256 colours
set -g default-terminal screen-256color
#+end_src

** Always stay in the same directory
I believe I copied from this from Stack Overflow a few years ago: but
this lets me easily navigate splits without constantly having to
change directories.
#+begin_src 
# Maintain the current path
bind '%' split-window -h -c '#{pane_current_path}'  # Split panes horizontal
bind '"' split-window -v -c '#{pane_current_path}'  # Split panes vertically
bind c new-window -c '#{pane_current_path}' # Create new window
#+end_src

** Always renumber windows
Before using this option I would end up with windows going beyond 9,
which are a mess to navigate -- and then I'd end up closing several
windows and cleaning up my sessions.

With automatic renumbering my shortcuts stay consistent. This might
not be the best choice if you're a stickler about what goes into which
window -- I tend to do this opportunistically.

#+begin_src
set-option -g renumber-windows on
#+end_src

* The full configuration
#+begin_src 
# Stolen from http://mutelight.org/articles/practical-tmux
# and then heavily modified over the last several years.

# Make pbcopy and pbpaste work from tmux
# set-option -g default-command "reattach-to-user-namespace -l zsh"

# C-a C-a to jump to the last active window
bind-key C-b last-window

# Windows from 1
set -g base-index 1

# Resize based on smallest client actually active at the moment
setw -g aggressive-resize on

# Faster key repetition
set -s escape-time 0

# Mouse support!
set-option -g mouse on

# vi everywhere
set -g status-keys vi
set -g mode-keys vi

# Custom status line
set-option -g status-left '-- #[fg=colour253]#S - '
set-window-option -g window-status-format '#[fg=colour244]#I/#[fg=colour253] #W '
set-window-option -g window-status-current-format '#[fg=colour244]#I/#[fg=colour253,bg=colour238] #W '
set-option -g status-right '#[fg=colour250] %Y-%m-%d #[fg=colour254]%H.%M'
set-option -g status-bg colour234
set-option -g status-fg colour007
set-option -g status-position top

# Better window navigation
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# More scroll back!
set-option -g history-limit 10000

# Force 256 colours
set -g default-terminal screen-256color

# Custom split colours
set -g pane-active-border-style bg=colour234,fg=colour234
set -g pane-border-style bg=colour234,fg=colour234


# Maintain the current path
bind '%' split-window -h -c '#{pane_current_path}'  # Split panes horizontal
bind '"' split-window -v -c '#{pane_current_path}'  # Split panes vertically
bind c new-window -c '#{pane_current_path}' # Create new window

# Automatically fill holes
set-option -g renumber-windows on
#+end_src

* Frequently used, somewhat obscure commands

- Ctrl-b z: Zoom the current window: particularly useful for copying
  multi-line content.
  
- Ctrl-b space: Quickly toggle between window layouts.

- Ctrl-b : detach-clients -a: This one is useful to kill all other clients
  attached to the current session; good to clean up in case you got
  disconnected or have a terminal emulator lost in the labyrinth of
  your desktop window manager.

- Ctrl-b : kill-pane: Useful when things are truly, completely, absolutely
  FUBAR. I've used it in cases my shell has become completely
  unresponsive (and yes, I also double checked that I hadn't
  accidentally hit Ctrl-S / ran Ctrl-Q).

* References
- A tmux introduction
- My original source for configuring tmux
- man tmux: The reference for tmux.

* History
- 2020-07-07: First version.
- 2020-07-08: Fleshed it out a little.