FREE THOUGHT · FREE SOFTWARE · FREE WORLD

Home » Hacking » TMUX

by comment

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.

TMUX

tmux usage

TMUX

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

Tags

Comments Welcome

Information is freedom. Freedom is non-negotiable. So please feel free to modify, copy, republish, sell, or use anything on this site in any way at any time ;)

My Online Tools

Popular Articles
Hacking and Hackers

The use of "hacker" to mean "security breaker" is a confusion on the part of the mass media. We hackers refuse to recognize that meaning, and continue using the word to mean someone who loves to program, someone who enjoys playful cleverness, or the combination of the two.
-- Richard M. Stallman


It's very simple - you read the protocol and write the code. -Bill Joy

Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 License, just credit with a link.
This site is not supported or endorsed by The Apache Software Foundation (ASF). All software and documentation produced by The ASF is licensed. "Apache" is a trademark of The ASF. NCSA HTTPd.
UNIX ® is a registered Trademark of The Open Group. POSIX ® is a registered Trademark of The IEEE.

+Askapache | htaccess.io | htaccess.guru

Site Map | Contact Webmaster | License and Disclaimer | Terms of Service | @Htaccess

↑ TOPMain