FREE THOUGHT · FREE SOFTWARE · FREE WORLD

TMUX

TMUX == GNU Screen x 2.. here is a screenshot from my Arch Linux ThinkPenguin.com laptop back in 2014. That bg image, taken from the International Space Station is now one of my favorite grub boot bg images.

penguin-tmux

tmux usage

archlinux-on-mac

Note: This is primarily an article of my notes taken from reading the tmux source code. I'll add some good practical usage another time perhaps.

usage: %s [-2lquvV] [-c shell-command] [-f file] [-L socket-name] [-S socket-path] [command [flags]]

tmux.conf

Per my usual habit, I downloaded the tmux source code and poured over it for weeks. The purpose of that wasn't abstract, I work to find and build systems that once built will enable and empower my computing for a long time. In this case, for me that meant building a super optimized and understood tmux.conf -- here is the one I am using at the moment. tmux.conf

Tmux Command Aliases

grep -h 'const struct cmd_entry' -A1 cmd-*.c|nobb|grep -v '^const'|grep -v '^\-\-'|trs|nobb| sed 's,^"\([^"]\+\)"\, *"\([^"]\+\)"..*$,\2:<li><strong>\2</strong>: \1</li>,g'|grep -v NULL|sort -g|cut -d':' -f2-
  • attach: attach-session
  • bind: bind-key
  • breakp: break-pane
  • capturep: capture-pane
  • clearhist: clear-history
  • confirm: confirm-before
  • deleteb: delete-buffer
  • detach: detach-client
  • display: display-message
  • displayp: display-panes
  • findw: find-window
  • has: has-session
  • if: if-shell
  • joinp: join-pane
  • killp: kill-pane
  • killw: kill-window
  • last: last-window
  • lastp: last-pane
  • linkw: link-window
  • loadb: load-buffer
  • lock: lock-server
  • lockc: lock-client
  • locks: lock-session
  • ls: list-sessions
  • lsb: list-buffers
  • lsc: list-clients
  • lscm: list-commands
  • lsk: list-keys
  • lsp: list-panes
  • lsw: list-windows
  • movep: move-pane
  • movew: move-window
  • new: new-session
  • neww: new-window
  • next: next-window
  • nextl: next-layout
  • pasteb: paste-buffer
  • pipep: pipe-pane
  • prev: previous-window
  • prevl: previous-layout
  • refresh: refresh-client
  • rename: rename-session
  • renamew: rename-window
  • resizep: resize-pane
  • respawnp: respawn-pane
  • respawnw: respawn-window
  • rotatew: rotate-window
  • run: run-shell
  • saveb: save-buffer
  • selectl: select-layout
  • selectp: select-pane
  • selectw: select-window
  • send: send-keys
  • set: set-option
  • setb: set-buffer
  • setenv: set-environment
  • setw: set-window-option
  • show: show-options
  • showb: show-buffer
  • showenv: show-environment
  • showmsgs: show-messages
  • showw: show-window-options
  • source: source-file
  • splitw: split-window
  • start: start-server
  • suspendc: suspend-client
  • swapp: swap-pane
  • swapw: swap-window
  • switchc: switch-client
  • unbind: unbind-key
  • unlinkw: unlink-window
  • wait: wait-for
  • info: server-info

Default Templates

CHOOSE_BUFFER_TEMPLATE
Default template for choose-buffer.
"#{line}: #{buffer_size} bytes: #{buffer_sample}"
CHOOSE_CLIENT_TEMPLATE
Default template for choose-client.
"#{client_tty}: #{session_name} [#{client_width}x#{client_height} #{client_termname}]#{?client_utf8, (utf8),}#{?client_readonly, (ro),} (last used #{client_activity_string})"
CHOOSE_TREE_SESSION_TEMPLATE
Default templates for choose-tree.
"#{session_name}: #{session_windows} windows#{?session_grouped, (group ,}#{session_group}#{?session_grouped,),}#{?session_attached, (attached),}"
CHOOSE_TREE_WINDOW_TEMPLATE
"#{window_index}: #{window_name}#{window_flags} \"#{pane_title}\""
DISPLAY_MESSAGE_TEMPLATE
Default template for display-message.
"[#{session_name}] #{window_index}:#{window_name}, current pane #{pane_index} - (%H:%M %d-%b-%y)"
FIND_WINDOW_TEMPLATE
Default template for find-window.
"#{window_index}: #{window_name} [#{window_width}x#{window_height}] (#{window_panes} panes) #{window_find_matches}"
LIST_BUFFERS_TEMPLATE
Default template for list-buffers.
"#{line}: #{buffer_size} bytes: \"#{buffer_sample}\""
LIST_CLIENTS_TEMPLATE
Default template for list-clients.
"#{client_tty}: #{session_name} [#{client_width}x#{client_height} #{client_termname}]#{?client_utf8, (utf8),} #{?client_readonly, (ro),}"
LIST_SESSIONS_TEMPLATE
Default template for list-sessions.
"#{session_name}: #{session_windows} windows (created #{session_created_string}) [#{session_width}x#{session_height}]#{?session_grouped, (group ,}#{session_group}#{?session_grouped,),}#{?session_attached, (attached),}"
LIST_WINDOWS_TEMPLATE
Default templates for list-windows.
"#{window_index}: #{window_name}#{window_flags} (#{window_panes} panes) [#{window_width}x#{window_height}] [layout #{window_layout}] #{window_id}#{?window_active, (active),}"
LIST_WINDOWS_WITH_SESSION_TEMPLATE
"#{session_name}:#{window_index}: #{window_name}#{window_flags} (#{window_panes} panes) [#{window_width}x#{window_height}] "
NEW_SESSION_TEMPLATE
"#{session_name}:"
BREAK_PANE_TEMPLATE
"#{session_name}:#{window_index}.#{pane_index}"
NEW_WINDOW_TEMPLATE
"#{session_name}:#{window_index}.#{pane_index}"
SPLIT_WINDOW_TEMPLATE
"#{session_name}:#{window_index}.#{pane_index}"

