From df680d725751e0fe9eca4403c732ec1332d91d97 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 22 Jan 2014 13:57:49 +0000 Subject: [PATCH 01/15] Only exit copy mode at the bottom if no selection in progress, from Benoit Pierre. --- window-copy.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/window-copy.c b/window-copy.c index dd4f23fa..ddd5bf41 100644 --- a/window-copy.c +++ b/window-copy.c @@ -853,8 +853,12 @@ window_copy_mouse( } else if (m->wheel == MOUSE_WHEEL_DOWN) { for (i = 0; i < 5; i++) window_copy_cursor_down(wp, 1); - if (data->oy == 0) - goto reset_mode; + /* + * We reached the bottom, leave copy mode, + * but only if no selection is in progress. + */ + if (data->oy == 0 && !s->sel.flag) + goto reset_mode; } return; } From 9ee93b3ea30cfa8e67a62b3c6cf522a9e677ca84 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 22 Jan 2014 14:00:08 +0000 Subject: [PATCH 02/15] Do not permit periods in session names (colons are already banned). From J Raynor. --- session.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/session.c b/session.c index 4f6ebed6..11ae2d35 100644 --- a/session.c +++ b/session.c @@ -175,11 +175,11 @@ session_destroy(struct session *s) RB_INSERT(sessions, &dead_sessions, s); } -/* Check a session name is valid: not empty and no colons. */ +/* Check a session name is valid: not empty and no colons or periods. */ int session_check_name(const char *name) { - return (*name != '\0' && strchr(name, ':') == NULL); + return (*name != '\0' && name[strcspn(name, ":.")] == '\0'); } /* Update session active time. */ From c9658705854599d89bd71bbd985d388fee01e113 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 22 Jan 2014 14:02:32 +0000 Subject: [PATCH 03/15] + to TODO. --- TODO | 3 +++ 1 file changed, 3 insertions(+) diff --git a/TODO b/TODO index d0bbaa5d..529b5e8c 100644 --- a/TODO +++ b/TODO @@ -142,3 +142,6 @@ - buffer_sample and the choose-* could let UTF-8 through and display it properly. + +- formats to show if a window is linked into multiple sessions, into multiple + attached sessions, and is the active window in multiple attached sessions? From cbf9224c5f7bcf07352f6ea128c90c12cb0af22e Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 22 Jan 2014 14:03:16 +0000 Subject: [PATCH 04/15] Add AC_PROG_MKDIR_P. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 644b283d..f646a0d0 100644 --- a/configure.ac +++ b/configure.ac @@ -16,6 +16,7 @@ AC_CANONICAL_HOST # Set up the compiler in two different ways and say yes we may want to install. AC_PROG_CC AM_PROG_CC_C_O +AC_PROG_MKDIR_P AC_PROG_INSTALL # Default tmux.conf goes in /etc not ${prefix}/etc. From d23561f38172d1fd3766bf55390ba750a5bd1b64 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 22 Jan 2014 14:43:42 +0000 Subject: [PATCH 05/15] Merge server-info into show-messages and remove some not useful output. --- Makefile | 1 - cmd-server-info.c | 173 -------------------------------------------- cmd-show-messages.c | 112 +++++++++++++++++++++++++++- tmux.1 | 14 +++- 4 files changed, 120 insertions(+), 180 deletions(-) delete mode 100644 cmd-server-info.c diff --git a/Makefile b/Makefile index 9fa55d9b..96972944 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,6 @@ SRCS= arguments.c \ cmd-select-pane.c \ cmd-select-window.c \ cmd-send-keys.c \ - cmd-server-info.c \ cmd-set-buffer.c \ cmd-set-environment.c \ cmd-set-option.c \ diff --git a/cmd-server-info.c b/cmd-server-info.c deleted file mode 100644 index 6cbabe2b..00000000 --- a/cmd-server-info.c +++ /dev/null @@ -1,173 +0,0 @@ -/* $OpenBSD$ */ - -/* - * Copyright (c) 2008 Nicholas Marriott - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include "tmux.h" - -/* - * Show various information about server. - */ - -enum cmd_retval cmd_server_info_exec(struct cmd *, struct cmd_q *); - -const struct cmd_entry cmd_server_info_entry = { - "server-info", "info", - "", 0, 0, - "", - 0, - NULL, - cmd_server_info_exec -}; - -enum cmd_retval -cmd_server_info_exec(unused struct cmd *self, struct cmd_q *cmdq) -{ - struct tty_term *term; - struct client *c; - struct session *s; - struct winlink *wl; - struct window *w; - struct window_pane *wp; - struct tty_code *code; - const struct tty_term_code_entry *ent; - struct utsname un; - struct job *job; - struct grid *gd; - struct grid_line *gl; - u_int i, j, k, lines; - size_t size; - char out[80]; - char *tim; - time_t t; - - tim = ctime(&start_time); - *strchr(tim, '\n') = '\0'; - cmdq_print(cmdq, "pid %ld, started %s", (long) getpid(), tim); - cmdq_print(cmdq, "socket path %s, debug level %d", socket_path, - debug_level); - if (uname(&un) >= 0) { - cmdq_print(cmdq, "system is %s %s %s %s", - un.sysname, un.release, un.version, un.machine); - } - if (cfg_file != NULL) - cmdq_print(cmdq, "configuration file is %s", cfg_file); - else - cmdq_print(cmdq, "configuration file not specified"); - cmdq_print(cmdq, "protocol version is %d", PROTOCOL_VERSION); - cmdq_print(cmdq, "%s", ""); - - cmdq_print(cmdq, "Clients:"); - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - - cmdq_print(cmdq,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho " - "class=%u] [flags=0x%x/0x%x, references=%u]", i, - c->tty.path, c->ibuf.fd, c->tty.fd, c->session->name, - c->tty.sx, c->tty.sy, c->tty.termname, - c->tty.tio.c_cc[VERASE], c->tty.class, - c->flags, c->tty.flags, c->references); - } - cmdq_print(cmdq, "%s", ""); - - cmdq_print(cmdq, "Sessions: [%zu]", sizeof (struct grid_cell)); - RB_FOREACH(s, sessions, &sessions) { - t = s->creation_time.tv_sec; - tim = ctime(&t); - *strchr(tim, '\n') = '\0'; - - cmdq_print(cmdq, "%2u: %s: %u windows (created %s) [%ux%u] " - "[flags=0x%x]", s->id, s->name, - winlink_count(&s->windows), tim, s->sx, s->sy, s->flags); - RB_FOREACH(wl, winlinks, &s->windows) { - w = wl->window; - cmdq_print(cmdq, "%4u: %s [%ux%u] [flags=0x%x, " - "references=%u, last layout=%d]", wl->idx, w->name, - w->sx, w->sy, w->flags, w->references, - w->lastlayout); - j = 0; - TAILQ_FOREACH(wp, &w->panes, entry) { - lines = size = 0; - gd = wp->base.grid; - for (k = 0; k < gd->hsize + gd->sy; k++) { - gl = &gd->linedata[k]; - if (gl->celldata == NULL) - continue; - lines++; - size += gl->cellsize * - sizeof *gl->celldata; - } - cmdq_print(cmdq, - "%6u: %s %lu %d %u/%u, %zu bytes", j, - wp->tty, (u_long) wp->pid, wp->fd, lines, - gd->hsize + gd->sy, size); - j++; - } - } - } - cmdq_print(cmdq, "%s", ""); - - cmdq_print(cmdq, "Terminals:"); - LIST_FOREACH(term, &tty_terms, entry) { - cmdq_print(cmdq, "%s [references=%u, flags=0x%x]:", - term->name, term->references, term->flags); - for (i = 0; i < NTTYCODE; i++) { - ent = &tty_term_codes[i]; - code = &term->codes[ent->code]; - switch (code->type) { - case TTYCODE_NONE: - cmdq_print(cmdq, "%2u: %s: [missing]", - ent->code, ent->name); - break; - case TTYCODE_STRING: - strnvis(out, code->value.string, sizeof out, - VIS_OCTAL|VIS_TAB|VIS_NL); - cmdq_print(cmdq, "%2u: %s: (string) %s", - ent->code, ent->name, out); - break; - case TTYCODE_NUMBER: - cmdq_print(cmdq, "%2u: %s: (number) %d", - ent->code, ent->name, code->value.number); - break; - case TTYCODE_FLAG: - cmdq_print(cmdq, "%2u: %s: (flag) %s", - ent->code, ent->name, - code->value.flag ? "true" : "false"); - break; - } - } - } - cmdq_print(cmdq, "%s", ""); - - cmdq_print(cmdq, "Jobs:"); - LIST_FOREACH(job, &all_jobs, lentry) { - cmdq_print(cmdq, "%s [fd=%d, pid=%d, status=%d]", - job->cmd, job->fd, job->pid, job->status); - } - - return (CMD_RETURN_NORMAL); -} diff --git a/cmd-show-messages.c b/cmd-show-messages.c index f43607aa..a3938e0a 100644 --- a/cmd-show-messages.c +++ b/cmd-show-messages.c @@ -20,6 +20,8 @@ #include #include +#include +#include #include "tmux.h" @@ -31,13 +33,98 @@ enum cmd_retval cmd_show_messages_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_show_messages_entry = { "show-messages", "showmsgs", - "t:", 0, 0, - CMD_TARGET_CLIENT_USAGE, + "IJTt:", 0, 0, + "[-IJT] " CMD_TARGET_CLIENT_USAGE, 0, NULL, cmd_show_messages_exec }; +const struct cmd_entry cmd_server_info_entry = { + "server-info", "info", + "", 0, 0, + "", + 0, + NULL, + cmd_show_messages_exec +}; + +void cmd_show_messages_server (struct cmd_q *); +void cmd_show_messages_terminals (struct cmd_q *); +void cmd_show_messages_jobs (struct cmd_q *); + +void +cmd_show_messages_server (struct cmd_q *cmdq) +{ + char *tim; + + tim = ctime(&start_time); + *strchr(tim, '\n') = '\0'; + + cmdq_print(cmdq, "started %s", tim); + cmdq_print(cmdq, "socket path %s", socket_path); + cmdq_print(cmdq, "debug level %d", debug_level); + cmdq_print(cmdq, "protocol version %d", PROTOCOL_VERSION); +} + +void +cmd_show_messages_terminals (struct cmd_q *cmdq) +{ + struct tty_term *term; + const struct tty_term_code_entry *ent; + struct tty_code *code; + u_int i, n; + char out[80]; + + n = 0; + LIST_FOREACH(term, &tty_terms, entry) { + cmdq_print(cmdq, + "Terminal %u: %s [references=%u, flags=0x%x]:", + n, term->name, term->references, term->flags); + n++; + for (i = 0; i < NTTYCODE; i++) { + ent = &tty_term_codes[i]; + code = &term->codes[ent->code]; + switch (code->type) { + case TTYCODE_NONE: + cmdq_print(cmdq, "%4u: %s: [missing]", + ent->code, ent->name); + break; + case TTYCODE_STRING: + strnvis(out, code->value.string, sizeof out, + VIS_OCTAL|VIS_TAB|VIS_NL); + cmdq_print(cmdq, "%4u: %s: (string) %s", + ent->code, ent->name, out); + break; + case TTYCODE_NUMBER: + cmdq_print(cmdq, "%4u: %s: (number) %d", + ent->code, ent->name, code->value.number); + break; + case TTYCODE_FLAG: + cmdq_print(cmdq, "%4u: %s: (flag) %s", + ent->code, ent->name, + code->value.flag ? "true" : "false"); + break; + } + } + } +} + +void +cmd_show_messages_jobs (struct cmd_q *cmdq) +{ + struct job *job; + u_int n; + + n = 0; + LIST_FOREACH(job, &all_jobs, lentry) { + cmdq_print(cmdq, + "Job %u: %s [fd=%d, pid=%d, status=%d]", + n, job->cmd, job->fd, job->pid, job->status); + n++; + } +} + enum cmd_retval cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq) { @@ -46,6 +133,27 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq) struct message_entry *msg; char *tim; u_int i; + int done; + + done = 0; + if (args_has (args, 'I') || self->entry == &cmd_server_info_entry) { + cmd_show_messages_server (cmdq); + done = 1; + } + if (args_has (args, 'T') || self->entry == &cmd_server_info_entry) { + if (done) + cmdq_print (cmdq, "%s", ""); + cmd_show_messages_terminals (cmdq); + done = 1; + } + if (args_has (args, 'J') || self->entry == &cmd_server_info_entry) { + if (done) + cmdq_print (cmdq, "%s", ""); + cmd_show_messages_jobs (cmdq); + done = 1; + } + if (done) + return (CMD_RETURN_NORMAL); if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); diff --git a/tmux.1 b/tmux.1 index a2404b4f..e44a44a6 100644 --- a/tmux.1 +++ b/tmux.1 @@ -770,15 +770,24 @@ is specified, only update the client's status bar. Rename the session to .Ar new-name . .It Xo Ic show-messages +.Op Fl IJT .Op Fl t Ar target-client .Xc .D1 (alias: Ic showmsgs ) +Show client messages or server information. Any messages displayed on the status line are saved in a per-client message log, up to a maximum of the limit set by the .Ar message-limit session option for the session attached to that client. -This command displays the log for +With +.Fl t , +display the log for .Ar target-client . +.Fl I, +.Fl J +and +.Fl T +show debugging information about the running server, jobs and terminals. .It Ic source-file Ar path .D1 (alias: Ic source ) Execute commands from @@ -3566,9 +3575,6 @@ specified by .Fl t or the current pane if omitted). If the command doesn't return success, the exit status is also displayed. -.It Ic server-info -.D1 (alias: Ic info ) -Show server information and terminal details. .It Xo Ic wait-for .Op Fl L | S | U .Ar channel From 7d3d9963839e92e56cfd484918c16ef58c0be687 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 22 Jan 2014 22:32:15 +0000 Subject: [PATCH 06/15] Support paste key in copy mode input (for search etc). Also clamp length to screen width. --- window-copy.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/window-copy.c b/window-copy.c index ddd5bf41..48cd4b33 100644 --- a/window-copy.c +++ b/window-copy.c @@ -750,8 +750,10 @@ window_copy_key_input(struct window_pane *wp, int key) { struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; - size_t inputlen; + size_t inputlen, n; int np; + struct paste_buffer *pb; + u_char ch; switch (mode_key_lookup(&data->mdata, key, NULL)) { case MODEKEYEDIT_CANCEL: @@ -765,6 +767,20 @@ window_copy_key_input(struct window_pane *wp, int key) case MODEKEYEDIT_DELETELINE: *data->inputstr = '\0'; break; + case MODEKEYEDIT_PASTE: + if ((pb = paste_get_top(&global_buffers)) == NULL) + break; + for (n = 0; n < pb->size; n++) { + ch = (u_char) pb->data[n]; + if (ch < 32 || ch == 127) + break; + } + inputlen = strlen(data->inputstr); + + data->inputstr = xrealloc(data->inputstr, 1, inputlen + n + 1); + memcpy(data->inputstr + inputlen, pb->data, n); + data->inputstr[inputlen + n] = '\0'; + break; case MODEKEYEDIT_ENTER: np = data->numprefix; if (np <= 0) @@ -1154,8 +1170,8 @@ window_copy_write_line( struct screen *s = &data->screen; struct options *oo = &wp->window->options; struct grid_cell gc; - char hdr[32]; - size_t last, xoff = 0, size = 0; + char hdr[512]; + size_t last, xoff = 0, size = 0, limit; window_mode_attrs(&gc, oo); @@ -1168,11 +1184,14 @@ window_copy_write_line( screen_write_cursormove(ctx, screen_size_x(s) - size, 0); screen_write_puts(ctx, &gc, "%s", hdr); } else if (py == last && data->inputtype != WINDOW_COPY_OFF) { + limit = sizeof hdr; + if (limit > screen_size_x(s)) + limit = screen_size_x(s); if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) { - xoff = size = xsnprintf(hdr, sizeof hdr, + xoff = size = xsnprintf(hdr, limit, "Repeat: %u", data->numprefix); } else { - xoff = size = xsnprintf(hdr, sizeof hdr, + xoff = size = xsnprintf(hdr, limit, "%s: %s", data->inputprompt, data->inputstr); } screen_write_cursormove(ctx, 0, last); From dda70d4ef1ce155906c123c6880352c4979e4b57 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 27 Jan 2014 23:57:35 +0000 Subject: [PATCH 07/15] Merge start-server into kill-server. --- Makefile | 1 - cmd-kill-server.c | 14 ++++++++++++-- cmd-start-server.c | 42 ------------------------------------------ 3 files changed, 12 insertions(+), 45 deletions(-) delete mode 100644 cmd-start-server.c diff --git a/Makefile b/Makefile index 96972944..a0736bdf 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,6 @@ SRCS= arguments.c \ cmd-show-options.c \ cmd-source-file.c \ cmd-split-window.c \ - cmd-start-server.c \ cmd-string.c \ cmd-suspend-client.c \ cmd-swap-pane.c \ diff --git a/cmd-kill-server.c b/cmd-kill-server.c index ef4a3946..6f0b7494 100644 --- a/cmd-kill-server.c +++ b/cmd-kill-server.c @@ -38,10 +38,20 @@ const struct cmd_entry cmd_kill_server_entry = { cmd_kill_server_exec }; +const struct cmd_entry cmd_start_server_entry = { + "start-server", "start", + "", 0, 0, + "", + CMD_STARTSERVER, + NULL, + cmd_kill_server_exec +}; + enum cmd_retval -cmd_kill_server_exec(unused struct cmd *self, unused struct cmd_q *cmdq) +cmd_kill_server_exec(struct cmd *self, unused struct cmd_q *cmdq) { - kill(getpid(), SIGTERM); + if (self->entry == &cmd_kill_server_entry) + kill(getpid(), SIGTERM); return (CMD_RETURN_NORMAL); } diff --git a/cmd-start-server.c b/cmd-start-server.c deleted file mode 100644 index d98f9506..00000000 --- a/cmd-start-server.c +++ /dev/null @@ -1,42 +0,0 @@ -/* $OpenBSD$ */ - -/* - * Copyright (c) 2007 Nicholas Marriott - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include "tmux.h" - -/* - * Start the server and do nothing else. - */ - -enum cmd_retval cmd_start_server_exec(struct cmd *, struct cmd_q *); - -const struct cmd_entry cmd_start_server_entry = { - "start-server", "start", - "", 0, 0, - "", - CMD_STARTSERVER, - NULL, - cmd_start_server_exec -}; - -enum cmd_retval -cmd_start_server_exec(unused struct cmd *self, unused struct cmd_q *cmdq) -{ - return (CMD_RETURN_NORMAL); -} From c930fd5ff696f5a60e93ed503f0ff57e0bbf6e4d Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 28 Jan 2014 22:19:17 +0000 Subject: [PATCH 08/15] Remember the last active pane in the top-bottom or left-right cell so that it can be restored when moving back to that cell with selectp -L/-R/etc. From Suraj N Kurapati. --- tmux.h | 2 ++ window.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/tmux.h b/tmux.h index 0a4f8fb5..b28f10a0 100644 --- a/tmux.h +++ b/tmux.h @@ -1028,6 +1028,8 @@ struct layout_cell { u_int yoff; struct window_pane *wp; + struct window_pane *lastwp; + struct layout_cells cells; TAILQ_ENTRY(layout_cell) entry; diff --git a/window.c b/window.c index 83e14db6..dcb2a5f1 100644 --- a/window.c +++ b/window.c @@ -61,6 +61,10 @@ struct window_pane_tree all_window_panes; u_int next_window_pane_id; u_int next_window_id; +struct window_pane *window_pane_active_set(struct window_pane *, + struct window_pane *); +void window_pane_active_lost(struct window_pane *, struct window_pane *); + void window_pane_timer_callback(int, short, void *); void window_pane_read_callback(struct bufferevent *, void *); void window_pane_error_callback(struct bufferevent *, short, void *); @@ -386,6 +390,59 @@ window_resize(struct window *w, u_int sx, u_int sy) w->sy = sy; } +/* + * Restore previously active pane when changing from wp to nextwp. The intended + * pane is in nextwp and it returns the previously focused pane. + */ +struct window_pane * +window_pane_active_set(struct window_pane *wp, struct window_pane *nextwp) +{ + struct layout_cell *lc; + struct window_pane *lastwp; + + /* Target pane's parent must not be an ancestor of source pane. */ + for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) { + if (lc == nextwp->layout_cell->parent) + return (nextwp); + } + + /* + * Previously active pane, if any, must not be the same as the source + * pane. + */ + if (nextwp->layout_cell->parent != NULL) { + lastwp = nextwp->layout_cell->parent->lastwp; + if (lastwp != wp && window_pane_visible(lastwp)) + return (lastwp); + } + return (nextwp); +} + +/* Remember previously active pane when changing from wp to nextwp. */ +void +window_pane_active_lost(struct window_pane *wp, struct window_pane *nextwp) +{ + struct layout_cell *lc, *lc2; + + /* Save the target pane in its parent. */ + nextwp->layout_cell->parent->lastwp = nextwp; + + /* + * Save the source pane in all of its parents up to, but not including, + * the common ancestor of itself and the target panes. + */ + if (wp == NULL) + return; + for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) { + lc2 = nextwp->layout_cell->parent; + for (; lc2 != NULL; lc2 = lc2->parent) { + if (lc == lc2) + return; + } + lc->lastwp = wp; + } +} + void window_set_active_pane(struct window *w, struct window_pane *wp) { @@ -393,6 +450,7 @@ window_set_active_pane(struct window *w, struct window_pane *wp) return; w->last = w->active; w->active = wp; + window_pane_active_lost(w->last, wp); while (!window_pane_visible(w->active)) { w->active = TAILQ_PREV(w->active, window_panes, entry); if (w->active == NULL) @@ -707,6 +765,16 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) void window_pane_destroy(struct window_pane *wp) { + struct window_pane *wp2; + + /* Forget removed pane in all layout cells that remember it. */ + RB_FOREACH(wp2, window_pane_tree, &all_window_panes) { + if (wp2->layout_cell != NULL && + wp2->layout_cell->parent != NULL && + wp2->layout_cell->parent->lastwp == wp) + wp2->layout_cell->parent->lastwp = NULL; + } + window_pane_reset_mode(wp); if (event_initialized(&wp->changes_timer)) @@ -1130,7 +1198,7 @@ window_pane_find_up(struct window_pane *wp) if (wp2->yoff + wp2->sy + 1 != top) continue; if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx) - return (wp2); + return (window_pane_active_set(wp, wp2)); } return (NULL); } @@ -1156,7 +1224,7 @@ window_pane_find_down(struct window_pane *wp) if (wp2->yoff != bottom) continue; if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx) - return (wp2); + return (window_pane_active_set(wp, wp2)); } return (NULL); } @@ -1185,7 +1253,7 @@ window_pane_find_left(struct window_pane *wp) if (wp2->xoff + wp2->sx + 1 != left) continue; if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy) - return (wp2); + return (window_pane_active_set(wp, wp2)); } return (NULL); } @@ -1214,7 +1282,7 @@ window_pane_find_right(struct window_pane *wp) if (wp2->xoff != right) continue; if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy) - return (wp2); + return (window_pane_active_set(wp, wp2)); } return (NULL); } From 945339b443affdaaca260605e15b5a3b9a3c6e16 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 28 Jan 2014 23:07:09 +0000 Subject: [PATCH 09/15] Allow replacing each of the many sets of separate foo-{fg,bg,attr} options with a single foo-style option. For example: set -g status-fg yellow set -g status-bg red set -g status-attr blink Becomes: set -g status-style fg=yellow,bg=red,blink The -a flag to set can be used to add to rather than replace a style. So: set -g status-bg red Becomes: set -ag status-style bg=red Currently this is fully backwards compatible (all *-{fg,bg,attr} options remain) but the plan is to deprecate them over time. From Tiago Cunha. --- Makefile | 1 + cmd-set-option.c | 28 +++++ grid.c | 1 - options-table.c | 269 +++++++++++++++++++++++++++++----------- options.c | 36 ++++++ screen-redraw.c | 20 +-- screen-write.c | 85 +------------ status.c | 118 +++--------------- style.c | 224 ++++++++++++++++++++++++++++++++++ tmux.1 | 310 ++++++++++++++++++++++++++--------------------- tmux.h | 36 ++++-- tty.c | 3 +- window-choose.c | 4 +- window-copy.c | 4 +- window.c | 10 -- 15 files changed, 710 insertions(+), 439 deletions(-) create mode 100644 style.c diff --git a/Makefile b/Makefile index a0736bdf..e566bb2a 100644 --- a/Makefile +++ b/Makefile @@ -113,6 +113,7 @@ SRCS= arguments.c \ session.c \ signal.c \ status.c \ + style.c \ tmux.c \ tty-acs.c \ tty-keys.c \ diff --git a/cmd-set-option.c b/cmd-set-option.c index 1b25fac0..b661913f 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -60,6 +60,9 @@ struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_q *, struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_q *, const struct options_table_entry *, struct options *, const char *); +struct options_entry *cmd_set_option_style(struct cmd *, struct cmd_q *, + const struct options_table_entry *, struct options *, + const char *); const struct cmd_entry cmd_set_option_entry = { "set-option", "set", @@ -304,9 +307,11 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq, break; case OPTIONS_TABLE_COLOUR: o = cmd_set_option_colour(self, cmdq, oe, oo, value); + style_update_new(oo, o->name, oe->style); break; case OPTIONS_TABLE_ATTRIBUTES: o = cmd_set_option_attributes(self, cmdq, oe, oo, value); + style_update_new(oo, o->name, oe->style); break; case OPTIONS_TABLE_FLAG: o = cmd_set_option_flag(self, cmdq, oe, oo, value); @@ -314,6 +319,9 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq, case OPTIONS_TABLE_CHOICE: o = cmd_set_option_choice(self, cmdq, oe, oo, value); break; + case OPTIONS_TABLE_STYLE: + o = cmd_set_option_style(self, cmdq, oe, oo, value); + break; } if (o == NULL) return (-1); @@ -462,3 +470,23 @@ cmd_set_option_choice(unused struct cmd *self, struct cmd_q *cmdq, return (options_set_number(oo, oe->name, choice)); } + +/* Set a style option. */ +struct options_entry * +cmd_set_option_style(struct cmd *self, struct cmd_q *cmdq, + const struct options_table_entry *oe, struct options *oo, + const char *value) +{ + struct args *args = self->args; + struct options_entry *o; + int append; + + append = args_has(args, 'a'); + if ((o = options_set_style(oo, oe->name, value, append)) == NULL) { + cmdq_error(cmdq, "bad style: %s", value); + return (NULL); + } + + style_update_old(oo, oe->name, &o->style); + return (o); +} diff --git a/grid.c b/grid.c index 852423b5..fb838adf 100644 --- a/grid.c +++ b/grid.c @@ -37,7 +37,6 @@ /* Default grid cell data. */ const struct grid_cell grid_default_cell = { 0, 0, 8, 8, (1 << 4) | 1, " " }; -const struct grid_cell grid_marker_cell = { 0, 0, 8, 8, (1 << 4) | 1, "_" }; #define grid_put_cell(gd, px, py, gc) do { \ memcpy(&gd->linedata[py].celldata[px], \ diff --git a/options-table.c b/options-table.c index 97ca90be..4480b344 100644 --- a/options-table.c +++ b/options-table.c @@ -196,32 +196,43 @@ const struct options_table_entry session_options_table[] = { { .name = "message-attr", .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = 0 + .default_num = 0, + .style = "message-style" }, { .name = "message-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 3 + .default_num = 3, + .style = "message-style" }, { .name = "message-command-attr", .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = 0 + .default_num = 0, + .style = "message-command-style" }, { .name = "message-command-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 0 + .default_num = 0, + .style = "message-command-style" }, { .name = "message-command-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 3 + .default_num = 3, + .style = "message-command-style" + }, + + { .name = "message-command-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "bg=black,fg=yellow" }, { .name = "message-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 0 + .default_num = 0, + .style = "message-style" }, { .name = "message-limit", @@ -231,6 +242,11 @@ const struct options_table_entry session_options_table[] = { .default_num = 20 }, + { .name = "message-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "bg=yellow,fg=black" + }, + { .name = "mouse-resize-pane", .type = OPTIONS_TABLE_FLAG, .default_num = 0 @@ -253,22 +269,36 @@ const struct options_table_entry session_options_table[] = { { .name = "pane-active-border-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "pane-active-border-style" }, { .name = "pane-active-border-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 2 + .default_num = 2, + .style = "pane-active-border-style" + }, + + { .name = "pane-active-border-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "fg=green" }, { .name = "pane-border-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "pane-border-style" }, { .name = "pane-border-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "pane-border-style" + }, + + { .name = "pane-border-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "default" }, { .name = "prefix", @@ -315,17 +345,20 @@ const struct options_table_entry session_options_table[] = { { .name = "status-attr", .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = 0 + .default_num = 0, + .style = "status-style" }, { .name = "status-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 2 + .default_num = 2, + .style = "status-style" }, { .name = "status-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 0 + .default_num = 0, + .style = "status-style" }, { .name = "status-interval", @@ -354,17 +387,20 @@ const struct options_table_entry session_options_table[] = { { .name = "status-left-attr", .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = 0 + .default_num = 0, + .style = "status-left-style" }, { .name = "status-left-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "status-left-style" }, { .name = "status-left-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "status-left-style" }, { .name = "status-left-length", @@ -374,6 +410,11 @@ const struct options_table_entry session_options_table[] = { .default_num = 10 }, + { .name = "status-left-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "default" + }, + { .name = "status-position", .type = OPTIONS_TABLE_CHOICE, .choices = options_table_status_position_list, @@ -387,17 +428,20 @@ const struct options_table_entry session_options_table[] = { { .name = "status-right-attr", .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = 0 + .default_num = 0, + .style = "status-right-style" }, { .name = "status-right-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "status-right-style" }, { .name = "status-right-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "status-right-style" }, { .name = "status-right-length", @@ -407,6 +451,16 @@ const struct options_table_entry session_options_table[] = { .default_num = 40 }, + { .name = "status-right-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "default" + }, + + { .name = "status-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "bg=green,fg=black" + }, + { .name = "status-utf8", .type = OPTIONS_TABLE_FLAG, .default_num = 0 /* overridden in main() */ @@ -537,17 +591,20 @@ const struct options_table_entry window_options_table[] = { { .name = "mode-attr", .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = 0 + .default_num = 0, + .style = "mode-style" }, { .name = "mode-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 3 + .default_num = 3, + .style = "mode-style" }, { .name = "mode-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 0 + .default_num = 0, + .style = "mode-style" }, { .name = "mode-keys", @@ -562,6 +619,11 @@ const struct options_table_entry window_options_table[] = { .default_num = 0 }, + { .name = "mode-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "bg=yellow,fg=black" + }, + { .name = "monitor-activity", .type = OPTIONS_TABLE_FLAG, .default_num = 0 @@ -617,72 +679,101 @@ const struct options_table_entry window_options_table[] = { { .name = "window-status-activity-attr", .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = GRID_ATTR_REVERSE + .default_num = GRID_ATTR_REVERSE, + .style = "window-status-activity-style" }, { .name = "window-status-activity-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "window-status-activity-style" }, { .name = "window-status-activity-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "window-status-activity-style" }, - { .name = "window-status-bell-attr", - .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = GRID_ATTR_REVERSE - }, - - { .name = "window-status-bell-bg", - .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 - }, - - { .name = "window-status-bell-fg", - .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 - }, - - { .name = "window-status-content-attr", - .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = GRID_ATTR_REVERSE - }, - - { .name = "window-status-content-bg", - .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 - }, - - { .name = "window-status-content-fg", - .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + { .name = "window-status-activity-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "reverse" }, { .name = "window-status-attr", .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = 0 + .default_num = 0, + .style = "window-status-style" + }, + + { .name = "window-status-bell-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = GRID_ATTR_REVERSE, + .style = "window-status-bell-style" + }, + + { .name = "window-status-bell-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8, + .style = "window-status-bell-style" + }, + + { .name = "window-status-bell-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8, + .style = "window-status-bell-style" + }, + + { .name = "window-status-bell-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "reverse" }, { .name = "window-status-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "window-status-style" + }, + + { .name = "window-status-content-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = GRID_ATTR_REVERSE, + .style = "window-status-content-style" + }, + + { .name = "window-status-content-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8, + .style = "window-status-content-style" + }, + + { .name = "window-status-content-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8, + .style = "window-status-content-style" + }, + + { .name = "window-status-content-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "reverse" }, { .name = "window-status-current-attr", .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = 0 + .default_num = 0, + .style = "window-status-current-style" }, { .name = "window-status-current-bg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "window-status-current-style" }, { .name = "window-status-current-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "window-status-current-style" }, { .name = "window-status-current-format", @@ -690,24 +781,15 @@ const struct options_table_entry window_options_table[] = { .default_str = "#I:#W#F" }, - { .name = "window-status-last-attr", - .type = OPTIONS_TABLE_ATTRIBUTES, - .default_num = 0 - }, - - { .name = "window-status-last-bg", - .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 - }, - - { .name = "window-status-last-fg", - .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + { .name = "window-status-current-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "default" }, { .name = "window-status-fg", .type = OPTIONS_TABLE_COLOUR, - .default_num = 8 + .default_num = 8, + .style = "window-status-style" }, { .name = "window-status-format", @@ -715,11 +797,39 @@ const struct options_table_entry window_options_table[] = { .default_str = "#I:#W#F" }, + { .name = "window-status-last-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = 0, + .style = "window-status-last-style" + }, + + { .name = "window-status-last-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8, + .style = "window-status-last-style" + }, + + { .name = "window-status-last-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8, + .style = "window-status-last-style" + }, + + { .name = "window-status-last-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "default" + }, + { .name = "window-status-separator", .type = OPTIONS_TABLE_STRING, .default_str = " " }, + { .name = "window-status-style", + .type = OPTIONS_TABLE_STYLE, + .default_str = "default" + }, + { .name = "wrap-search", .type = OPTIONS_TABLE_FLAG, .default_num = 1 @@ -741,10 +851,17 @@ options_table_populate_tree( const struct options_table_entry *oe; for (oe = table; oe->name != NULL; oe++) { - if (oe->default_str != NULL) + switch (oe->type) { + case OPTIONS_TABLE_STRING: options_set_string(oo, oe->name, "%s", oe->default_str); - else + break; + case OPTIONS_TABLE_STYLE: + options_set_style(oo, oe->name, oe->default_str); + break; + default: options_set_number(oo, oe->name, oe->default_num); + break; + } } } @@ -789,6 +906,10 @@ options_table_print_entry(const struct options_table_entry *oe, s = oe->choices[o->num]; xsnprintf(out, sizeof out, "%s", s); break; + case OPTIONS_TABLE_STYLE: + s = style_tostring(&o->style); + xsnprintf(out, sizeof out, "%s", s); + break; } return (out); } diff --git a/options.c b/options.c index 51a6608e..699dd9b0 100644 --- a/options.c +++ b/options.c @@ -109,6 +109,7 @@ options_set_string(struct options *oo, const char *name, const char *fmt, ...) o = xmalloc(sizeof *o); o->name = xstrdup(name); RB_INSERT(options_tree, &oo->tree, o); + memcpy(&o->style, &grid_default_cell, sizeof o->style); } else if (o->type == OPTIONS_STRING) free(o->str); @@ -140,6 +141,7 @@ options_set_number(struct options *oo, const char *name, long long value) o = xmalloc(sizeof *o); o->name = xstrdup(name); RB_INSERT(options_tree, &oo->tree, o); + memcpy(&o->style, &grid_default_cell, sizeof o->style); } else if (o->type == OPTIONS_STRING) free(o->str); @@ -159,3 +161,37 @@ options_get_number(struct options *oo, const char *name) fatalx("option not a number"); return (o->num); } + +struct options_entry * +options_set_style(struct options *oo, const char *name, const char *value, + int append) +{ + struct options_entry *o; + + if ((o = options_find1(oo, name)) == NULL) { + o = xmalloc(sizeof *o); + o->name = xstrdup(name); + RB_INSERT(options_tree, &oo->tree, o); + } else if (o->type == OPTIONS_STRING) + free(o->str); + + if (!append) + memcpy(&o->style, &grid_default_cell, sizeof o->style); + + o->type = OPTIONS_STYLE; + if (style_parse(&grid_default_cell, &o->style, value) == -1) + return (NULL); + return (o); +} + +struct grid_cell * +options_get_style(struct options *oo, const char *name) +{ + struct options_entry *o; + + if ((o = options_find(oo, name)) == NULL) + fatalx("missing option"); + if (o->type != OPTIONS_STYLE) + fatalx("option not a style"); + return (&o->style); +} diff --git a/screen-redraw.c b/screen-redraw.c index 4601c6f3..a67cb952 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -224,7 +224,7 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only) struct window_pane *wp; struct grid_cell active_gc, other_gc; u_int i, j, type, top; - int status, spos, fg, bg; + int status, spos; /* Suspended clients should not be updated. */ if (c->flags & CLIENT_SUSPENDED) @@ -251,17 +251,9 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only) } /* Set up pane border attributes. */ - memcpy(&other_gc, &grid_marker_cell, sizeof other_gc); - memcpy(&active_gc, &grid_marker_cell, sizeof active_gc); - active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET; - fg = options_get_number(oo, "pane-border-fg"); - colour_set_fg(&other_gc, fg); - bg = options_get_number(oo, "pane-border-bg"); - colour_set_bg(&other_gc, bg); - fg = options_get_number(oo, "pane-active-border-fg"); - colour_set_fg(&active_gc, fg); - bg = options_get_number(oo, "pane-active-border-bg"); - colour_set_bg(&active_gc, bg); + style_apply(&other_gc, oo, "pane-border-style"); + style_apply(&active_gc, oo, "pane-active-border-style"); + active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET; /* nuke existing */ /* Draw background and borders. */ for (j = 0; j < tty->sy - status; j++) { @@ -368,7 +360,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp) px -= len * 3; py -= 2; - memcpy(&gc, &grid_marker_cell, sizeof gc); + memcpy(&gc, &grid_default_cell, sizeof gc); if (w->active == wp) colour_set_bg(&gc, active_colour); else @@ -395,7 +387,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp) tty_cursor(tty, xoff + wp->sx - len, yoff); draw_text: - memcpy(&gc, &grid_marker_cell, sizeof gc); + memcpy(&gc, &grid_default_cell, sizeof gc); if (w->active == wp) colour_set_fg(&gc, active_colour); else diff --git a/screen-write.c b/screen-write.c index 7fcfc5ee..3da145e8 100644 --- a/screen-write.c +++ b/screen-write.c @@ -248,7 +248,7 @@ screen_write_cnputs(struct screen_write_ctx *ctx, } *last = '\0'; - screen_write_parsestyle(gc, &lgc, ptr); + style_parse(gc, &lgc, ptr); ptr = last + 1; continue; } @@ -288,89 +288,6 @@ screen_write_cnputs(struct screen_write_ctx *ctx, free(msg); } -/* Parse an embedded style of the form "fg=colour,bg=colour,bright,...". */ -void -screen_write_parsestyle( - struct grid_cell *defgc, struct grid_cell *gc, const char *in) -{ - const char delimiters[] = " ,"; - char tmp[32]; - int val; - size_t end; - u_char fg, bg, attr, flags; - - if (*in == '\0') - return; - if (strchr(delimiters, in[strlen(in) - 1]) != NULL) - return; - - fg = gc->fg; - bg = gc->bg; - attr = gc->attr; - flags = gc->flags; - do { - end = strcspn(in, delimiters); - if (end > (sizeof tmp) - 1) - return; - memcpy(tmp, in, end); - tmp[end] = '\0'; - - if (strcasecmp(tmp, "default") == 0) { - fg = defgc->fg; - bg = defgc->bg; - attr = defgc->attr; - flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256); - flags |= - defgc->flags & (GRID_FLAG_FG256|GRID_FLAG_BG256); - } else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) { - if ((val = colour_fromstring(tmp + 3)) == -1) - return; - if (*in == 'f' || *in == 'F') { - if (val != 8) { - if (val & 0x100) { - flags |= GRID_FLAG_FG256; - val &= ~0x100; - } else - flags &= ~GRID_FLAG_FG256; - fg = val; - } else { - fg = defgc->fg; - flags &= ~GRID_FLAG_FG256; - flags |= defgc->flags & GRID_FLAG_FG256; - } - } else if (*in == 'b' || *in == 'B') { - if (val != 8) { - if (val & 0x100) { - flags |= GRID_FLAG_BG256; - val &= ~0x100; - } else - flags &= ~GRID_FLAG_BG256; - bg = val; - } else { - bg = defgc->bg; - flags &= ~GRID_FLAG_BG256; - flags |= defgc->flags & GRID_FLAG_BG256; - } - } else - return; - } else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) { - if ((val = attributes_fromstring(tmp + 2)) == -1) - return; - attr &= ~val; - } else { - if ((val = attributes_fromstring(tmp)) == -1) - return; - attr |= val; - } - - in += end + strspn(in + end, delimiters); - } while (*in != '\0'); - gc->fg = fg; - gc->bg = bg; - gc->attr = attr; - gc->flags = flags; -} - /* Copy from another screen. */ void screen_write_copy(struct screen_write_ctx *ctx, diff --git a/status.c b/status.c index c5572b74..e14c1a81 100644 --- a/status.c +++ b/status.c @@ -80,18 +80,9 @@ status_redraw_get_left(struct client *c, { struct session *s = c->session; char *left; - int fg, bg, attr; size_t leftlen; - fg = options_get_number(&s->options, "status-left-fg"); - if (fg != 8) - colour_set_fg(gc, fg); - bg = options_get_number(&s->options, "status-left-bg"); - if (bg != 8) - colour_set_bg(gc, bg); - attr = options_get_number(&s->options, "status-left-attr"); - if (attr != 0) - gc->attr = attr; + style_apply_update(gc, &s->options, "status-left-style"); left = status_replace(c, NULL, NULL, NULL, options_get_string(&s->options, "status-left"), t, 1); @@ -110,18 +101,9 @@ status_redraw_get_right(struct client *c, { struct session *s = c->session; char *right; - int fg, bg, attr; size_t rightlen; - fg = options_get_number(&s->options, "status-right-fg"); - if (fg != 8) - colour_set_fg(gc, fg); - bg = options_get_number(&s->options, "status-right-bg"); - if (bg != 8) - colour_set_bg(gc, bg); - attr = options_get_number(&s->options, "status-right-attr"); - if (attr != 0) - gc->attr = attr; + style_apply_update(gc, &s->options, "status-right-style"); right = status_replace(c, NULL, NULL, NULL, options_get_string(&s->options, "status-right"), t, 1); @@ -177,10 +159,7 @@ status_redraw(struct client *c) t = c->status_timer.tv_sec; /* Set up default colour. */ - memcpy(&stdgc, &grid_default_cell, sizeof gc); - colour_set_fg(&stdgc, options_get_number(&s->options, "status-fg")); - colour_set_bg(&stdgc, options_get_number(&s->options, "status-bg")); - stdgc.attr |= options_get_number(&s->options, "status-attr"); + style_apply(&stdgc, &s->options, "status-style"); /* Create the target screen. */ memcpy(&old_status, &c->status, sizeof old_status); @@ -646,73 +625,22 @@ status_print( struct session *s = c->session; const char *fmt; char *text; - int fg, bg, attr; - fg = options_get_number(oo, "window-status-fg"); - if (fg != 8) - colour_set_fg(gc, fg); - bg = options_get_number(oo, "window-status-bg"); - if (bg != 8) - colour_set_bg(gc, bg); - attr = options_get_number(oo, "window-status-attr"); - if (attr != 0) - gc->attr = attr; + style_apply_update(gc, oo, "window-status-style"); fmt = options_get_string(oo, "window-status-format"); if (wl == s->curw) { - fg = options_get_number(oo, "window-status-current-fg"); - if (fg != 8) - colour_set_fg(gc, fg); - bg = options_get_number(oo, "window-status-current-bg"); - if (bg != 8) - colour_set_bg(gc, bg); - attr = options_get_number(oo, "window-status-current-attr"); - if (attr != 0) - gc->attr = attr; + style_apply_update(gc, oo, "window-status-current-style"); fmt = options_get_string(oo, "window-status-current-format"); } - if (wl == TAILQ_FIRST(&s->lastw)) { - fg = options_get_number(oo, "window-status-last-fg"); - if (fg != 8) - colour_set_fg(gc, fg); - bg = options_get_number(oo, "window-status-last-bg"); - if (bg != 8) - colour_set_bg(gc, bg); - attr = options_get_number(oo, "window-status-last-attr"); - if (attr != 0) - gc->attr = attr; - } + if (wl == TAILQ_FIRST(&s->lastw)) + style_apply_update(gc, oo, "window-status-last-style"); - if (wl->flags & WINLINK_BELL) { - fg = options_get_number(oo, "window-status-bell-fg"); - if (fg != 8) - colour_set_fg(gc, fg); - bg = options_get_number(oo, "window-status-bell-bg"); - if (bg != 8) - colour_set_bg(gc, bg); - attr = options_get_number(oo, "window-status-bell-attr"); - if (attr != 0) - gc->attr = attr; - } else if (wl->flags & WINLINK_CONTENT) { - fg = options_get_number(oo, "window-status-content-fg"); - if (fg != 8) - colour_set_fg(gc, fg); - bg = options_get_number(oo, "window-status-content-bg"); - if (bg != 8) - colour_set_bg(gc, bg); - attr = options_get_number(oo, "window-status-content-attr"); - if (attr != 0) - gc->attr = attr; - } else if (wl->flags & (WINLINK_ACTIVITY|WINLINK_SILENCE)) { - fg = options_get_number(oo, "window-status-activity-fg"); - if (fg != 8) - colour_set_fg(gc, fg); - bg = options_get_number(oo, "window-status-activity-bg"); - if (bg != 8) - colour_set_bg(gc, bg); - attr = options_get_number(oo, "window-status-activity-attr"); - if (attr != 0) - gc->attr = attr; - } + if (wl->flags & WINLINK_BELL) + style_apply_update(gc, oo, "window-status-bell-style"); + else if (wl->flags & WINLINK_CONTENT) + style_apply_update(gc, oo, "window-status-content-style"); + else if (wl->flags & (WINLINK_ACTIVITY|WINLINK_SILENCE)) + style_apply_update(gc, oo, "window-status-activity-style"); text = status_replace(c, NULL, wl, NULL, fmt, t, 1); return (text); @@ -814,10 +742,7 @@ status_message_redraw(struct client *c) if (len > c->tty.sx) len = c->tty.sx; - memcpy(&gc, &grid_default_cell, sizeof gc); - colour_set_fg(&gc, options_get_number(&s->options, "message-fg")); - colour_set_bg(&gc, options_get_number(&s->options, "message-bg")); - gc.attr |= options_get_number(&s->options, "message-attr"); + style_apply(&gc, &s->options, "message-style"); screen_write_start(&ctx, NULL, &c->status); @@ -935,18 +860,11 @@ status_prompt_redraw(struct client *c) len = c->tty.sx; off = 0; - memcpy(&gc, &grid_default_cell, sizeof gc); - /* Change colours for command mode. */ - if (c->prompt_mdata.mode == 1) { - colour_set_fg(&gc, options_get_number(&s->options, "message-command-fg")); - colour_set_bg(&gc, options_get_number(&s->options, "message-command-bg")); - gc.attr |= options_get_number(&s->options, "message-command-attr"); - } else { - colour_set_fg(&gc, options_get_number(&s->options, "message-fg")); - colour_set_bg(&gc, options_get_number(&s->options, "message-bg")); - gc.attr |= options_get_number(&s->options, "message-attr"); - } + if (c->prompt_mdata.mode == 1) + style_apply(&gc, &s->options, "message-command-style"); + else + style_apply(&gc, &s->options, "message-style"); screen_write_start(&ctx, NULL, &c->status); diff --git a/style.c b/style.c new file mode 100644 index 00000000..97d5576e --- /dev/null +++ b/style.c @@ -0,0 +1,224 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * Copyright (c) 2014 Tiago Cunha + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "tmux.h" + +/* Parse an embedded style of the form "fg=colour,bg=colour,bright,...". */ +int +style_parse(const struct grid_cell *defgc, struct grid_cell *gc, + const char *in) +{ + const char delimiters[] = " ,"; + char tmp[32]; + int val; + size_t end; + u_char fg, bg, attr, flags; + + if (*in == '\0') + return (0); + if (strchr(delimiters, in[strlen(in) - 1]) != NULL) + return (-1); + + fg = gc->fg; + bg = gc->bg; + attr = gc->attr; + flags = gc->flags; + do { + end = strcspn(in, delimiters); + if (end > (sizeof tmp) - 1) + return (-1); + memcpy(tmp, in, end); + tmp[end] = '\0'; + + if (strcasecmp(tmp, "default") == 0) { + fg = defgc->fg; + bg = defgc->bg; + attr = defgc->attr; + flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256); + flags |= + defgc->flags & (GRID_FLAG_FG256|GRID_FLAG_BG256); + } else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) { + if ((val = colour_fromstring(tmp + 3)) == -1) + return (-1); + if (*in == 'f' || *in == 'F') { + if (val != 8) { + if (val & 0x100) { + flags |= GRID_FLAG_FG256; + val &= ~0x100; + } else + flags &= ~GRID_FLAG_FG256; + fg = val; + } else { + fg = defgc->fg; + flags &= ~GRID_FLAG_FG256; + flags |= defgc->flags & GRID_FLAG_FG256; + } + } else if (*in == 'b' || *in == 'B') { + if (val != 8) { + if (val & 0x100) { + flags |= GRID_FLAG_BG256; + val &= ~0x100; + } else + flags &= ~GRID_FLAG_BG256; + bg = val; + } else { + bg = defgc->bg; + flags &= ~GRID_FLAG_BG256; + flags |= defgc->flags & GRID_FLAG_BG256; + } + } else + return (-1); + } else if (strcasecmp(tmp, "none") == 0) + attr = 0; + else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) { + if ((val = attributes_fromstring(tmp + 2)) == -1) + return (-1); + attr &= ~val; + } else { + if ((val = attributes_fromstring(tmp)) == -1) + return (-1); + attr |= val; + } + + in += end + strspn(in + end, delimiters); + } while (*in != '\0'); + gc->fg = fg; + gc->bg = bg; + gc->attr = attr; + gc->flags = flags; + + return (0); +} + +/* Convert style to a string. */ +const char * +style_tostring(struct grid_cell *gc) +{ + int c, off = 0, comma = 0; + static char s[256]; + + *s = '\0'; + + if (gc->fg != 8) { + if (gc->flags & GRID_FLAG_FG256) + c = gc->fg | 0x100; + else + c = gc->fg; + off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(c)); + comma = 1; + } + + if (gc->bg != 8) { + if (gc->flags & GRID_FLAG_BG256) + c = gc->bg | 0x100; + else + c = gc->bg; + off += xsnprintf(s + off, sizeof s - off, "%sbg=%s", + comma ? "," : "", colour_tostring(c)); + comma = 1; + } + + if (gc->attr != 0 && gc->attr != GRID_ATTR_CHARSET) { + xsnprintf(s + off, sizeof s - off, "%s%s", + comma ? "," : "", attributes_tostring(gc->attr)); + } + + if (*s == '\0') + return ("default"); + return (s); +} + +/* Synchronize new -style option with the old one. */ +void +style_update_new(struct options *oo, const char *name, const char *newname) +{ + int value; + struct grid_cell *gc; + + /* It's a colour or attribute, but with no -style equivalent. */ + if (newname == NULL) + return; + + gc = options_get_style(oo, newname); + value = options_get_number(oo, name); + + if (strstr(name, "-bg") != NULL) + colour_set_bg(gc, value); + else if (strstr(name, "-fg") != NULL) + colour_set_fg(gc, value); + else if (strstr(name, "-attr") != NULL) + gc->attr = value; +} + +/* Synchronize all the old options with the new -style one. */ +void +style_update_old(struct options *oo, const char *name, struct grid_cell *gc) +{ + char newname[128]; + int c, size; + + size = strrchr(name, '-') - name; + + if (gc->flags & GRID_FLAG_BG256) + c = gc->bg | 0x100; + else + c = gc->bg; + xsnprintf(newname, sizeof newname, "%.*s-bg", size, name); + options_set_number(oo, newname, c); + + if (gc->flags & GRID_FLAG_FG256) + c = gc->fg | 0x100; + else + c = gc->fg; + xsnprintf(newname, sizeof newname, "%.*s-fg", size, name); + options_set_number(oo, newname, c); + + xsnprintf(newname, sizeof newname, "%.*s-attr", size, name); + options_set_number(oo, newname, gc->attr); +} + +/* Apply a style. */ +void +style_apply(struct grid_cell *gc, struct options *oo, const char *name) +{ + struct grid_cell *gcp; + + memcpy(gc, &grid_default_cell, sizeof *gc); + gcp = options_get_style(oo, name); + colour_set_fg(gc, gcp->fg); + colour_set_bg(gc, gcp->bg); + gc->attr |= gcp->attr; +} + +/* Apply a style, updating if default. */ +void +style_apply_update(struct grid_cell *gc, struct options *oo, const char *name) +{ + struct grid_cell *gcp; + + gcp = options_get_style(oo, name); + if (gcp->fg != 8) + colour_set_fg(gc, gcp->fg); + if (gcp->bg != 8) + colour_set_bg(gc, gcp->bg); + if (gcp->attr != 0) + gc->attr |= gcp->attr; +} diff --git a/tmux.1 b/tmux.1 index e44a44a6..e0b27b6d 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2060,11 +2060,6 @@ otherwise a session option. If .Fl g is specified, the global session or window option is set. -With -.Fl a , -and if the option expects a string, -.Ar value -is appended to the existing setting. The .Fl u flag unsets an option, so a session inherits the option from the global @@ -2081,6 +2076,32 @@ flag suppresses the informational message (as if the .Ic quiet server option was set). .Pp +With +.Fl a , +and if the option expects a string or a style, +.Ar value +is appended to the existing setting. +For example: +.Bd -literal -offset indent +set -g status-left "foo" +set -ag status-left "bar" +.Ed +.Pp +Will result in +.Ql foobar . +And: +.Bd -literal -offset indent +set -g status-style "bg=red" +set -ag status-style "fg=blue" +.Ed +.Pp +Will result in a red background +.Em and +blue foreground. +Without +.Fl a , +the result would be the default background and a blue foreground. +.Pp Available window options are listed under .Ic set-window-option . .Pp @@ -2272,26 +2293,18 @@ the entire server will lock after .Em all sessions would have locked. This has no effect as a session option; it must be set as a global option. -.It Ic message-attr Ar attributes -Set status line message attributes, where -.Ar attributes -is either -.Ic none -or a comma-delimited list of one or more of: -.Ic bright -(or -.Ic bold ) , -.Ic dim , -.Ic underscore , -.Ic blink , -.Ic reverse , -.Ic hidden , -or -.Ic italics . -.It Ic message-bg Ar colour -Set status line message background colour, where -.Ar colour -is one of: +.It Ic message-command-style Ar style +Set status line message command style, where +.Ar style +is a comma-separated list of characteristics to be specified. +.Pp +These may be +.Ql bg=colour +to set the background colour, +.Ql fg=colour +to set the foreground colour, and a list of attributes as specified below. +.Pp +The colour is one of: .Ic black , .Ic red , .Ic green , @@ -2312,18 +2325,46 @@ from the 256-colour set, or a hexadecimal RGB string such as .Ql #ffffff , which chooses the closest match from the default 256-colour set. -.It Ic message-command-attr Ar attributes -Set status line message attributes when in command mode. -.It Ic message-command-bg Ar colour -Set status line message background colour when in command mode. -.It Ic message-command-fg Ar colour -Set status line message foreground colour when in command mode. -.It Ic message-fg Ar colour -Set status line message foreground colour. +.Pp +The attributes is either +.Ic none +or a comma-delimited list of one or more of: +.Ic bright +(or +.Ic bold ) , +.Ic dim , +.Ic underscore , +.Ic blink , +.Ic reverse , +.Ic hidden , +or +.Ic italics , +to turn an attribute on, or an attribute prefixed with +.Ql no +to turn one off. +.Pp +Examples are: +.Bd -literal -offset indent +fg=yellow,bold,underscore,blink +bg=black,fg=default,noreverse +.Ed +.Pp +With the +.Fl a +flag to the +.Ic set-option +command the new style is added otherwise the existing style is replaced. .It Ic message-limit Ar number Set the number of error or information messages to save in the message log for each client. The default is 20. +.It Ic message-style Ar style +Set status line message style. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. .It Xo Ic mouse-resize-pane .Op Ic on | off .Xc @@ -2347,12 +2388,22 @@ window. .Op Ic on | off .Xc If enabled, request mouse input as UTF-8 on UTF-8 terminals. -.It Ic pane-active-border-bg Ar colour -.It Ic pane-active-border-fg Ar colour -Set the pane border colour for the currently active pane. -.It Ic pane-border-bg Ar colour -.It Ic pane-border-fg Ar colour -Set the pane border colour for panes aside from the active pane. +.It Ic pane-active-border-style Ar style +Set the pane border style for the currently active pane. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. +Attributes are ignored. +.It Ic pane-border-style Ar style +Set the pane border style for paneas aside from the active pane. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. +Attributes are ignored. .It Ic prefix Ar key Set the key accepted as a prefix key. .It Ic prefix2 Ar key @@ -2418,12 +2469,6 @@ option. .Op Ic on | off .Xc Show or hide the status line. -.It Ic status-attr Ar attributes -Set status line attributes. -.It Ic status-bg Ar colour -Set status line background colour. -.It Ic status-fg Ar colour -Set status line foreground colour. .It Ic status-interval Ar interval Update the status bar every .Ar interval @@ -2481,19 +2526,10 @@ section). For details on how the names and titles can be set see the .Sx "NAMES AND TITLES" section. +For a list of allowed attributes see the +.Ic message-command-style +option. .Pp -#[attributes] allows a comma-separated list of attributes to be specified, -these may be -.Ql fg=colour -to set the foreground colour, -.Ql bg=colour -to set the background colour, the name of one of the attributes (listed under -the -.Ic message-attr -option) to turn an attribute on, or an attribute prefixed with -.Ql no -to turn one off, for example -.Ic nobright . Examples are: .Bd -literal -offset indent #(sysctl vm.loadavg) @@ -2509,17 +2545,18 @@ By default, UTF-8 in is not interpreted, to enable UTF-8, use the .Ic status-utf8 option. -.It Ic status-left-attr Ar attributes -Set the attribute of the left part of the status line. -.It Ic status-left-bg Ar colour -Set the background colour of the left part of the status line. -.It Ic status-left-fg Ar colour -Set the foreground colour of the left part of the status line. .It Ic status-left-length Ar length Set the maximum .Ar length of the left component of the status bar. The default is 10. +.It Ic status-left-style Ar style +Set the style of the left part of the status line. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. .It Xo Ic status-position .Op Ic top | bottom .Xc @@ -2538,17 +2575,25 @@ will be passed to character pairs are replaced, and UTF-8 is dependent on the .Ic status-utf8 option. -.It Ic status-right-attr Ar attributes -Set the attribute of the right part of the status line. -.It Ic status-right-bg Ar colour -Set the background colour of the right part of the status line. -.It Ic status-right-fg Ar colour -Set the foreground colour of the right part of the status line. .It Ic status-right-length Ar length Set the maximum .Ar length of the right component of the status bar. The default is 40. +.It Ic status-right-style Ar style +Set the style of the right part of the status line. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. +.It Ic status-style Ar style +Set status line style. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. .It Xo Ic status-utf8 .Op Ic on | off .Xc @@ -2775,15 +2820,6 @@ or .Ic main-vertical layouts. .Pp -.It Ic mode-attr Ar attributes -Set window modes attributes. -.Pp -.It Ic mode-bg Ar colour -Set window modes background colour. -.Pp -.It Ic mode-fg Ar colour -Set window modes foreground colour. -.Pp .It Xo Ic mode-keys .Op Ic vi | emacs .Xc @@ -2809,6 +2845,14 @@ If set to the mouse behaves as set to on, but cannot be used to enter copy mode. .Pp +.It Ic mode-style Ar style +Set window modes style. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. +.Pp .It Xo Ic monitor-activity .Op Ic on | off .Xc @@ -2879,64 +2923,42 @@ Instructs .Nm to expect UTF-8 sequences to appear in this window. .Pp -.It Ic window-status-bell-attr Ar attributes -Set status line attributes for windows which have a bell alert. +.It Ic window-status-activity-style Ar style +Set status line style for windows with an activity alert. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. .Pp -.It Ic window-status-bell-bg Ar colour -Set status line background colour for windows with a bell alert. +.It Ic window-status-bell-style Ar style +Set status line style for windows with a bell alert. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. .Pp -.It Ic window-status-bell-fg Ar colour -Set status line foreground colour for windows with a bell alert. -.Pp -.It Ic window-status-content-attr Ar attributes -Set status line attributes for windows which have a content alert. -.Pp -.It Ic window-status-content-bg Ar colour -Set status line background colour for windows with a content alert. -.Pp -.It Ic window-status-content-fg Ar colour -Set status line foreground colour for windows with a content alert. -.Pp -.It Ic window-status-activity-attr Ar attributes -Set status line attributes for windows which have an activity (or silence) alert. -.Pp -.It Ic window-status-activity-bg Ar colour -Set status line background colour for windows with an activity alert. -.Pp -.It Ic window-status-activity-fg Ar colour -Set status line foreground colour for windows with an activity alert. -.Pp -.It Ic window-status-attr Ar attributes -Set status line attributes for a single window. -.Pp -.It Ic window-status-bg Ar colour -Set status line background colour for a single window. -.Pp -.It Ic window-status-current-attr Ar attributes -Set status line attributes for the currently active window. -.Pp -.It Ic window-status-current-bg Ar colour -Set status line background colour for the currently active window. -.Pp -.It Ic window-status-current-fg Ar colour -Set status line foreground colour for the currently active window. +.It Ic window-status-content-style Ar style +Set status line style for windows with a content alert. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. .Pp .It Ic window-status-current-format Ar string Like .Ar window-status-format , but is the format used when the window is the current window. .Pp -.It Ic window-status-last-attr Ar attributes -Set status line attributes for the last active window. -.Pp -.It Ic window-status-last-bg Ar colour -Set status line background colour for the last active window. -.Pp -.It Ic window-status-last-fg Ar colour -Set status line foreground colour for the last active window. -.Pp -.It Ic window-status-fg Ar colour -Set status line foreground colour for a single window. +.It Ic window-status-current-style Ar style +Set status line style for the currently active window. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. .Pp .It Ic window-status-format Ar string Set the format in which the window is displayed in the status line window list. @@ -2946,10 +2968,26 @@ option for details of special character sequences available. The default is .Ql #I:#W#F . .Pp +.It Ic window-status-last-style Ar style +Set status line style for the last active window. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. +.Pp .It Ic window-status-separator Ar string Sets the separator drawn between windows in the status line. The default is a single space character. .Pp +.It Ic window-status-style Ar style +Set status line style for a single window. +For how to specify +.Ar style , +see the +.Ic message-command-style +option. +.Pp .It Xo Ic xterm-keys .Op Ic on | off .Xc @@ -3288,16 +3326,10 @@ content) is present. .Pp The colour and attributes of the status line may be configured, the entire status line using the -.Ic status-attr , -.Ic status-fg -and -.Ic status-bg -session options and individual windows using the -.Ic window-status-attr , -.Ic window-status-fg -and -.Ic window-status-bg -window options. +.Ic status-style +session option and individual windows using the +.Ic window-status-style +window option. .Pp The status line is automatically refreshed at interval if it has changed, the interval may be controlled with the @@ -3798,7 +3830,7 @@ bind-key C-a send-prefix Turning the status line off, or changing its colour: .Bd -literal -offset indent set-option -g status off -set-option -g status-bg blue +set-option -g status-style bg=blue .Ed .Pp Setting other options, such as the default command, diff --git a/tmux.h b/tmux.h index b28f10a0..b8fd445c 100644 --- a/tmux.h +++ b/tmux.h @@ -726,11 +726,12 @@ struct options_entry { enum { OPTIONS_STRING, OPTIONS_NUMBER, - OPTIONS_DATA, + OPTIONS_STYLE } type; - char *str; - long long num; + char *str; + long long num; + struct grid_cell style; RB_ENTRY(options_entry) entry; }; @@ -1453,7 +1454,8 @@ enum options_table_type { OPTIONS_TABLE_COLOUR, OPTIONS_TABLE_ATTRIBUTES, OPTIONS_TABLE_FLAG, - OPTIONS_TABLE_CHOICE + OPTIONS_TABLE_CHOICE, + OPTIONS_TABLE_STYLE }; struct options_table_entry { @@ -1466,6 +1468,8 @@ struct options_table_entry { const char *default_str; long long default_num; + + const char *style; }; /* Tree of format entries. */ @@ -1577,12 +1581,15 @@ void options_free(struct options *); struct options_entry *options_find1(struct options *, const char *); struct options_entry *options_find(struct options *, const char *); void options_remove(struct options *, const char *); -struct options_entry *printflike3 options_set_string( - struct options *, const char *, const char *, ...); +struct options_entry *printflike3 options_set_string(struct options *, + const char *, const char *, ...); char *options_get_string(struct options *, const char *); -struct options_entry *options_set_number( - struct options *, const char *, long long); +struct options_entry *options_set_number(struct options *, const char *, + long long); long long options_get_number(struct options *, const char *); +struct options_entry *options_set_style(struct options *, const char *, + const char *, int); +struct grid_cell *options_get_style(struct options *, const char *); /* options-table.c */ extern const struct options_table_entry server_options_table[]; @@ -2042,8 +2049,6 @@ void printflike5 screen_write_nputs(struct screen_write_ctx *, ssize_t, struct grid_cell *, int, const char *, ...); void screen_write_vnputs(struct screen_write_ctx *, ssize_t, struct grid_cell *, int, const char *, va_list); -void screen_write_parsestyle( - struct grid_cell *, struct grid_cell *, const char *); void screen_write_putc( struct screen_write_ctx *, struct grid_cell *, u_char); void screen_write_copy(struct screen_write_ctx *, @@ -2173,7 +2178,6 @@ struct window_pane *window_pane_find_right(struct window_pane *); void window_set_name(struct window *, const char *); void window_remove_ref(struct window *); void winlink_clear_flags(struct winlink *); -void window_mode_attrs(struct grid_cell *, struct options *); /* layout.c */ u_int layout_count_cells(struct layout_cell *); @@ -2345,4 +2349,14 @@ int xvasprintf(char **, const char *, va_list); int printflike3 xsnprintf(char *, size_t, const char *, ...); int xvsnprintf(char *, size_t, const char *, va_list); +/* style.c */ +int style_parse(const struct grid_cell *, + struct grid_cell *, const char *); +const char *style_tostring(struct grid_cell *); +void style_update_new(struct options *, const char *, const char *); +void style_update_old(struct options *, const char *, + struct grid_cell *); +void style_apply(struct grid_cell *, struct options *, const char *); +void style_apply_update(struct grid_cell *, struct options *, const char *); + #endif /* TMUX_H */ diff --git a/tty.c b/tty.c index 53b415ff..f5a85992 100644 --- a/tty.c +++ b/tty.c @@ -1354,8 +1354,7 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc) tty_putcode(tty, TTYC_BOLD); if (changed & GRID_ATTR_DIM) tty_putcode(tty, TTYC_DIM); - if (changed & GRID_ATTR_ITALICS) - { + if (changed & GRID_ATTR_ITALICS) { if (tty_term_has(tty->term, TTYC_SITM)) tty_putcode(tty, TTYC_SITM); else diff --git a/window-choose.c b/window-choose.c index 77add5e4..0cf7f66b 100644 --- a/window-choose.c +++ b/window-choose.c @@ -736,7 +736,7 @@ window_choose_write_line( utf8flag = options_get_number(&wp->window->options, "utf8"); memcpy(&gc, &grid_default_cell, sizeof gc); if (data->selected == data->top + py) - window_mode_attrs(&gc, oo); + style_apply(&gc, oo, "mode-style"); screen_write_cursormove(ctx, 0, py); if (data->top + py < ARRAY_LENGTH(&data->list)) { @@ -763,7 +763,7 @@ window_choose_write_line( screen_write_putc(ctx, &gc, ' '); if (data->input_type != WINDOW_CHOOSE_NORMAL) { - window_mode_attrs(&gc, oo); + style_apply(&gc, oo, "mode-style"); xoff = xsnprintf(hdr, sizeof hdr, "%s: %s", data->input_prompt, data->input_str); diff --git a/window-copy.c b/window-copy.c index 48cd4b33..df4ca55a 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1173,7 +1173,7 @@ window_copy_write_line( char hdr[512]; size_t last, xoff = 0, size = 0, limit; - window_mode_attrs(&gc, oo); + style_apply(&gc, oo, "mode-style"); last = screen_size_y(s) - 1; if (py == 0) { @@ -1290,7 +1290,7 @@ window_copy_update_selection(struct window_pane *wp, int may_redraw) return (0); /* Set colours. */ - window_mode_attrs(&gc, oo); + style_apply(&gc, oo, "mode-style"); /* Find top of screen. */ ty = screen_hsize(data->backing) - data->oy; diff --git a/window.c b/window.c index dcb2a5f1..1e11cace 100644 --- a/window.c +++ b/window.c @@ -1315,13 +1315,3 @@ winlink_clear_flags(struct winlink *wl) } } } - -/* Set the grid_cell with fg/bg/attr information when window is in a mode. */ -void -window_mode_attrs(struct grid_cell *gc, struct options *oo) -{ - memcpy(gc, &grid_default_cell, sizeof *gc); - colour_set_fg(gc, options_get_number(oo, "mode-fg")); - colour_set_bg(gc, options_get_number(oo, "mode-bg")); - gc->attr |= options_get_number(oo, "mode-attr"); -} From 62e0ed5d7eac5470e4ad2fbde5034d3fa72343c0 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 28 Jan 2014 23:11:44 +0000 Subject: [PATCH 10/15] Fix missing argument, stupid last minute changes... --- options-table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options-table.c b/options-table.c index 4480b344..ec1d3680 100644 --- a/options-table.c +++ b/options-table.c @@ -856,7 +856,7 @@ options_table_populate_tree( options_set_string(oo, oe->name, "%s", oe->default_str); break; case OPTIONS_TABLE_STYLE: - options_set_style(oo, oe->name, oe->default_str); + options_set_style(oo, oe->name, oe->default_str, 0); break; default: options_set_number(oo, oe->name, oe->default_num); From 1935eb5c1ea697762a142ca5353ade82d9a372a1 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 31 Jan 2014 11:17:20 +0000 Subject: [PATCH 11/15] Add \033[18t window operations from J Raynor. --- input.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/input.c b/input.c index e27250ed..58064ddd 100644 --- a/input.c +++ b/input.c @@ -74,6 +74,7 @@ void input_csi_dispatch_rm(struct input_ctx *); void input_csi_dispatch_rm_private(struct input_ctx *); void input_csi_dispatch_sm(struct input_ctx *); void input_csi_dispatch_sm_private(struct input_ctx *); +void input_csi_dispatch_winops(struct input_ctx *); void input_csi_dispatch_sgr(struct input_ctx *); int input_dcs_dispatch(struct input_ctx *); int input_utf8_open(struct input_ctx *); @@ -154,6 +155,7 @@ enum input_csi_type { INPUT_CSI_SM_PRIVATE, INPUT_CSI_TBC, INPUT_CSI_VPA, + INPUT_CSI_WINOPS, }; /* Control (CSI) command table. */ @@ -188,6 +190,7 @@ const struct input_table_entry input_csi_table[] = { { 'q', " ", INPUT_CSI_DECSCUSR }, { 'r', "", INPUT_CSI_DECSTBM }, { 's', "", INPUT_CSI_SCP }, + { 't', "", INPUT_CSI_WINOPS }, { 'u', "", INPUT_CSI_RCP }, }; @@ -1077,7 +1080,7 @@ input_csi_dispatch(struct input_ctx *ictx) struct screen_write_ctx *sctx = &ictx->ctx; struct screen *s = sctx->s; struct input_table_entry *entry; - int n, m; + int n, m; if (ictx->flags & INPUT_DISCARD) return (0); @@ -1117,6 +1120,9 @@ input_csi_dispatch(struct input_ctx *ictx) m = input_get(ictx, 1, 1, 1); screen_write_cursormove(sctx, m - 1, n - 1); break; + case INPUT_CSI_WINOPS: + input_csi_dispatch_winops(ictx); + break; case INPUT_CSI_CUU: screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); break; @@ -1430,6 +1436,55 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx) } } +/* Handle CSI window operations. */ +void +input_csi_dispatch_winops(struct input_ctx *ictx) +{ + struct window_pane *wp = ictx->wp; + int n, m; + + m = 0; + while ((n = input_get(ictx, m, 0, -1)) != -1) { + switch (n) { + case 1: + case 2: + case 5: + case 6: + case 7: + case 11: + case 13: + case 14: + case 19: + case 20: + case 21: + case 24: + break; + case 3: + case 4: + case 8: + m++; + if (input_get(ictx, m, 0, -1) == -1) + return; + /* FALLTHROUGH */ + case 9: + case 10: + case 22: + case 23: + m++; + if (input_get(ictx, m, 0, -1) == -1) + return; + break; + case 18: + input_reply(ictx, "\033[8;%u;%u", wp->sy, wp->sx); + break; + default: + log_debug("%s: unknown '%c'", __func__, ictx->ch); + break; + } + m++; + } +} + /* Handle CSI SGR. */ void input_csi_dispatch_sgr(struct input_ctx *ictx) From 72d1be5ddd0dbc87f99d5430bb4ee4a295ea193b Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 31 Jan 2014 11:20:28 +0000 Subject: [PATCH 12/15] Fix partial matches with xterm-keys on, from m0viefreak dot cm at googlemail dot com. --- xterm-keys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xterm-keys.c b/xterm-keys.c index 75eb6751..9b5a0a21 100644 --- a/xterm-keys.c +++ b/xterm-keys.c @@ -133,7 +133,7 @@ xterm_keys_match(const char *template, const char *buf, size_t len) do { if (*template != '_' && buf[pos] != *template) return (-1); - } while (pos++ != len && *++template != '\0'); + } while (*++template != '\0' && ++pos != len); if (*template != '\0') /* partial */ return (1); From 9f02feb9d089b1a4639afb52ab0e8212eeb55a7c Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 31 Jan 2014 14:19:24 +0000 Subject: [PATCH 13/15] Break up and simplify screen_redraw_screen. --- screen-redraw.c | 153 +++++++++++++++++++++++++----------------------- server-client.c | 6 +- tmux.h | 2 +- 3 files changed, 84 insertions(+), 77 deletions(-) diff --git a/screen-redraw.c b/screen-redraw.c index a67cb952..3a082cbf 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -29,6 +29,9 @@ int screen_redraw_check_cell(struct client *, u_int, u_int, int screen_redraw_check_active(u_int, u_int, int, struct window *, struct window_pane *); +void screen_redraw_draw_borders(struct client *, int, u_int); +void screen_redraw_draw_panes(struct client *, u_int); +void screen_redraw_draw_status(struct client *, u_int); void screen_redraw_draw_number(struct client *, struct window_pane *); #define CELL_INSIDE 0 @@ -216,15 +219,13 @@ screen_redraw_check_active(u_int px, u_int py, int type, struct window *w, /* Redraw entire screen. */ void -screen_redraw_screen(struct client *c, int status_only, int borders_only) +screen_redraw_screen(struct client *c, int draw_panes, int draw_status, + int draw_borders) { - struct window *w = c->session->curw->window; - struct options *oo = &c->session->options; - struct tty *tty = &c->tty; - struct window_pane *wp; - struct grid_cell active_gc, other_gc; - u_int i, j, type, top; - int status, spos; + struct options *oo = &c->session->options; + struct tty *tty = &c->tty; + u_int top; + int status, spos; /* Suspended clients should not be updated. */ if (c->flags & CLIENT_SUSPENDED) @@ -239,72 +240,15 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only) top = 0; if (status && spos == 0) top = 1; + if (!status) + draw_status = 0; - /* If only drawing status and it is present, don't need the rest. */ - if (status_only && status) { - if (top) - tty_draw_line(tty, &c->status, 0, 0, 0); - else - tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1); - tty_reset(tty); - return; - } - - /* Set up pane border attributes. */ - style_apply(&other_gc, oo, "pane-border-style"); - style_apply(&active_gc, oo, "pane-active-border-style"); - active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET; /* nuke existing */ - - /* Draw background and borders. */ - for (j = 0; j < tty->sy - status; j++) { - if (status_only) { - if (spos == 1 && j != tty->sy - 1) - continue; - else if (spos == 0 && j != 0) - break; - } - for (i = 0; i < tty->sx; i++) { - type = screen_redraw_check_cell(c, i, j, &wp); - if (type == CELL_INSIDE) - continue; - if (screen_redraw_check_active(i, j, type, w, wp)) - tty_attributes(tty, &active_gc); - else - tty_attributes(tty, &other_gc); - tty_cursor(tty, i, top + j); - tty_putc(tty, CELL_BORDERS[type]); - } - } - - /* If only drawing borders, that's it. */ - if (borders_only) - return; - - /* Draw the panes, if necessary. */ - TAILQ_FOREACH(wp, &w->panes, entry) { - if (!window_pane_visible(wp)) - continue; - for (i = 0; i < wp->sy; i++) { - if (status_only) { - if (spos == 1 && wp->yoff + i != tty->sy - 1) - continue; - else if (spos == 0 && wp->yoff + i != 0) - break; - } - tty_draw_line( - tty, wp->screen, i, wp->xoff, top + wp->yoff); - } - if (c->flags & CLIENT_IDENTIFY) - screen_redraw_draw_number(c, wp); - } - - /* Draw the status line. */ - if (status) { - if (top) - tty_draw_line(tty, &c->status, 0, 0, 0); - else - tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1); - } + if (draw_borders) + screen_redraw_draw_borders(c, status, top); + if (draw_panes) + screen_redraw_draw_panes(c, top); + if (draw_status) + screen_redraw_draw_status(c, top); tty_reset(tty); } @@ -326,6 +270,69 @@ screen_redraw_pane(struct client *c, struct window_pane *wp) tty_reset(&c->tty); } +/* Draw the borders. */ +void +screen_redraw_draw_borders(struct client *c, int status, u_int top) +{ + struct window *w = c->session->curw->window; + struct options *oo = &c->session->options; + struct tty *tty = &c->tty; + struct window_pane *wp; + struct grid_cell active_gc, other_gc; + u_int i, j, type; + + style_apply(&other_gc, oo, "pane-border-style"); + style_apply(&active_gc, oo, "pane-active-border-style"); + active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET; + + for (j = 0; j < tty->sy - status; j++) { + for (i = 0; i < tty->sx; i++) { + type = screen_redraw_check_cell(c, i, j, &wp); + if (type == CELL_INSIDE) + continue; + if (screen_redraw_check_active(i, j, type, w, wp)) + tty_attributes(tty, &active_gc); + else + tty_attributes(tty, &other_gc); + tty_cursor(tty, i, top + j); + tty_putc(tty, CELL_BORDERS[type]); + } + } +} + +/* Draw the panes. */ +void +screen_redraw_draw_panes(struct client *c, u_int top) +{ + struct window *w = c->session->curw->window; + struct tty *tty = &c->tty; + struct window_pane *wp; + struct screen *s; + u_int i; + + TAILQ_FOREACH(wp, &w->panes, entry) { + if (!window_pane_visible(wp)) + continue; + s = wp->screen; + for (i = 0; i < wp->sy; i++) + tty_draw_line(tty, s, i, wp->xoff, top + wp->yoff); + if (c->flags & CLIENT_IDENTIFY) + screen_redraw_draw_number(c, wp); + } +} + +/* Draw the status line. */ +void +screen_redraw_draw_status(struct client *c, u_int top) +{ + struct tty *tty = &c->tty; + + if (top) + tty_draw_line(tty, &c->status, 0, 0, 0); + else + tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1); +} + /* Draw number on a pane. */ void screen_redraw_draw_number(struct client *c, struct window_pane *wp) diff --git a/server-client.c b/server-client.c index c6257edb..5a6cb7d9 100644 --- a/server-client.c +++ b/server-client.c @@ -743,7 +743,7 @@ server_client_check_redraw(struct client *c) } if (c->flags & CLIENT_REDRAW) { - screen_redraw_screen(c, 0, 0); + screen_redraw_screen(c, 1, 1, 1); c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS); } else if (c->flags & CLIENT_REDRAWWINDOW) { TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) @@ -757,10 +757,10 @@ server_client_check_redraw(struct client *c) } if (c->flags & CLIENT_BORDERS) - screen_redraw_screen(c, 0, 1); + screen_redraw_screen(c, 0, 0, 1); if (c->flags & CLIENT_STATUS) - screen_redraw_screen(c, 1, 0); + screen_redraw_screen(c, 0, 1, 0); c->tty.flags |= flags; diff --git a/tmux.h b/tmux.h index b8fd445c..c6919622 100644 --- a/tmux.h +++ b/tmux.h @@ -2084,7 +2084,7 @@ void screen_write_setselection(struct screen_write_ctx *, u_char *, u_int); void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); /* screen-redraw.c */ -void screen_redraw_screen(struct client *, int, int); +void screen_redraw_screen(struct client *, int, int, int); void screen_redraw_pane(struct client *, struct window_pane *); /* screen.c */ From 44737b06db6113528fe684a5ba5dcec854a93a6a Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Fri, 31 Jan 2014 21:47:54 +0000 Subject: [PATCH 14/15] Fixup BSD specific things from last merge There's entries for header files we don't use, and the cvsimport doesn't like removing files automatically, etc., and it won't have known to have done this from autoconf's POV, so define that in the correct place, hence the removal of the previously committed Makefile. --- Makefile | 138 ----------------------------------- Makefile.am | 3 +- cmd-server-info.c | 173 -------------------------------------------- cmd-show-messages.c | 1 - 4 files changed, 1 insertion(+), 314 deletions(-) delete mode 100644 Makefile delete mode 100644 cmd-server-info.c diff --git a/Makefile b/Makefile deleted file mode 100644 index e566bb2a..00000000 --- a/Makefile +++ /dev/null @@ -1,138 +0,0 @@ -# $OpenBSD$ - -PROG= tmux -SRCS= arguments.c \ - attributes.c \ - cfg.c \ - client.c \ - clock.c \ - cmd-attach-session.c \ - cmd-bind-key.c \ - cmd-break-pane.c \ - cmd-capture-pane.c \ - cmd-choose-buffer.c \ - cmd-choose-client.c \ - cmd-choose-list.c \ - cmd-choose-tree.c \ - cmd-clear-history.c \ - cmd-clock-mode.c \ - cmd-command-prompt.c \ - cmd-confirm-before.c \ - cmd-copy-mode.c \ - cmd-delete-buffer.c \ - cmd-detach-client.c \ - cmd-display-message.c \ - cmd-display-panes.c \ - cmd-find-window.c \ - cmd-has-session.c \ - cmd-if-shell.c \ - cmd-join-pane.c \ - cmd-kill-pane.c \ - cmd-kill-server.c \ - cmd-kill-session.c \ - cmd-kill-window.c \ - cmd-link-window.c \ - cmd-list-buffers.c \ - cmd-list-clients.c \ - cmd-list-commands.c \ - cmd-list-keys.c \ - cmd-list-panes.c \ - cmd-list-sessions.c \ - cmd-list-windows.c \ - cmd-list.c \ - cmd-load-buffer.c \ - cmd-lock-server.c \ - cmd-move-window.c \ - cmd-new-session.c \ - cmd-new-window.c \ - cmd-paste-buffer.c \ - cmd-pipe-pane.c \ - cmd-refresh-client.c \ - cmd-rename-session.c \ - cmd-rename-window.c \ - cmd-resize-pane.c \ - cmd-respawn-pane.c \ - cmd-respawn-window.c \ - cmd-rotate-window.c \ - cmd-run-shell.c \ - cmd-save-buffer.c \ - cmd-select-layout.c \ - cmd-select-pane.c \ - cmd-select-window.c \ - cmd-send-keys.c \ - cmd-set-buffer.c \ - cmd-set-environment.c \ - cmd-set-option.c \ - cmd-show-environment.c \ - cmd-show-messages.c \ - cmd-show-options.c \ - cmd-source-file.c \ - cmd-split-window.c \ - cmd-string.c \ - cmd-suspend-client.c \ - cmd-swap-pane.c \ - cmd-swap-window.c \ - cmd-switch-client.c \ - cmd-unbind-key.c \ - cmd-unlink-window.c \ - cmd-wait-for.c \ - cmd.c \ - cmd-queue.c \ - colour.c \ - control.c \ - control-notify.c \ - environ.c \ - format.c \ - grid-cell.c \ - grid-view.c \ - grid.c \ - input-keys.c \ - input.c \ - job.c \ - key-bindings.c \ - key-string.c \ - layout-custom.c \ - layout-set.c \ - layout.c \ - log.c \ - mode-key.c \ - names.c \ - notify.c \ - options-table.c \ - options.c \ - paste.c \ - procname.c \ - resize.c \ - screen-redraw.c \ - screen-write.c \ - screen.c \ - server-client.c \ - server-fn.c \ - server-window.c \ - server.c \ - session.c \ - signal.c \ - status.c \ - style.c \ - tmux.c \ - tty-acs.c \ - tty-keys.c \ - tty-term.c \ - tty.c \ - utf8.c \ - window-choose.c \ - window-clock.c \ - window-copy.c \ - window.c \ - xmalloc.c \ - xterm-keys.c - -CDIAGFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2 -CDIAGFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -CDIAGFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare -CDIAGFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align - -LDADD= -lutil -lcurses -levent -DPADD= ${LIBUTIL} ${LIBCURSES} ${LIBEVENT} - -.include diff --git a/Makefile.am b/Makefile.am index 690e466d..e5a7286e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -122,7 +122,6 @@ dist_tmux_SOURCES = \ cmd-select-pane.c \ cmd-select-window.c \ cmd-send-keys.c \ - cmd-server-info.c \ cmd-set-buffer.c \ cmd-set-environment.c \ cmd-set-option.c \ @@ -131,7 +130,6 @@ dist_tmux_SOURCES = \ cmd-show-options.c \ cmd-source-file.c \ cmd-split-window.c \ - cmd-start-server.c \ cmd-string.c \ cmd-suspend-client.c \ cmd-swap-pane.c \ @@ -175,6 +173,7 @@ dist_tmux_SOURCES = \ session.c \ signal.c \ status.c \ + style.c \ tmux.c \ tty-acs.c \ tty-keys.c \ diff --git a/cmd-server-info.c b/cmd-server-info.c deleted file mode 100644 index 3aa5df8a..00000000 --- a/cmd-server-info.c +++ /dev/null @@ -1,173 +0,0 @@ -/* $Id$ */ - -/* - * Copyright (c) 2008 Nicholas Marriott - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include - -#include -#include -#include -#include - -#include "tmux.h" - -/* - * Show various information about server. - */ - -enum cmd_retval cmd_server_info_exec(struct cmd *, struct cmd_q *); - -const struct cmd_entry cmd_server_info_entry = { - "server-info", "info", - "", 0, 0, - "", - 0, - NULL, - cmd_server_info_exec -}; - -enum cmd_retval -cmd_server_info_exec(unused struct cmd *self, struct cmd_q *cmdq) -{ - struct tty_term *term; - struct client *c; - struct session *s; - struct winlink *wl; - struct window *w; - struct window_pane *wp; - struct tty_code *code; - const struct tty_term_code_entry *ent; - struct utsname un; - struct job *job; - struct grid *gd; - struct grid_line *gl; - u_int i, j, k, lines; - size_t size; - char out[80]; - char *tim; - time_t t; - - tim = ctime(&start_time); - *strchr(tim, '\n') = '\0'; - cmdq_print(cmdq, - "tmux " VERSION ", pid %ld, started %s", (long) getpid(), tim); - cmdq_print(cmdq, "socket path %s, debug level %d", socket_path, - debug_level); - if (uname(&un) >= 0) { - cmdq_print(cmdq, "system is %s %s %s %s", - un.sysname, un.release, un.version, un.machine); - } - if (cfg_file != NULL) - cmdq_print(cmdq, "configuration file is %s", cfg_file); - else - cmdq_print(cmdq, "configuration file not specified"); - cmdq_print(cmdq, "protocol version is %d", PROTOCOL_VERSION); - cmdq_print(cmdq, "%s", ""); - - cmdq_print(cmdq, "Clients:"); - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - - cmdq_print(cmdq,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho " - "class=%u] [flags=0x%x/0x%x, references=%u]", i, - c->tty.path, c->ibuf.fd, c->tty.fd, c->session->name, - c->tty.sx, c->tty.sy, c->tty.termname, - c->tty.tio.c_cc[VERASE], c->tty.class, - c->flags, c->tty.flags, c->references); - } - cmdq_print(cmdq, "%s", ""); - - cmdq_print(cmdq, "Sessions: [%zu]", sizeof (struct grid_cell)); - RB_FOREACH(s, sessions, &sessions) { - t = s->creation_time.tv_sec; - tim = ctime(&t); - *strchr(tim, '\n') = '\0'; - - cmdq_print(cmdq, "%2u: %s: %u windows (created %s) [%ux%u] " - "[flags=0x%x]", s->id, s->name, - winlink_count(&s->windows), tim, s->sx, s->sy, s->flags); - RB_FOREACH(wl, winlinks, &s->windows) { - w = wl->window; - cmdq_print(cmdq, "%4u: %s [%ux%u] [flags=0x%x, " - "references=%u, last layout=%d]", wl->idx, w->name, - w->sx, w->sy, w->flags, w->references, - w->lastlayout); - j = 0; - TAILQ_FOREACH(wp, &w->panes, entry) { - lines = size = 0; - gd = wp->base.grid; - for (k = 0; k < gd->hsize + gd->sy; k++) { - gl = &gd->linedata[k]; - if (gl->celldata == NULL) - continue; - lines++; - size += gl->cellsize * - sizeof *gl->celldata; - } - cmdq_print(cmdq, - "%6u: %s %lu %d %u/%u, %zu bytes", j, - wp->tty, (u_long) wp->pid, wp->fd, lines, - gd->hsize + gd->sy, size); - j++; - } - } - } - cmdq_print(cmdq, "%s", ""); - - cmdq_print(cmdq, "Terminals:"); - LIST_FOREACH(term, &tty_terms, entry) { - cmdq_print(cmdq, "%s [references=%u, flags=0x%x]:", - term->name, term->references, term->flags); - for (i = 0; i < NTTYCODE; i++) { - ent = &tty_term_codes[i]; - code = &term->codes[ent->code]; - switch (code->type) { - case TTYCODE_NONE: - cmdq_print(cmdq, "%2u: %s: [missing]", - ent->code, ent->name); - break; - case TTYCODE_STRING: - strnvis(out, code->value.string, sizeof out, - VIS_OCTAL|VIS_TAB|VIS_NL); - cmdq_print(cmdq, "%2u: %s: (string) %s", - ent->code, ent->name, out); - break; - case TTYCODE_NUMBER: - cmdq_print(cmdq, "%2u: %s: (number) %d", - ent->code, ent->name, code->value.number); - break; - case TTYCODE_FLAG: - cmdq_print(cmdq, "%2u: %s: (flag) %s", - ent->code, ent->name, - code->value.flag ? "true" : "false"); - break; - } - } - } - cmdq_print(cmdq, "%s", ""); - - cmdq_print(cmdq, "Jobs:"); - LIST_FOREACH(job, &all_jobs, lentry) { - cmdq_print(cmdq, "%s [fd=%d, pid=%d, status=%d]", - job->cmd, job->fd, job->pid, job->status); - } - - return (CMD_RETURN_NORMAL); -} diff --git a/cmd-show-messages.c b/cmd-show-messages.c index 393ed789..0905c32e 100644 --- a/cmd-show-messages.c +++ b/cmd-show-messages.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "tmux.h" From 57332be8da86f0e40a91d7acd857564e789027a7 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sat, 1 Feb 2014 00:47:04 +0000 Subject: [PATCH 15/15] Tidy up TODO list. --- TODO | 138 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 62 insertions(+), 76 deletions(-) diff --git a/TODO b/TODO index 529b5e8c..b9a83fb4 100644 --- a/TODO +++ b/TODO @@ -18,14 +18,16 @@ - options bits and pieces: * set-remain-on-exit is a complete hack * way to set socket path from config file - * -fg/-bg/-attr is crap - better just foo-style options which accept - fg=,bg=,bright and so on like #[] - format improvements: * option to quote format (#{session_name:quoted}) * formats need conditions for >0 (for #P) * some way to pad # stuff with spaces, #!2T maybe * status stuff is redundant with formats + * last window update time and format for it + * formats to show if a window is linked into multiple sessions, into + multiple attached sessions, and is the active window in multiple + attached sessions? - choose mode improvements: * choose-pane command (augment choose-tree to do this?) @@ -40,108 +42,92 @@ * monitor changes within a region * perhaps monitor /all/ panes in the window not just one -- panning over window (window larger than visible) - -- link panes into multiple windows - - improve mouse support: * bind commands to mouse in different areas? * more fine-grained options * commands executed when clicking on a pattern (URL) + * send arrow key sequences for mouse scroll wheel in alternate screen + * mouse-select-pane will screw up with !MODE_MOUSE_STANDARD (it sets + the flag on w/o checking the others before calling tty_update_mode) - hooks! - warts on current naming: * display-time but message-fg/bg/attr * list-* vs show-* - * server-info * split-window -> split-pane?? -- way to keep a job running just read its last line of output for #() - - better UTF-8 support: * #22T can split in the middle of UTF-8 characters! * window names and titles * message display * prompt input * multibyte key input - -- live update: server started with -U connects to server, requests sessions and - windows, receives file descriptors - -- there are inconsistencies in what we get from old shell and what comes from - config for new sessions and windows - -- multiline status line? - -- support title stack, both internally and externally (restore on detach) - http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions - -- last window update time and format for it - -- bind commands to key sequences -- make it so ALL keys go through a table, - first an implicit table in which C-b is the only default binding to a command - that says "next key from $othertable" and so on. means -n can go away as well + * buffer_sample and the choose-* could show UTF-8 properly - copy/paste improvements: - * case insensitive searching * incremental searching * append to buffer * paste w/o trailing whitespace * named buffers and allow gaps in the stack * command to toggle selection not to move it in copy-mode -- mouse-select-pane will screw up with !MODE_MOUSE_STANDARD (it sets the flag - on w/o checking the others before calling tty_update_mode) +- layout stuff + * way to tag a layout as a number/name + * maybe keep last layout + size around and if size reverts just put it + back + * revamp layouts: they are too complicated, should be more closely + integrated, should support hints, layout sets should just be a + special case of custom layouts, and we should support panes that are + not attached to a cell at all. this could be the time to introduce + panelink to replace layout_cell + * way to set hints/limits about pane size for resizing + * panning over window (window larger than visible) -- way to tag a layout as a number/name +- terminfo bits + * use a better termcap internally instead of screen, perhaps xterm + * use screen-256color when started on 256 colour terminal? + * need a tmux terminfo entry to document the extensions we are using in + upstream terminfo + * support title stack, both internally and externally (restore on + detach) http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions -- optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx +- code cleanup + * instead of separate window and session options, just one master + options list with each option having a type (window or session), then + options on window, on session, and global. for window options we look + window->session->global, and for session we look session->global + * the way pane, window, session destroy is handled is too complicated + and the distinction between session.c, window.c and server-fn.c + functions is not clear. could we just have kill_pane(), + kill_window(), unlink_window(), kill_session() that fix up all data + structures (flagging sessions as dead) and return a value to say + whether clients need to be checked for dead sessions? sort of like + session_detach now but more so. or some other scheme to make it + simpler and clearer? also would be nice to remove/rename server-fn.c + * more readable way to work out the various things commands need to + know about the client, notably: + - is this the config file? (cmdq->c == NULL) + - is this a command client? (cmdq->c != NULL && + cmdq->c->session == NULL) + - is this a control client? + - can i do stdin or stdout to this client? + or even guarantee that cmdq->c != NULL and provide a better way to + tell when in the config file - then we use cmdq->c if we need a + client w/o a session else cmd_current_client + * optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx -- instead of separate window and session options, just one master options list - with each option having a type (window or session), then options on window, - on session, and global. for window options we look window->session->global, - and for session we look session->global +- miscellaneous + * way to keep a job running just read its last line of output for #() + link panes into multiple windows + * live update: server started with -U connects to server, requests + sessions and windows, receives file descriptors + * there are inconsistencies in what we get from old shell and what + comes from config for new sessions and windows + * multiline status line? + * bind commands to key sequences -- make it so ALL keys go through a + table, first an implicit table in which C-b is the only default + binding to a command that says "next key from $othertable" and so + on. means -n can go away as well -- maybe keep last layout + size around and if size reverts just put it back -- way to set hints/limits about pane size for resizing - -- revamp layouts: they are too complicated, should be more closely integrated, - should support hints, layout sets should just be a special case of custom - layouts, and we should support panes that are not attached to a cell at - all. this could be the time to introduce panelink to replace layout_cell - -- use a better termcap internally instead of screen, perhaps xterm - -- use screen-256color when started on 256 colour terminal? - -- we need a tmux terminfo entry to document the extensions we are using in - upstream terminfo - -- send arrow key sequences for mouse scroll wheel when in alternate screen - -- the way pane, window, session destroy is handled is too complicated and the - distinction between session.c, window.c and server-fn.c functions is not - clear. could we just have kill_pane(), kill_window(), unlink_window(), - kill_session() that fix up all data structures (flagging sessions as dead) - and return a value to say whether clients need to be checked for dead - sessions? sort of like session_detach now but more so. or some other scheme - to make it simpler and clearer? also would be nice to remove/rename - server-fn.c - -- more readable way to work out the various things commands need to know about - the client, notably: - - is this the config file? (cmdq->c == NULL) - - is this a command client? (cmdq->c != NULL && cmdq->c->session == NULL) - - is this a control client? - - can i do stdin or stdout to this client? - or even guarantee that cmdq->c != NULL and provide a better way to tell when - in the config file - then we use cmdq->c if we need a client w/o a session - else cmd_current_client - -- buffer_sample and the choose-* could let UTF-8 through and display it - properly. - -- formats to show if a window is linked into multiple sessions, into multiple - attached sessions, and is the active window in multiple attached sessions?