//				vim: set syntax=asciidoc textwidth=75:
Managing Screens with tmux(1)
=============================
Holger Zuleger,  0.5, 30. April 2021  
:lang: en
include::{ldir}/attributes.adoc[]

== What is it?

tmux(1) is a replacement and enhancement of screen(1), a terminal multiplexer.
It allows multiple windows on a single terminal session to a Unix box.

The additional advantage is, that a local running server handle the state
of all sessions even if the terminal session to the Unix box is interrupted (detached).

To understand the basic concept of tmux, we have to understand and to
distinguish three different elements:

. Sessions
. Windows
. Panes

Starting a tmux client automatically connects to an already running tmux session
or creates a new one.
The session is numbered by default (starting at 0) or gets a name.
A tmux session has a (normally green) status line at the bottom of the screen.

Within a session, multiple windows can exist.
Every new window gets also a number (starting at 0 but this could/should be
changed) and can get additionally a name.
It's possible to switch between the windows by specifying the window
number (e.g. +\^B 1+ switches to window number 1) or rotate through the window
list with +\^B n+ (next window) or +^B p+ (previous window).

Each window can be split into two panes.
The split can be horizontal or vertical, and every pane can further divided
to another two panes.

The separator line between two panes can moved to left/right or up/down
respectively. By default the split takes place in the middle of the
window or pane.

                   +------- Screen   +----- Window
	           v                 |
	=============================v===================
	!+----------------------+----------------------+!
	!|                      |                      |!
	!|                      |                      |!
	!|                      |       Pane 2         |!
	!|                      |                      |!
	!|        Pane 1        +----------------------+!
	!|                      |                      |!
	!|                      |                      |!
	!|                      |       Pane 3         |!
	!|                      |                      |!
	!|                      |                      |!
	!+----------------------+----------------------+!
	![0] 1:bash 2:bash         host.ex.de. 23.04.21 ! <-- Status line
	==^==^=====================^===========^=========
	  |  |                     |           |
	  |  +-- Window list       |           +-- Date/Time
	  +-- Session Number/Name  +-- Hostname


== Start/Stop and attach/detach

To start a tmux (client) session run +tmux+.
The tmux server is started too if it's not already running.

The name of the session is just a simple number, or the name specified by
the option `-s`.  The name of the session we are connected to is shown at
the very beginning of the status line within brackets (+[1]+ or +[session-name]+).

* Start

 $ tmux				# start tmux and create a (unnamed) session
 $ tmux new -s <session-name>	# create new tmux session and name it "session-name"

 $ tmux ls	# Show all sessions plus the # of windows in each
  ^B s		# Roughly the same "within" tmux (with window "preview")

* Detach/Attach

Within a running tmux session you can detach from it with +^B d+

 ^B d		# detach from session

If your are attached (within) or unattached (outside) to a tmux session is
well indicated by a (usually green) status line at the bottom of the
screen.

You can re-attach to a session with the `tmux attach` command

 $ tmux attach [-t <session-name>]	# re-attach to target session

* Stop

 $ tmux kill-window
 	or
 $ exit			# exit the shell and therefore close the window

 $ tmux kill-session	# exit all windows and kill the server

When the last tmux session ends, the server is automatically stopped as
well.  This could changed with option `exit-empty` and/or `exit-unattached`.

== Windows

The current (active) window is marked with a star (+*+) in the status line.

Within +tmux+ almost all tmux related commands starts with a dedicated
``control'' key, also know as 'prefix'-key.
By default this is <Ctrl>B, written as +^B+ in the text.

* Manage Windows

  ^B c		# create new window
  ^B &		# kill window
  ^B ,		# rename window

* Move/Switch Window

  ^B w		# list all windows
  ^B 0|1..	# switch to window <x> (or mouse click in status line if "set mouse on")
  ^B n		# next window
  ^B p		# previous window
  ^B l		# toggle with the last active window (the one with a "-" in the status line)
  ^B w		# Choose a window (or session/pane) interactively
  ^B f <text>	# find a window which contains <text>

== Pane Options

Panes are the result of splitting a window horizontally or vertically.
A pane can be created within another pane recursively.

* Create/Resize new vertical pane

  ^B %		# split window vertical (left/right); create two panes
  ^B left/right # switch pane (bound to M-Left/M-Right too)
  ^B+left/right	# Resize pane (one char) (Don't work on OS/X)
  ^B+h/l	# Resize pane (5 chars) (see bind-key below)

* Create/Resize new horizontal pane

  ^B "		# split window horizontal (up/down); create two panes
  ^B up/down	# switch pane (bound to M-Up/M-Down too)
  ^B+up/down	# Resize pane (one line) (Don't work on OS/X)
  ^B+j/k	# Resize pane (5 lines) (see bind-key below)

* Destroy pane

  ^B x		# kill the active pane (Ask interactively)

* Move/Switch pane

  ^B o		# next pane
  ^B ;		# last (previously selected) pane
  ^B {		# swap the pane with the previous one
  ^B }		# swap the pane with the next pane

* Other pane related commands

  ^B q		# Show pane numbers
  ^B ^O		# Swap panes within a window

  ^B z		# zoom active pane (toggle) (See "Z" in status line)

  ^B M-1	# rearrange panes to even-horizontal layout
  ^B M-2	# rearrange panes to even-vertical layout
  ^B M-3	# rearrange panes to main-horizontal layout
  ^B M-4	# rearrange panes to main-vertical layout