tmux main() processing order:

struct options   global_options;  /* server options */
struct options   global_s_options;  /* session options */
struct options   global_w_options;  /* window options */
struct environ   global_environ;
  1. Parse cmd line options while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1)
  2. Setup global environment for (var = environ; *var != NULL; var++) environ_put(&global_environ, *var);
  3. Set PWD if (getcwd(tmp, sizeof tmp) != NULL) environ_set(&global_environ, "PWD", tmp);
  4. Populate Server Options options_table_populate_tree(server_options_table, &global_options)
  5. Populate Session Options options_table_populate_tree(session_options_table, &global_s_options);
  6. Set default-shell in global session option to the current shell options_set_string(&global_s_options, "default-shell", "%s", getshell());
  7. Populate Window Options options_table_populate_tree(window_options_table, &global_w_options);
  8. Enable UTF-8 if first client is on UTF-8 terminal
    if (flags & CLIENT_UTF8) {
      options_set_number(&global_s_options, "status-utf8", 1);
      options_set_number(&global_s_options, "mouse-utf8", 1);
      options_set_number(&global_w_options, "utf8", 1);
    }
  9. Override keys to vi if VISUAL or EDITOR are set
    if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) {
      if (strrchr(s, '/') != NULL) s = strrchr(s, '/') + 1;
      if (strstr(s, "vi") != NULL) keys = MODEKEY_VI;
      else keys = MODEKEY_EMACS;
      options_set_number(&global_s_options, "status-keys", keys);
      options_set_number(&global_w_options, "mode-keys", keys);
    }
  10. Locate the configuration file.
  11. Get path from environment
    s = getenv("TMUX");
    if (s != NULL && sscanf(s, "%255[^,],%lld,%d", in, &pid, &session) == 3) environ_path = xstrdup(in);
  12. Figure out the socket path and use.
  13. Set process title. #ifdef HAVE_SETPROCTITLE setproctitle("%s (%s)", __progname, socket_path);
  14. Pass control to the client
    ev_base = osdep_event_init();
    exit(client_main(argc, argv, flags));

tmux.c

makesocketpath

makesocketpath sets the socketpath in this order.

  1. TMUX_TMPDIR
  2. TMPDIR
char *
makesocketpath(const char *label)
{
    char        base[MAXPATHLEN], realbase[MAXPATHLEN], *path, *s;
    struct stat sb;
    u_int       uid;

    uid = getuid();
    if ((s = getenv("TMUX_TMPDIR")) != NULL && *s != '\0')
        xsnprintf(base, sizeof base, "%s/", s);
    else if ((s = getenv("TMPDIR")) != NULL && *s != '\0')
        xsnprintf(base, sizeof base, "%s/tmux-%u", s, uid);
    else
        xsnprintf(base, sizeof base, "%s/tmux-%u", _PATH_TMP, uid);

    if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST)
        return (NULL);

    if (lstat(base, &sb) != 0)
        return (NULL);
    if (!S_ISDIR(sb.st_mode)) {
        errno = ENOTDIR;
        return (NULL);
    }
    if (sb.st_uid != uid || (!S_ISDIR(sb.st_mode) &&
        sb.st_mode & (S_IRWXG|S_IRWXO)) != 0) {
        errno = EACCES;
        return (NULL);
    }

    if (realpath(base, realbase) == NULL)
        strlcpy(realbase, base, sizeof realbase);

    xasprintf(&path, "%s/%s", realbase, label);
    return (path);
}

shell_exec

__dead void
shell_exec(const char *shell, const char *shellcmd)
{
    const char  *shellname, *ptr;
    char        *argv0;

    ptr = strrchr(shell, '/');
    if (ptr != NULL && *(ptr + 1) != '\0')
        shellname = ptr + 1;
    else
        shellname = shell;
    if (login_shell)
        xasprintf(&argv0, "-%s", shellname);
    else
        xasprintf(&argv0, "%s", shellname);
    setenv("SHELL", shell, 1);

    setblocking(STDIN_FILENO, 1);
    setblocking(STDOUT_FILENO, 1);
    setblocking(STDERR_FILENO, 1);
    closefrom(STDERR_FILENO + 1);

    execl(shell, argv0, "-c", shellcmd, (char *) NULL);
    fatal("execl failed");
}

