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.
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]]
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
grep -h 'const struct cmd_entry' -A1 cmd-*.c|nobb|grep -v '^const'|grep -v '^\-\-'|trs|nobb| sed 's,^"\([^"]\+\)"\, *"\([^"]\+\)"..*$,\2:
"#{line}: #{buffer_size} bytes: #{buffer_sample}"
"#{client_tty}: #{session_name} [#{client_width}x#{client_height} #{client_termname}]#{?client_utf8, (utf8),}#{?client_readonly, (ro),} (last used #{client_activity_string})"
"#{session_name}: #{session_windows} windows#{?session_grouped, (group ,}#{session_group}#{?session_grouped,),}#{?session_attached, (attached),}"
"#{window_index}: #{window_name}#{window_flags} \"#{pane_title}\""
"[#{session_name}] #{window_index}:#{window_name}, current pane #{pane_index} - (%H:%M %d-%b-%y)"
"#{window_index}: #{window_name} [#{window_width}x#{window_height}] (#{window_panes} panes) #{window_find_matches}"
"#{line}: #{buffer_size} bytes: \"#{buffer_sample}\""
"#{client_tty}: #{session_name} [#{client_width}x#{client_height} #{client_termname}]#{?client_utf8, (utf8),} #{?client_readonly, (ro),}"
"#{session_name}: #{session_windows} windows (created #{session_created_string}) [#{session_width}x#{session_height}]#{?session_grouped, (group ,}#{session_group}#{?session_grouped,),}#{?session_attached, (attached),}"
"#{window_index}: #{window_name}#{window_flags} (#{window_panes} panes) [#{window_width}x#{window_height}] [layout #{window_layout}] #{window_id}#{?window_active, (active),}"
"#{session_name}:#{window_index}: #{window_name}#{window_flags} (#{window_panes} panes) [#{window_width}x#{window_height}] "
"#{session_name}:"
"#{session_name}:#{window_index}.#{pane_index}"
"#{session_name}:#{window_index}.#{pane_index}"
"#{session_name}:#{window_index}.#{pane_index}"
struct options global_options; /* server options */ struct options global_s_options; /* session options */ struct options global_w_options; /* window options */ struct environ global_environ;
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1)
for (var = environ; *var != NULL; var++) environ_put(&global_environ, *var);
if (getcwd(tmp, sizeof tmp) != NULL) environ_set(&global_environ, "PWD", tmp);
options_table_populate_tree(server_options_table, &global_options)
options_table_populate_tree(session_options_table, &global_s_options);
options_set_string(&global_s_options, "default-shell", "%s", getshell());
options_table_populate_tree(window_options_table, &global_w_options);
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); }
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); }
s = getenv("TMUX"); if (s != NULL && sscanf(s, "%255[^,],%lld,%d", in, &pid, &session) == 3) environ_path = xstrdup(in);
#ifdef HAVE_SETPROCTITLE setproctitle("%s (%s)", __progname, socket_path);
ev_base = osdep_event_init(); exit(client_main(argc, argv, flags));
makesocketpath sets the socketpath in this order.
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); }
__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"); }
extern struct options global_options; extern struct options global_s_options; extern struct options global_w_options; extern struct environ global_environ;
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 *);
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[];
/* 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, };
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, };
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, };
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, };
#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)
#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 */
enum layout_type { LAYOUT_LEFTRIGHT, LAYOUT_TOPBOTTOM, LAYOUT_WINDOWPANE };
/* 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. 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. */ #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 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 *);
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; } }
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); }
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); }
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); }
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); }
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
- TMUX FAQ - Trunk
- TMUX Examples
- https://wiki.archlinux.org/index.php/Tmux
- http://mutelight.org/articles/practical-tmux
- Terminal ZEN
JWR
tmux.conf examples
URXVT
TMUX - AskApache