.Main horizontal layout
 +----------------------------+
 |         Main               |
 |              Pane          |
 +-------------+--------------+
 |             |              |
 |             |              |
 |             |              |
 |             |              |
 +-------------+--------------+

The space in the main pane is defined with option +main-pane-height+.

.Main vertical layout
 +------------+--------------+
 |            |              |
 |            |              |
 |    Main    |              |
 |            +--------------+
 |    Pane    |              |
 |            |              |
 |            |              |
 +------------+--------------+

The space in the main pane is defined with option +main-pane-width+.

== Scroll Mode / Copy Buffer

Scroll mode is good to search or browse within the history buffer of a window or pane.
Text could marked and copied into several text buffers.
Later on, the content of a text buffer could be inserted in another window or
pane.

Within scroll mode the keys have a special meaning. The following
description is related to ++vi++-mode keys.

  setw -g mode-keys vi	# set vi editing commands

Scroll mode is not only good to browse within the history buffer, but also for
marking and copying text from it.

* Start scroll/copy mode and move the cursor around

  ^B [		# Start scroll/copy mode (bound to ^B PgUp too)

  Almost any (vi) movement commands

* Copy text into a buffer

  <Space>	# Begin selection (bound to (lower) 'v' too)
  <ESC>		# Cancel selection
  <Enter>	# End selection and insert selection into buffer
		# (bound to (lower) 'y' too)

* End scroll/copy mode

  q		# End scroll/copy mode
  ^B ]		# End copy mode and insert last selected buffer
  		# (bound to ^B P too

* Input/show buffers

  ^B #		# List all paste buffers
  ^B =		# Choose which buffer to paste

* Buffers and files

A (named) buffer could filled with the content of a file.  This can easily
used to paste the file content (use '-' for stdin) into a terminal session
(e.g. to put a predefined config snippet into a router).

	$ tmux load-buffer [-b bname] file

Similar commands are available to show the buffer content or to list all
buffers including their content (like +^B =+ within a pane).

	$ tmux show-buffer [-b name]
	$ tmux delete-buffer [-b name]
	$ tmux list-buffers

It's possible rename a buffer

	$ tmux set-buffer [-b bname] -n newname

If no buffer name is given the last used buffer is addressed.

I've written a small shell script to fill and show tmux buffers on the
command line (see https://www.hznet.de/unix/tbm.sh[tbm(1)]).

== tmux configuration file

To adapt tmux(1) a bit to the own preference put your tmux configuration
commands in +$HOME/.tmux.conf+.

	# add mouse support (questionable)
	set -g mouse on

	setw -g mode-keys vi
	setw -g status-keys vi

	# allow pane resizing via keystrokes
	# single char/line resizing is bound to C-Left/Right/Up/Down by default
	bind -r C-h resize-pane -L 10
	bind -r C-j resize-pane -D 5
	bind -r C-k resize-pane -U 5
	bind -r C-l resize-pane -R 10

	# Switch between panes using alt + arrow
	bind -T root M-Left select-pane -L
	bind -T root M-Right select-pane -R
	bind -T root M-Up select-pane -U
	bind -T root M-Down select-pane -D

	# toggle pane synchronization
	bind -T prefix C-s set-window-option synchronize-panes

	# search within scroll/copy mode
	bind -T root PPage copy-mode -eu	# use PgUp to start scrolling mode; ends automatically at buffer end
	bind -T prefix / copy-mode \; send-key ?	# Start search mode
	bind -T copy-mode-vi 'y' send -X copy-pipe-and-cancel "pbcopy"
	bind -T copy-mode-vi 'V' send -X select-line
	bind -T copy-mode-vi 'r' send -X rectangle-toggle
	bind -T prefix P paste-buffer			# same as ^B ]
	bind -T prefix C-f command-prompt -p "(load-buffer) filename:" "load-buffer -b filebuffer %%"
	bind -T prefix C-p paste-buffer -b filebuffer

	# For non C-Programmer: make the first window number start at 1
	# (Helpful for C-Programmers too, because the 1,2,3,... keys
	# 			are more close together than 0,1,2... )
	set -g base-index 1

	# add weather report to status line (`weather` is a shell script)
	set-option -g status-interval 60
	set-option -g status-right-length 65
	set-option -g status-right-style "bg=green,fg=black"
	set-option -ag status-right "#[bg=colour22 fg=white]#(weather -s -n)#[bg=default fg=default]"

	# A dark green background for the active window
	%if "#{m:*3*,#{version},r}"
	  set-option -g window-status-current-style "bg=colour28,fg=white"
	%else
	  set-option -g window-status-current-bg colour28
	%endif

Reread the configuration file after you made changes with

	$ tmux source ~/.tmux.conf

== tmux Options

* Show current sessions

	$ tmux ls
	$ tmux list-sessions

* Show current window list (including the # of panes)

	$ tmux list-windows

* Show current client list

	$ tmux list-clients

* Show all buffers

	$ tmux list-buffers

* Show current key bindings

	$ tmux list-keys

* Show current option settings

	$ tmux show-options -g 

* Show all available tmux commands

	$ tmux list-commands

* Show all terminfo options

	$ tmux info



== Miscellaneous

* Enter command-line mode

 ^B :	# goto command line mode

* Shows a large clock on the screen

  $ tmux clock-mode

== Alternatives

* screen is a predecessor of tmux
* https://zellij.dev/[zellij] is potentially a tmux successor written in
  Rust