tmux.h

extern struct options global_options;
extern struct options global_s_options;
extern struct options global_w_options;
extern struct environ global_environ;

notify.c

void  notify_enable(void);
void  notify_disable(void);
void  notify_input(struct window_pane *, struct evbuffer *);
void  notify_window_layout_changed(struct window *);
void  notify_window_unlinked(struct session *, struct window *);
void  notify_window_linked(struct session *, struct window *);
void  notify_window_renamed(struct window *);
void  notify_attached_session_changed(struct client *);
void  notify_session_renamed(struct session *);
void  notify_session_created(struct session *);
void  notify_session_closed(struct session *);

options-table.c

extern const struct options_table_entry server_options_table[];
extern const struct options_table_entry session_options_table[];
extern const struct options_table_entry window_options_table[];

Default Templates

key codes

/* Special key codes. */
#define KEYC_NONE 0xfff
#define KEYC_BASE 0x1000

/* Key modifier bits. */
#define KEYC_ESCAPE 0x2000
#define KEYC_CTRL 0x4000
#define KEYC_SHIFT 0x8000
#define KEYC_PREFIX 0x10000

/* Mask to obtain key w/o modifiers. */
#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT|KEYC_PREFIX)
#define KEYC_MASK_KEY (~KEYC_MASK_MOD)

/* Other key codes. */
enum key_code {
  /* Mouse key. */
  KEYC_MOUSE = KEYC_BASE,

  /* Backspace key. */
  KEYC_BSPACE,

  /* Function keys. */
  KEYC_F1,
  KEYC_F2,
  KEYC_F3,
  KEYC_F4,
  KEYC_F5,
  KEYC_F6,
  KEYC_F7,
  KEYC_F8,
  KEYC_F9,
  KEYC_F10,
  KEYC_F11,
  KEYC_F12,
  KEYC_F13,
  KEYC_F14,
  KEYC_F15,
  KEYC_F16,
  KEYC_F17,
  KEYC_F18,
  KEYC_F19,
  KEYC_F20,
  KEYC_IC,
  KEYC_DC,
  KEYC_HOME,
  KEYC_END,
  KEYC_NPAGE,
  KEYC_PPAGE,
  KEYC_BTAB,

  /* Arrow keys. */
  KEYC_UP,
  KEYC_DOWN,
  KEYC_LEFT,
  KEYC_RIGHT,

  /* Numeric keypad. */
  KEYC_KP_SLASH,
  KEYC_KP_STAR,
  KEYC_KP_MINUS,
  KEYC_KP_SEVEN,
  KEYC_KP_EIGHT,
  KEYC_KP_NINE,
  KEYC_KP_PLUS,
  KEYC_KP_FOUR,
  KEYC_KP_FIVE,
  KEYC_KP_SIX,
  KEYC_KP_ONE,
  KEYC_KP_TWO,
  KEYC_KP_THREE,
  KEYC_KP_ENTER,
  KEYC_KP_ZERO,
  KEYC_KP_PERIOD,

  KEYC_FOCUS_IN,
  KEYC_FOCUS_OUT,
};

Termcap codes

enum tty_code_code {
  TTYC_AX = 0,
  TTYC_ACSC,  /* acs_chars, ac */
  TTYC_BEL,  /* bell, bl */
  TTYC_BLINK,  /* enter_blink_mode, mb */
  TTYC_BOLD,  /* enter_bold_mode, md */
  TTYC_CIVIS,  /* cursor_invisible, vi */
  TTYC_CLEAR,  /* clear_screen, cl */
  TTYC_CNORM,  /* cursor_normal, ve */
  TTYC_COLORS,  /* max_colors, Co */
  TTYC_CR,  /* restore cursor colour, Cr */
  TTYC_CS,  /* set cursor colour, Cs */
  TTYC_CSR,  /* change_scroll_region, cs */
  TTYC_CUB,  /* parm_left_cursor, LE */
  TTYC_CUB1,  /* cursor_left, le */
  TTYC_CUD,  /* parm_down_cursor, DO */
  TTYC_CUD1,  /* cursor_down, do */
  TTYC_CUF,  /* parm_right_cursor, RI */
  TTYC_CUF1,  /* cursor_right, nd */
  TTYC_CUP,  /* cursor_address, cm */
  TTYC_CUU,  /* parm_up_cursor, UP */
  TTYC_CUU1,  /* cursor_up, up */
  TTYC_DCH,  /* parm_dch, DC */
  TTYC_DCH1,  /* delete_character, dc */
  TTYC_DIM,  /* enter_dim_mode, mh */
  TTYC_DL,  /* parm_delete_line, DL */
  TTYC_DL1,  /* delete_line, dl */
  TTYC_E3,
  TTYC_ECH,  /* erase_chars, ec */
  TTYC_EL,  /* clr_eol, ce */
  TTYC_EL1,  /* clr_bol, cb */
  TTYC_ENACS,  /* ena_acs, eA */
  TTYC_FSL,  /* from_status_line, fsl */
  TTYC_HOME,  /* cursor_home, ho */
  TTYC_HPA,  /* column_address, ch */
  TTYC_ICH,  /* parm_ich, IC */
  TTYC_ICH1,  /* insert_character, ic */
  TTYC_IL,  /* parm_insert_line, IL */
  TTYC_IL1,  /* insert_line, il */
  TTYC_INVIS,  /* enter_secure_mode, mk */
  TTYC_IS1,  /* init_1string, i1 */
  TTYC_IS2,  /* init_2string, i2 */
  TTYC_IS3,  /* init_3string, i3 */
  TTYC_KCBT,  /* key_btab, kB */
  TTYC_KCUB1,  /* key_left, kl */
  TTYC_KCUD1,  /* key_down, kd */
  TTYC_KCUF1,  /* key_right, kr */
  TTYC_KCUU1,  /* key_up, ku */
  TTYC_KDC2,
  TTYC_KDC3,
  TTYC_KDC4,
  TTYC_KDC5,
  TTYC_KDC6,
  TTYC_KDC7,
  TTYC_KDCH1,  /* key_dc, kD */
  TTYC_KDN2,
  TTYC_KDN3,
  TTYC_KDN4,
  TTYC_KDN5,
  TTYC_KDN6,
  TTYC_KDN7,
  TTYC_KEND,  /* key_end, ke */
  TTYC_KEND2,
  TTYC_KEND3,
  TTYC_KEND4,
  TTYC_KEND5,
  TTYC_KEND6,
  TTYC_KEND7,
  TTYC_KF1,  /* key_f1, k1 */
  TTYC_KF10,  /* key_f10, k; */
  TTYC_KF11,  /* key_f11, F1 */
  TTYC_KF12,  /* key_f12, F2 */
  TTYC_KF13,  /* key_f13, F3 */
  TTYC_KF14,  /* key_f14, F4 */
  TTYC_KF15,  /* key_f15, F5 */
  TTYC_KF16,  /* key_f16, F6 */
  TTYC_KF17,  /* key_f17, F7 */
  TTYC_KF18,  /* key_f18, F8 */
  TTYC_KF19,  /* key_f19, F9 */
  TTYC_KF2,  /* key_f2, k2 */
  TTYC_KF20,  /* key_f20, F10 */
  TTYC_KF3,  /* key_f3, k3 */
  TTYC_KF4,  /* key_f4, k4 */
  TTYC_KF5,  /* key_f5, k5 */
  TTYC_KF6,  /* key_f6, k6 */
  TTYC_KF7,  /* key_f7, k7 */
  TTYC_KF8,  /* key_f8, k8 */
  TTYC_KF9,  /* key_f9, k9 */
  TTYC_KHOM2,
  TTYC_KHOM3,
  TTYC_KHOM4,
  TTYC_KHOM5,
  TTYC_KHOM6,
  TTYC_KHOM7,
  TTYC_KHOME,  /* key_home, kh */
  TTYC_KIC2,
  TTYC_KIC3,
  TTYC_KIC4,
  TTYC_KIC5,
  TTYC_KIC6,
  TTYC_KIC7,
  TTYC_KICH1,  /* key_ic, kI */
  TTYC_KLFT2,
  TTYC_KLFT3,
  TTYC_KLFT4,
  TTYC_KLFT5,
  TTYC_KLFT6,
  TTYC_KLFT7,
  TTYC_KMOUS,  /* key_mouse, Km */
  TTYC_KNP,  /* key_npage, kN */
  TTYC_KNXT2,
  TTYC_KNXT3,
  TTYC_KNXT4,
  TTYC_KNXT5,
  TTYC_KNXT6,
  TTYC_KNXT7,
  TTYC_KPP,  /* key_ppage, kP */
  TTYC_KPRV2,
  TTYC_KPRV3,
  TTYC_KPRV4,
  TTYC_KPRV5,
  TTYC_KPRV6,
  TTYC_KPRV7,
  TTYC_KRIT2,
  TTYC_KRIT3,
  TTYC_KRIT4,
  TTYC_KRIT5,
  TTYC_KRIT6,
  TTYC_KRIT7,
  TTYC_KUP2,
  TTYC_KUP3,
  TTYC_KUP4,
  TTYC_KUP5,
  TTYC_KUP6,
  TTYC_KUP7,
  TTYC_MS,  /* modify xterm(1) selection */
  TTYC_OP,  /* orig_pair, op */
  TTYC_REV,  /* enter_reverse_mode, mr */
  TTYC_RI,  /* scroll_reverse, sr */
  TTYC_RMACS,  /* exit_alt_charset_mode */
  TTYC_RMCUP,  /* exit_ca_mode, te */
  TTYC_RMKX,  /* keypad_local, ke */
  TTYC_SE,  /* reset cursor style, Se */
  TTYC_SETAB,  /* set_a_background, AB */
  TTYC_SETAF,  /* set_a_foreground, AF */
  TTYC_SGR0,  /* exit_attribute_mode, me */
  TTYC_SITM,  /* enter_italics_mode, it */
  TTYC_SMACS,  /* enter_alt_charset_mode, as */
  TTYC_SMCUP,  /* enter_ca_mode, ti */
  TTYC_SMKX,  /* keypad_xmit, ks */
  TTYC_SMSO,  /* enter_standout_mode, so */
  TTYC_SMUL,  /* enter_underline_mode, us */
  TTYC_SS,  /* set cursor style, Ss */
  TTYC_TSL,  /* to_status_line, tsl */
  TTYC_VPA,  /* row_address, cv */
  TTYC_XENL,  /* eat_newline_glitch, xn */
  TTYC_XT,  /* xterm(1)-compatible title, XT */
};
#define NTTYCODE (TTYC_XT + 1)

/* Termcap types. */
enum tty_code_type {
  TTYCODE_NONE = 0,
  TTYCODE_STRING,
  TTYCODE_NUMBER,
  TTYCODE_FLAG,
};

Message codes

enum msgtype {
  MSG_VERSION = 12,

  MSG_IDENTIFY_FLAGS = 100,
  MSG_IDENTIFY_TERM,
  MSG_IDENTIFY_TTYNAME,
  MSG_IDENTIFY_CWD,
  MSG_IDENTIFY_STDIN,
  MSG_IDENTIFY_ENVIRON,
  MSG_IDENTIFY_DONE,

  MSG_COMMAND = 200,
  MSG_DETACH,
  MSG_DETACHKILL,
  MSG_EXIT,
  MSG_EXITED,
  MSG_EXITING,
  MSG_LOCK,
  MSG_READY,
  MSG_RESIZE,
  MSG_SHELL,
  MSG_SHUTDOWN,
  MSG_STDERR,
  MSG_STDIN,
  MSG_STDOUT,
  MSG_SUSPEND,
  MSG_UNLOCK,
  MSG_WAKEUP,
};

Mode key commands

enum mode_key_cmd {
  MODEKEY_NONE,
  MODEKEY_OTHER,

  /* Editing keys. */
  MODEKEYEDIT_BACKSPACE,
  MODEKEYEDIT_CANCEL,
  MODEKEYEDIT_COMPLETE,
  MODEKEYEDIT_CURSORLEFT,
  MODEKEYEDIT_CURSORRIGHT,
  MODEKEYEDIT_DELETE,
  MODEKEYEDIT_DELETELINE,
  MODEKEYEDIT_DELETETOENDOFLINE,
  MODEKEYEDIT_DELETEWORD,
  MODEKEYEDIT_ENDOFLINE,
  MODEKEYEDIT_ENTER,
  MODEKEYEDIT_HISTORYDOWN,
  MODEKEYEDIT_HISTORYUP,
  MODEKEYEDIT_NEXTSPACE,
  MODEKEYEDIT_NEXTSPACEEND,
  MODEKEYEDIT_NEXTWORD,
  MODEKEYEDIT_NEXTWORDEND,
  MODEKEYEDIT_PASTE,
  MODEKEYEDIT_PREVIOUSSPACE,
  MODEKEYEDIT_PREVIOUSWORD,
  MODEKEYEDIT_STARTOFLINE,
  MODEKEYEDIT_SWITCHMODE,
  MODEKEYEDIT_SWITCHMODEAPPEND,
  MODEKEYEDIT_SWITCHMODEAPPENDLINE,
  MODEKEYEDIT_SWITCHMODEBEGINLINE,
  MODEKEYEDIT_SWITCHMODECHANGELINE,
  MODEKEYEDIT_SWITCHMODESUBSTITUTE,
  MODEKEYEDIT_SWITCHMODESUBSTITUTELINE,
  MODEKEYEDIT_TRANSPOSECHARS,

  /* Menu (choice) keys. */
  MODEKEYCHOICE_BACKSPACE,
  MODEKEYCHOICE_BOTTOMLINE,
  MODEKEYCHOICE_CANCEL,
  MODEKEYCHOICE_CHOOSE,
  MODEKEYCHOICE_DOWN,
  MODEKEYCHOICE_ENDOFLIST,
  MODEKEYCHOICE_PAGEDOWN,
  MODEKEYCHOICE_PAGEUP,
  MODEKEYCHOICE_SCROLLDOWN,
  MODEKEYCHOICE_SCROLLUP,
  MODEKEYCHOICE_STARTNUMBERPREFIX,
  MODEKEYCHOICE_STARTOFLIST,
  MODEKEYCHOICE_TOPLINE,
  MODEKEYCHOICE_TREE_COLLAPSE,
  MODEKEYCHOICE_TREE_COLLAPSE_ALL,
  MODEKEYCHOICE_TREE_EXPAND,
  MODEKEYCHOICE_TREE_EXPAND_ALL,
  MODEKEYCHOICE_TREE_TOGGLE,
  MODEKEYCHOICE_UP,

  /* Copy keys. */
  MODEKEYCOPY_APPENDSELECTION,
  MODEKEYCOPY_BACKTOINDENTATION,
  MODEKEYCOPY_BOTTOMLINE,
  MODEKEYCOPY_CANCEL,
  MODEKEYCOPY_CLEARSELECTION,
  MODEKEYCOPY_COPYPIPE,
  MODEKEYCOPY_COPYLINE,
  MODEKEYCOPY_COPYENDOFLINE,
  MODEKEYCOPY_COPYSELECTION,
  MODEKEYCOPY_DOWN,
  MODEKEYCOPY_ENDOFLINE,
  MODEKEYCOPY_GOTOLINE,
  MODEKEYCOPY_HALFPAGEDOWN,
  MODEKEYCOPY_HALFPAGEUP,
  MODEKEYCOPY_HISTORYBOTTOM,
  MODEKEYCOPY_HISTORYTOP,
  MODEKEYCOPY_JUMP,
  MODEKEYCOPY_JUMPAGAIN,
  MODEKEYCOPY_JUMPREVERSE,
  MODEKEYCOPY_JUMPBACK,
  MODEKEYCOPY_JUMPTO,
  MODEKEYCOPY_JUMPTOBACK,
  MODEKEYCOPY_LEFT,
  MODEKEYCOPY_MIDDLELINE,
  MODEKEYCOPY_NEXTPAGE,
  MODEKEYCOPY_NEXTSPACE,
  MODEKEYCOPY_NEXTSPACEEND,
  MODEKEYCOPY_NEXTWORD,
  MODEKEYCOPY_NEXTWORDEND,
  MODEKEYCOPY_OTHEREND,
  MODEKEYCOPY_PREVIOUSPAGE,
  MODEKEYCOPY_PREVIOUSSPACE,
  MODEKEYCOPY_PREVIOUSWORD,
  MODEKEYCOPY_RECTANGLETOGGLE,
  MODEKEYCOPY_RIGHT,
  MODEKEYCOPY_SCROLLDOWN,
  MODEKEYCOPY_SCROLLUP,
  MODEKEYCOPY_SEARCHAGAIN,
  MODEKEYCOPY_SEARCHDOWN,
  MODEKEYCOPY_SEARCHREVERSE,
  MODEKEYCOPY_SEARCHUP,
  MODEKEYCOPY_SELECTLINE,
  MODEKEYCOPY_STARTNUMBERPREFIX,
  MODEKEYCOPY_STARTOFLINE,
  MODEKEYCOPY_STARTSELECTION,
  MODEKEYCOPY_TOPLINE,
  MODEKEYCOPY_UP,
};

Modes

#define MODE_CURSOR 0x1
#define MODE_INSERT 0x2
#define MODE_KCURSOR 0x4
#define MODE_KKEYPAD 0x8  /* set = application, clear = number */
#define MODE_WRAP 0x10    /* whether lines wrap */
#define MODE_MOUSE_STANDARD 0x20
#define MODE_MOUSE_BUTTON 0x40
#define MODE_MOUSE_ANY 0x80
#define MODE_MOUSE_UTF8 0x100
#define MODE_MOUSE_SGR 0x200
#define MODE_BRACKETPASTE 0x400
#define MODE_FOCUSON 0x800

#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)

Grid attributes

#define GRID_ATTR_BRIGHT 0x1
#define GRID_ATTR_DIM 0x2
#define GRID_ATTR_UNDERSCORE 0x4
#define GRID_ATTR_BLINK 0x8
#define GRID_ATTR_REVERSE 0x10
#define GRID_ATTR_HIDDEN 0x20
#define GRID_ATTR_ITALICS 0x40
#define GRID_ATTR_CHARSET 0x80  /* alternative character set */

Layout direction

enum layout_type {
  LAYOUT_LEFTRIGHT,
  LAYOUT_TOPBOTTOM,
  LAYOUT_WINDOWPANE
};

Mouse

/* Mouse button masks. */
#define MOUSE_MASK_BUTTONS 3
#define MOUSE_MASK_SHIFT 4
#define MOUSE_MASK_META 8
#define MOUSE_MASK_CTRL 16
#define MOUSE_MASK_DRAG 32
#define MOUSE_MASK_WHEEL 64

/* Mouse wheel states. */
#define MOUSE_WHEEL_UP 0
#define MOUSE_WHEEL_DOWN 1

/* Mouse event bits. */
#define MOUSE_EVENT_DOWN 0x1
#define MOUSE_EVENT_DRAG 0x2
#define MOUSE_EVENT_UP 0x4
#define MOUSE_EVENT_CLICK 0x8
#define MOUSE_EVENT_WHEEL 0x10

/* Mouse flag bits. */
#define MOUSE_RESIZE_PANE 0x1

Option table entries

/*
 * Option table entries. The option table is the user-visible part of the
 * option, as opposed to the internal options (struct option) which are just
 * number or string.
 */
enum options_table_type {
    OPTIONS_TABLE_STRING,
    OPTIONS_TABLE_NUMBER,
    OPTIONS_TABLE_KEY,
    OPTIONS_TABLE_COLOUR,
    OPTIONS_TABLE_ATTRIBUTES,
    OPTIONS_TABLE_FLAG,
    OPTIONS_TABLE_CHOICE,
    OPTIONS_TABLE_STYLE
};

Common command usages

/* Common command usages. */
#define CMD_TARGET_PANE_USAGE "[-t target-pane]"
#define CMD_TARGET_WINDOW_USAGE "[-t target-window]"
#define CMD_TARGET_SESSION_USAGE "[-t target-session]"
#define CMD_TARGET_CLIENT_USAGE "[-t target-client]"
#define CMD_SRCDST_PANE_USAGE "[-s src-pane] [-t dst-pane]"
#define CMD_SRCDST_WINDOW_USAGE "[-s src-window] [-t dst-window]"
#define CMD_SRCDST_SESSION_USAGE "[-s src-session] [-t dst-session]"
#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]"
#define CMD_BUFFER_USAGE "[-b buffer-index]"

colour.c

Colour to string conversion functions. Bit 8 of the colour means it is one of the 256 colour palette.

/* An RGB colour. */
struct colour_rgb {
    u_char  r;
    u_char  g;
    u_char  b;
};

/* 256 colour RGB table, generated on first use. */
struct colour_rgb *colour_rgb_256;

void    colour_rgb_generate256(void);
u_int   colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
int colour_rgb_find(struct colour_rgb *);

Generate 256 colour RGB table.

void
colour_rgb_generate256(void)
{
    struct colour_rgb   *rgb;
    u_int            i, r, g, b;

    /*
     * Allocate the table. The first 16 colours are often changed by users
     * and terminals so don't include them.
     */
    colour_rgb_256 = xcalloc(240, sizeof *colour_rgb_256);

    /* Add the colours first. */
    r = g = b = 0;
    for (i = 240; i > 24; i--) {
        rgb = &colour_rgb_256[240 - i];

        if (r != 0)
            rgb->r = (r * 40) + 55;
        if (g != 0)
            rgb->g = (g * 40) + 55;
        if (b != 0)
            rgb->b = (b * 40) + 55;

        b++;
        if (b > 5) {
            b = 0;
            g++;
        }
        if (g > 5) {
            g = 0;
            r++;
        }
    }

    /* Then add the greys. */
    for (i = 24; i > 0; i--) {
        rgb = &colour_rgb_256[240 - i];

        rgb->r = 8 + (24 - i) * 10;
        rgb->g = 8 + (24 - i) * 10;
        rgb->b = 8 + (24 - i) * 10;
    }
}

Get colour RGB distance.

u_int
colour_rgb_distance(struct colour_rgb *rgb1, struct colour_rgb *rgb2)
{
    int r, g, b;

    r = rgb1->r - rgb2->r;
    g = rgb1->g - rgb2->g;
    b = rgb1->b - rgb2->b;
    return (r * r + g * g + b * b);
}

Work out the nearest colour from the 256 colour set.

int
colour_rgb_find(struct colour_rgb *rgb)
{
    u_int   distance, lowest, colour, i;

    if (colour_rgb_256 == NULL)
        colour_rgb_generate256();

    colour = 16;
    lowest = UINT_MAX;
    for (i = 0; i < 240; i++) {
        distance = colour_rgb_distance(&colour_rgb_256[i], rgb);
        if (distance < lowest) {
            lowest = distance;
            colour = 16 + i;
        }
    }
    return (colour);
}

Convert colour to a string.

const char *
colour_tostring(int c)
{
    static char s[32];

    if (c & 0x100) {
        xsnprintf(s, sizeof s, "colour%u", c & ~0x100);
        return (s);
    }

    switch (c) {
    case 0:
        return ("black");
    case 1:
        return ("red");
    case 2:
        return ("green");
    case 3:
        return ("yellow");
    case 4:
        return ("blue");
    case 5:
        return ("magenta");
    case 6:
        return ("cyan");
    case 7:
        return ("white");
    case 8:
        return ("default");
    case 90:
        return ("brightblack");
    case 91:
        return ("brightred");
    case 92:
        return ("brightgreen");
    case 93:
        return ("brightyellow");
    case 94:
        return ("brightblue");
    case 95:
        return ("brightmagenta");
    case 96:
        return ("brightcyan");
    case 97:
        return ("brightwhite");
    }
    return (NULL);
}

Convert colour from string.

int
colour_fromstring(const char *s)
{
    const char      *errstr;
    const char      *cp;
    struct colour_rgb    rgb;
    int          n;

    if (*s == '#' && strlen(s) == 7) {
        for (cp = s + 1; isxdigit((u_char) *cp); cp++)
            ;
        if (*cp != '\0')
            return (-1);
        n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &rgb.r, &rgb.g, &rgb.b);
        if (n != 3)
            return (-1);
        return (colour_rgb_find(&rgb) | 0x100);
    }

    if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
        n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
        if (errstr != NULL)
            return (-1);
        return (n | 0x100);
    }

    if (strcasecmp(s, "black") == 0 || (s[0] == '0' && s[1] == '\0'))
        return (0);
    if (strcasecmp(s, "red") == 0 || (s[0] == '1' && s[1] == '\0'))
        return (1);
    if (strcasecmp(s, "green") == 0 || (s[0] == '2' && s[1] == '\0'))
        return (2);
    if (strcasecmp(s, "yellow") == 0 || (s[0] == '3' && s[1] == '\0'))
        return (3);
    if (strcasecmp(s, "blue") == 0 || (s[0] == '4' && s[1] == '\0'))
        return (4);
    if (strcasecmp(s, "magenta") == 0 || (s[0] == '5' && s[1] == '\0'))
        return (5);
    if (strcasecmp(s, "cyan") == 0 || (s[0] == '6' && s[1] == '\0'))
        return (6);
    if (strcasecmp(s, "white") == 0 || (s[0] == '7' && s[1] == '\0'))
        return (7);
    if (strcasecmp(s, "default") == 0 || (s[0] == '8' && s[1] == '\0'))
        return (8);
    if (strcasecmp(s, "brightblack") == 0 ||
        (s[0] == '9' && s[1] == '0' && s[1] == '\0'))
        return (90);
    if (strcasecmp(s, "brightred") == 0 ||
        (s[0] == '9' && s[1] == '1' && s[1] == '\0'))
        return (91);
    if (strcasecmp(s, "brightgreen") == 0 ||
        (s[0] == '9' && s[1] == '2' && s[1] == '\0'))
        return (92);
    if (strcasecmp(s, "brightyellow") == 0 ||
        (s[0] == '9' && s[1] == '3' && s[1] == '\0'))
        return (93);
    if (strcasecmp(s, "brightblue") == 0 ||
        (s[0] == '9' && s[1] == '4' && s[1] == '\0'))
        return (94);
    if (strcasecmp(s, "brightmagenta") == 0 ||
        (s[0] == '9' && s[1] == '5' && s[1] == '\0'))
        return (95);
    if (strcasecmp(s, "brightcyan") == 0 ||
        (s[0] == '9' && s[1] == '6' && s[1] == '\0'))
        return (96);
    if (strcasecmp(s, "brightwhite") == 0 ||
        (s[0] == '9' && s[1] == '7' && s[1] == '\0'))
        return (97);
    return (-1);
}

Convert 256 colour palette to 16.

u_char
colour_256to16(u_char c)
{
    static const u_char table[256] = {
         0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
         0,  4,  4,  4, 12, 12,  2,  6,  4,  4, 12, 12,  2,  2,  6,  4,
        12, 12,  2,  2,  2,  6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
        10, 10, 10, 14,  1,  5,  4,  4, 12, 12,  3,  8,  4,  4, 12, 12,
         2,  2,  6,  4, 12, 12,  2,  2,  2,  6, 12, 12, 10, 10, 10, 10,
        14, 12, 10, 10, 10, 10, 10, 14,  1,  1,  5,  4, 12, 12,  1,  1,
         5,  4, 12, 12,  3,  3,  8,  4, 12, 12,  2,  2,  2,  6, 12, 12,
        10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,  1,  1,  1,  5,
        12, 12,  1,  1,  1,  5, 12, 12,  1,  1,  1,  5, 12, 12,  3,  3,
         3,  7, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,
         9,  9,  9,  9, 13, 12,  9,  9,  9,  9, 13, 12,  9,  9,  9,  9,
        13, 12,  9,  9,  9,  9, 13, 12, 11, 11, 11, 11,  7, 12, 10, 10,
        10, 10, 10, 14,  9,  9,  9,  9,  9, 13,  9,  9,  9,  9,  9, 13,
         9,  9,  9,  9,  9, 13,  9,  9,  9,  9,  9, 13,  9,  9,  9,  9,
         9, 13, 11, 11, 11, 11, 11, 15,  0,  0,  0,  0,  0,  0,  8,  8,
         8,  8,  8,  8,  7,  7,  7,  7,  7,  7, 15, 15, 15, 15, 15, 15
    };

    return (table[c]);
}




















More Reading

  1. TMUX FAQ - Trunk
  2. TMUX Examples
  3. https://wiki.archlinux.org/index.php/Tmux
  4. http://mutelight.org/articles/practical-tmux
  5. Terminal ZEN

JWR

  1. Copy and Paste
  2. tmux multiplexer
  3. tmux sessions

tmux.conf examples

  1. jasonwryan tmux.conf

URXVT

  1. http://linux.die.net/man/7/urxvt

Hacking Linux linux.bash Screen shell tmux

 

 

Comments