From 5f92f92908b81b4ec66682adb84b9ffc8d83c2f7 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 20 Jun 2019 11:59:59 +0000 Subject: [PATCH] Add a per-pane option set. Pane options inherit from window options (so there should be no change to existing behaviour) and are set and shown with set-option -p and show-options -p. Change remain-on-exit and window-style/window-active-style to be pane options (some others will be changed later). This makes select-pane -P and -g unnecessary so no longer document them (they still work) and no longer document set-window-option and show-window-options in favour of set-option -w and show-options -w. --- cmd-break-pane.c | 2 + cmd-join-pane.c | 2 + cmd-select-pane.c | 18 ++-- cmd-set-option.c | 13 +-- cmd-show-options.c | 26 ++--- cmd-swap-pane.c | 4 + format.c | 2 + input.c | 16 +-- options-table.c | 6 +- options.c | 100 ++++++++++++------ server-fn.c | 2 +- tmux.1 | 255 ++++++++++++++++++++------------------------- tmux.c | 6 +- tmux.h | 27 +++-- tty.c | 44 ++++---- window.c | 55 +++++----- 16 files changed, 300 insertions(+), 278 deletions(-) diff --git a/cmd-break-pane.c b/cmd-break-pane.c index 3b929dee..b4c5b7cd 100644 --- a/cmd-break-pane.c +++ b/cmd-break-pane.c @@ -77,6 +77,8 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item) layout_close_pane(wp); w = wp->window = window_create(w->sx, w->sy); + options_set_parent(wp->options, w->options); + wp->flags |= PANE_STYLECHANGED; TAILQ_INSERT_HEAD(&w->panes, wp, entry); w->active = wp; diff --git a/cmd-join-pane.c b/cmd-join-pane.c index ab245302..4a0c7339 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -140,6 +140,8 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) TAILQ_REMOVE(&src_w->panes, src_wp, entry); src_wp->window = dst_w; + options_set_parent(src_wp->options, dst_w->options); + src_wp->flags |= PANE_STYLECHANGED; TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry); layout_assign_pane(lc, src_wp); diff --git a/cmd-select-pane.c b/cmd-select-pane.c index 92ecb734..52c58dbc 100644 --- a/cmd-select-pane.c +++ b/cmd-select-pane.c @@ -33,8 +33,8 @@ const struct cmd_entry cmd_select_pane_entry = { .name = "select-pane", .alias = "selectp", - .args = { "DdegLlMmP:RT:t:U", 0, 0 }, - .usage = "[-DdegLlMmRU] [-P style] [-T title] " CMD_TARGET_PANE_USAGE, + .args = { "DdegLlMmP:RT:t:U", 0, 0 }, /* -P and -g deprecated */ + .usage = "[-DdeLlMmRU] [-T title] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, @@ -90,9 +90,10 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item) struct window *w = wl->window; struct session *s = item->target.s; struct window_pane *wp = item->target.wp, *lastwp, *markedwp; - struct style *sy = &wp->style; char *pane_title; const char *style; + struct style *sy; + struct options_entry *o; if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) { lastwp = w->last; @@ -144,15 +145,18 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item) if (args_has(self->args, 'P') || args_has(self->args, 'g')) { if ((style = args_get(args, 'P')) != NULL) { - style_set(sy, &grid_default_cell); - if (style_parse(sy, &grid_default_cell, style) == -1) { + o = options_set_style(wp->options, "window-style", 0, + style); + if (o == NULL) { cmdq_error(item, "bad style: %s", style); return (CMD_RETURN_ERROR); } - wp->flags |= PANE_REDRAW; + wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); } - if (args_has(self->args, 'g')) + if (args_has(self->args, 'g')) { + sy = options_get_style(wp->options, "window-style"); cmdq_print(item, "%s", style_tostring(sy)); + } return (CMD_RETURN_NORMAL); } diff --git a/cmd-set-option.c b/cmd-set-option.c index 10b70304..23b45230 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -43,10 +43,10 @@ const struct cmd_entry cmd_set_option_entry = { .name = "set-option", .alias = "set", - .args = { "aFgoqst:uw", 1, 2 }, - .usage = "[-aFgosquw] [-t target-window] option [value]", + .args = { "aFgopqst:uw", 1, 2 }, + .usage = "[-aFgopqsuw] " CMD_TARGET_PANE_USAGE " option [value]", - .target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL }, + .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL }, .flags = CMD_AFTERHOOK, .exec = cmd_set_option_exec @@ -88,11 +88,12 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) struct session *s = fs->s; struct winlink *wl = fs->wl; struct window *w; - enum options_table_scope scope; + struct window_pane *wp; struct options *oo; struct options_entry *parent, *o; char *name, *argument, *value = NULL, *cause; int window, idx, already, error, ambiguous; + int scope; struct style *sy; window = (self->entry == &cmd_set_window_option_entry); @@ -249,8 +250,8 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) alerts_reset_all(); if (strcmp(name, "window-style") == 0 || strcmp(name, "window-active-style") == 0) { - RB_FOREACH(w, windows, &windows) - w->flags |= WINDOW_STYLECHANGED; + RB_FOREACH(wp, window_pane_tree, &all_window_panes) + wp->flags |= PANE_STYLECHANGED; } if (strcmp(name, "pane-border-status") == 0) { RB_FOREACH(w, windows, &windows) diff --git a/cmd-show-options.c b/cmd-show-options.c index 109c6c52..5b22b8bd 100644 --- a/cmd-show-options.c +++ b/cmd-show-options.c @@ -33,16 +33,16 @@ static enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmdq_item *); static void cmd_show_options_print(struct cmd *, struct cmdq_item *, struct options_entry *, int, int); static enum cmd_retval cmd_show_options_all(struct cmd *, struct cmdq_item *, - enum options_table_scope, struct options *); + int, struct options *); const struct cmd_entry cmd_show_options_entry = { .name = "show-options", .alias = "show", - .args = { "AgHqst:vw", 0, 1 }, - .usage = "[-AgHqsvw] [-t target-session|target-window] [option]", + .args = { "AgHpqst:vw", 0, 1 }, + .usage = "[-AgHpqsvw] " CMD_TARGET_PANE_USAGE " [option]", - .target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL }, + .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL }, .flags = CMD_AFTERHOOK, .exec = cmd_show_options_exec @@ -83,9 +83,8 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item) struct session *s = item->target.s; struct winlink *wl = item->target.wl; struct options *oo; - enum options_table_scope scope; char *argument, *name = NULL, *cause; - int window, idx, ambiguous, parent; + int window, idx, ambiguous, parent, scope; struct options_entry *o; window = (self->entry == &cmd_show_window_options_entry); @@ -191,17 +190,18 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item, } static enum cmd_retval -cmd_show_options_all(struct cmd *self, struct cmdq_item *item, - enum options_table_scope scope, struct options *oo) +cmd_show_options_all(struct cmd *self, struct cmdq_item *item, int scope, + struct options *oo) { const struct options_table_entry *oe; struct options_entry *o; struct options_array_item *a; + const char *name; u_int idx; int parent; for (oe = options_table; oe->name != NULL; oe++) { - if (oe->scope != scope) + if (~oe->scope & scope) continue; if ((self->entry != &cmd_show_hooks_entry && @@ -228,15 +228,17 @@ cmd_show_options_all(struct cmd *self, struct cmdq_item *item, cmd_show_options_print(self, item, o, -1, parent); else if ((a = options_array_first(o)) == NULL) { if (!args_has(self->args, 'v')) { + name = options_name(o); if (parent) - cmdq_print(item, "%s*", options_name(o)); + cmdq_print(item, "%s*", name); else - cmdq_print(item, "%s", options_name(o)); + cmdq_print(item, "%s", name); } } else { while (a != NULL) { idx = options_array_item_index(a); - cmd_show_options_print(self, item, o, idx, parent); + cmd_show_options_print(self, item, o, idx, + parent); a = options_array_next(a); } } diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c index 2ad05561..994ad0e8 100644 --- a/cmd-swap-pane.c +++ b/cmd-swap-pane.c @@ -90,7 +90,11 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item) src_wp->layout_cell = dst_lc; src_wp->window = dst_w; + options_set_parent(src_wp->options, dst_w->options); + src_wp->flags |= PANE_STYLECHANGED; dst_wp->window = src_w; + options_set_parent(dst_wp->options, src_w->options); + dst_wp->flags |= PANE_STYLECHANGED; sx = src_wp->sx; sy = src_wp->sy; xoff = src_wp->xoff; yoff = src_wp->yoff; diff --git a/format.c b/format.c index 50b537fa..6b07e67e 100644 --- a/format.c +++ b/format.c @@ -1052,6 +1052,8 @@ format_find(struct format_tree *ft, const char *key, int modifiers) if (~modifiers & FORMAT_TIMESTRING) { o = options_parse_get(global_options, key, &idx, 0); + if (o == NULL && ft->wp != NULL) + o = options_parse_get(ft->wp->options, key, &idx, 0); if (o == NULL && ft->w != NULL) o = options_parse_get(ft->w->options, key, &idx, 0); if (o == NULL) diff --git a/input.c b/input.c index e54b5ac0..3e85e14f 100644 --- a/input.c +++ b/input.c @@ -2347,12 +2347,14 @@ input_osc_10(struct input_ctx *ictx, const char *p) { struct window_pane *wp = ictx->wp; u_int r, g, b; + char tmp[16]; if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3) goto bad; - - wp->style.gc.fg = colour_join_rgb(r, g, b); - wp->flags |= PANE_REDRAW; + xsnprintf(tmp, sizeof tmp, "fg=#%02x%02x%02x", r, g, b); + options_set_style(wp->options, "window-style", 1, tmp); + options_set_style(wp->options, "window-active-style", 1, tmp); + wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); return; @@ -2366,12 +2368,14 @@ input_osc_11(struct input_ctx *ictx, const char *p) { struct window_pane *wp = ictx->wp; u_int r, g, b; + char tmp[16]; if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3) goto bad; - - wp->style.gc.bg = colour_join_rgb(r, g, b); - wp->flags |= PANE_REDRAW; + xsnprintf(tmp, sizeof tmp, "bg=#%02x%02x%02x", r, g, b); + options_set_style(wp->options, "window-style", 1, tmp); + options_set_style(wp->options, "window-active-style", 1, tmp); + wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); return; diff --git a/options-table.c b/options-table.c index 32032f8b..b287d660 100644 --- a/options-table.c +++ b/options-table.c @@ -700,7 +700,7 @@ const struct options_table_entry options_table[] = { { .name = "remain-on-exit", .type = OPTIONS_TABLE_FLAG, - .scope = OPTIONS_TABLE_WINDOW, + .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, .default_num = 0 }, @@ -712,7 +712,7 @@ const struct options_table_entry options_table[] = { { .name = "window-active-style", .type = OPTIONS_TABLE_STYLE, - .scope = OPTIONS_TABLE_WINDOW, + .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, .default_str = "default" }, @@ -725,7 +725,7 @@ const struct options_table_entry options_table[] = { { .name = "window-style", .type = OPTIONS_TABLE_STYLE, - .scope = OPTIONS_TABLE_WINDOW, + .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, .default_str = "default" }, diff --git a/options.c b/options.c index 3bce6041..bbb6af98 100644 --- a/options.c +++ b/options.c @@ -100,7 +100,7 @@ options_parent_table_entry(struct options *oo, const char *s) if (oo->parent == NULL) fatalx("no parent options for %s", s); - o = options_get_only(oo->parent, s); + o = options_get(oo->parent, s); if (o == NULL) fatalx("%s not in parent options", s); return (o->tableentry); @@ -178,6 +178,12 @@ options_free(struct options *oo) free(oo); } +void +options_set_parent(struct options *oo, struct options *parent) +{ + oo->parent = parent; +} + struct options_entry * options_first(struct options *oo) { @@ -545,7 +551,7 @@ options_parse_get(struct options *oo, const char *s, int *idx, int only) } char * -options_match(const char *s, int *idx, int* ambiguous) +options_match(const char *s, int *idx, int *ambiguous) { const struct options_table_entry *oe, *found; char *name; @@ -725,70 +731,96 @@ options_set_style(struct options *oo, const char *name, int append, return (o); } -enum options_table_scope +int options_scope_from_name(struct args *args, int window, const char *name, struct cmd_find_state *fs, struct options **oo, char **cause) { - struct session *s = fs->s; - struct winlink *wl = fs->wl; - const char *target = args_get(args, 't'); - enum options_table_scope scope; + struct session *s = fs->s; + struct winlink *wl = fs->wl; + struct window_pane *wp = fs->wp; + const char *target = args_get(args, 't'); + const struct options_table_entry *oe; + int scope; if (*name == '@') return (options_scope_from_flags(args, window, fs, oo, cause)); - if (options_get_only(global_options, name) != NULL) - scope = OPTIONS_TABLE_SERVER; - else if (options_get_only(global_s_options, name) != NULL) - scope = OPTIONS_TABLE_SESSION; - else if (options_get_only(global_w_options, name) != NULL) - scope = OPTIONS_TABLE_WINDOW; - else { + for (oe = options_table; oe->name != NULL; oe++) { + if (strcmp(oe->name, name) == 0) + break; + } + if (oe->name == NULL) { xasprintf(cause, "unknown option: %s", name); return (OPTIONS_TABLE_NONE); } + scope = oe->scope; - if (scope == OPTIONS_TABLE_SERVER) + switch (scope) { + case OPTIONS_TABLE_SERVER: *oo = global_options; - else if (scope == OPTIONS_TABLE_SESSION) { + break; + case OPTIONS_TABLE_SESSION: if (args_has(args, 'g')) *oo = global_s_options; - else if (s == NULL) { - if (target != NULL) - xasprintf(cause, "no such session: %s", target); - else - xasprintf(cause, "no current session"); - } else + else if (s == NULL && target != NULL) + xasprintf(cause, "no such session: %s", target); + else if (s == NULL) + xasprintf(cause, "no current session"); + else *oo = s->options; - } else if (scope == OPTIONS_TABLE_WINDOW) { + break; + case OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE: + if (args_has(args, 'p')) { + if (wp == NULL && target != NULL) + xasprintf(cause, "no such pane: %s", target); + else if (wp == NULL) + xasprintf(cause, "no current pane"); + else + *oo = wp->options; + break; + } + scope = OPTIONS_TABLE_WINDOW; + /* FALLTHROUGH */ + case OPTIONS_TABLE_WINDOW: if (args_has(args, 'g')) *oo = global_w_options; - else if (wl == NULL) { - if (target != NULL) - xasprintf(cause, "no such window: %s", target); - else - xasprintf(cause, "no current window"); - } else + else if (wl == NULL && target != NULL) + xasprintf(cause, "no such window: %s", target); + else if (wl == NULL) + xasprintf(cause, "no current window"); + else *oo = wl->window->options; + break; } return (scope); } -enum options_table_scope +int options_scope_from_flags(struct args *args, int window, struct cmd_find_state *fs, struct options **oo, char **cause) { - struct session *s = fs->s; - struct winlink *wl = fs->wl; - const char *target = args_get(args, 't'); + struct session *s = fs->s; + struct winlink *wl = fs->wl; + struct window_pane *wp = fs->wp; + const char *target = args_get(args, 't'); if (args_has(args, 's')) { *oo = global_options; return (OPTIONS_TABLE_SERVER); } - if (window || args_has(args, 'w')) { + if (args_has(args, 'p')) { + if (wp == NULL) { + if (target != NULL) + xasprintf(cause, "no such pane: %s", target); + else + xasprintf(cause, "no current pane"); + return (OPTIONS_TABLE_NONE); + } + *oo = wp->options; + return (OPTIONS_TABLE_PANE); + } else if (window || args_has(args, 'w')) { if (args_has(args, 'g')) { *oo = global_w_options; return (OPTIONS_TABLE_WINDOW); diff --git a/server-fn.c b/server-fn.c index 372bf21d..25d3aeb1 100644 --- a/server-fn.c +++ b/server-fn.c @@ -307,7 +307,7 @@ server_destroy_pane(struct window_pane *wp, int notify) wp->fd = -1; } - if (options_get_number(w->options, "remain-on-exit")) { + if (options_get_number(wp->options, "remain-on-exit")) { if (~wp->flags & PANE_STATUSREADY) return; diff --git a/tmux.1 b/tmux.1 index 4b3568f3..ec7fdc31 100644 --- a/tmux.1 +++ b/tmux.1 @@ -876,7 +876,7 @@ refresh-client -t/dev/ttyp2 rename-session -tfirst newname -set-window-option -t:0 monitor-activity on +set-option -wt:0 monitor-activity on new-window ; split-window -d @@ -2323,8 +2323,7 @@ applies the last set layout if possible (undoes the most recent layout change). .Fl E spreads the current pane and any panes next to it out evenly. .It Xo Ic select-pane -.Op Fl DdegLlMmRU -.Op Fl P Ar style +.Op Fl DdeLlMmRU .Op Fl T Ar title .Op Fl t Ar target-pane .Xc @@ -2351,6 +2350,8 @@ command. enables or .Fl d disables input to the pane. +.Fl T +sets the pane title. .Pp .Fl m and @@ -2365,25 +2366,6 @@ to .Ic swap-pane and .Ic swap-window . -.Pp -Each pane has a style: by default the -.Ic window-style -and -.Ic window-active-style -options are used, -.Ic select-pane -.Fl P -sets the style for a single pane. -For example, to set the pane 1 background to red: -.Bd -literal -offset indent -select-pane -t:.1 -P 'bg=red' -.Ed -.Pp -.Fl g -shows the current pane style. -.Pp -.Fl T -sets the pane title. .It Xo Ic select-window .Op Fl lnpT .Op Fl t Ar target-window @@ -2702,16 +2684,17 @@ is present, all key bindings are removed. The appearance and behaviour of .Nm may be modified by changing the value of various options. -There are three types of option: +There are four types of option: .Em server options , .Em session options +.Em window options and -.Em window options . +.Em pane options . .Pp The .Nm server has a set of global options which do not apply to any particular -window or session. +window or session or pane. These are altered with the .Ic set-option .Fl s @@ -2733,16 +2716,29 @@ The available server and session options are listed under the .Ic set-option command. .Pp -Similarly, a set of window options is attached to each window, and there is -a set of global window options from which any unset options are inherited. -Window options are altered with the -.Ic set-window-option -command and can be listed with the -.Ic show-window-options -command. -All window options are documented with the -.Ic set-window-option -command. +Similarly, a set of window options is attached to each window and a set of pane +options to each pane. +Pane options inherit from window options. +This means any pane option may be set as a window option to apply the option to +all panes in the window without the option set, for example these commands will +set the background colour to red for all panes except pane 0: +.Bd -literal -offset indent +set -w window-style bg=red +set -pt:.0 window-style bg=blue +.Ed +.Pp +There is also a set of global window options from which any unset window or +pane options are inherited. +Window and pane options are altered with +.Ic set-option +.Fl w +and +.Fl p +commands and displayed with +.Ic show-option +.Fl w +and +.Fl p . .Pp .Nm also supports user options which are prefixed with a @@ -2760,26 +2756,27 @@ abc123 Commands which set options are as follows: .Bl -tag -width Ds .It Xo Ic set-option -.Op Fl aFgoqsuw -.Op Fl t Ar target-session | Ar target-window +.Op Fl aFgopqsuw +.Op Fl t Ar target-pane .Ar option Ar value .Xc .D1 (alias: Ic set ) -Set a window option with -.Fl w -(equivalent to the -.Ic set-window-option -command), +Set a pane option with +.Fl p , +a window option with +.Fl w , a server option with .Fl s , otherwise a session option. If the option is not a user option, .Fl w -and +or .Fl s -are unnecessary - +may be unnecessary - .Nm -will infer the type from the option name. +will infer the type from the option name, assuming +.Fl w +for pane options. If .Fl g is given, the global session or window option is set. @@ -2824,13 +2821,49 @@ 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 +.It Xo Ic show-options +.Op Fl AgHpqsvw +.Op Fl t Ar target-pane +.Op Ar option +.Xc +.D1 (alias: Ic show ) +Show the pane options (or a single option if +.Ar option +is provided) with +.Fl p , +the window options with +.Fl w , +the server options with +.Fl s , +otherwise the session options. +If the option is not a user option, +.Fl w +or +.Fl s +may be unnecessary - +.Nm +will infer the type from the option name, assuming +.Fl w +for pane options. +Global session or window options are listed if +.Fl g +is used. +.Fl v +shows only the option value, not the name. +If +.Fl q +is set, no error will be returned if +.Ar option +is unset. +.Fl H +includes hooks (omitted by default). +.Fl A +includes options inherited from a parent set of options, such options are +marked with an asterisk. .Ar value depends on the option and may be a number, a string, or a flag (on, off, or omitted to toggle). +.El .Pp Available server options are: .Bl -tag -width Ds @@ -3357,26 +3390,8 @@ copy mode. The default is .Ql \ -_@ . .El -.It Xo Ic set-window-option -.Op Fl aFgoqu -.Op Fl t Ar target-window -.Ar option Ar value -.Xc -.D1 (alias: Ic setw ) -Set a window option. -The -.Fl a , -.Fl F , -.Fl g , -.Fl o , -.Fl q -and -.Fl u -flags work similarly to the -.Ic set-option -command. .Pp -Supported window options are: +Available window options are: .Pp .Bl -tag -width Ds -compact .It Xo Ic aggressive-resize @@ -3436,7 +3451,7 @@ or later with or with a terminal escape sequence. It may be switched off globally with: .Bd -literal -offset indent -set-window-option -g automatic-rename off +set-option -wg automatic-rename off .Ed .Pp .It Ic automatic-rename-format Ar format @@ -3553,29 +3568,12 @@ see the section. Attributes are ignored. .Pp -.It Xo Ic remain-on-exit -.Op Ic on | off -.Xc -A window with this flag set is not destroyed when the program running in it -exits. -The window may be reactivated with the -.Ic respawn-window -command. -.Pp .It Xo Ic synchronize-panes .Op Ic on | off .Xc Duplicate input to any pane to all other panes in the same window (only for panes that are not in any special mode). .Pp -.It Ic window-active-style Ar style -Set the style for the window's active pane. -For how to specify -.Ar style , -see the -.Sx STYLES -section. -.Pp .It Ic window-status-activity-style Ar style Set status line style for windows with an activity alert. For how to specify @@ -3655,14 +3653,6 @@ command and the .Ic aggressive-resize option. .Pp -.It Ic window-style Ar style -Set the default window style. -For how to specify -.Ar style , -see the -.Sx STYLES -section. -.Pp .It Xo Ic wrap-search .Op Ic on | off .Xc @@ -3679,57 +3669,34 @@ will generate function key sequences; these have a number included to indicate modifiers such as Shift, Alt or Ctrl. .El -.It Xo Ic show-options -.Op Fl AgHqsvw -.Op Fl t Ar target-session | Ar target-window -.Op Ar option +.Pp +Available pane options are: +.Pp +.Bl -tag -width Ds -compact +.It Xo Ic remain-on-exit +.Op Ic on | off .Xc -.D1 (alias: Ic show ) -Show the window options (or a single window option if given) with -.Fl w -(equivalent to -.Ic show-window-options ) , -the server options with -.Fl s , -otherwise the session options for -.Ar target session . -If -.Ar option -is given and is not a user option, -.Fl w -and -.Fl s -are unnecessary - -.Nm -will infer the type from the option name. -Global session or window options are listed if -.Fl g -is used. -.Fl v -shows only the option value, not the name. -If -.Fl q -is set, no error will be returned if -.Ar option -is unset. -.Fl H -includes hooks (omitted by default). -.Fl A -includes options inherited from a parent set of options, such options are -marked with an asterisk. -.It Xo Ic show-window-options -.Op Fl gv -.Op Fl t Ar target-window -.Op Ar option -.Xc -.D1 (alias: Ic showw ) -List the window options or a single option for -.Ar target-window , -or the global window options if -.Fl g -is used. -.Fl v -shows only the option value, not the name. +A pane with this flag set is not destroyed when the program running in it +exits. +The pane may be reactivated with the +.Ic respawn-pane +command. +.Pp +.It Ic window-active-style Ar style +Set the pane style when it is the active pane. +For how to specify +.Ar style , +see the +.Sx STYLES +section. +.Pp +.It Ic window-style Ar style +Set the pane style. +For how to specify +.Ar style , +see the +.Sx STYLES +section. .El .Sh HOOKS .Nm diff --git a/tmux.c b/tmux.c index ac8a131a..c3fe3ee6 100644 --- a/tmux.c +++ b/tmux.c @@ -321,11 +321,11 @@ main(int argc, char **argv) global_s_options = options_create(NULL); global_w_options = options_create(NULL); for (oe = options_table; oe->name != NULL; oe++) { - if (oe->scope == OPTIONS_TABLE_SERVER) + if (oe->scope & OPTIONS_TABLE_SERVER) options_default(global_options, oe); - if (oe->scope == OPTIONS_TABLE_SESSION) + if (oe->scope & OPTIONS_TABLE_SESSION) options_default(global_s_options, oe); - if (oe->scope == OPTIONS_TABLE_WINDOW) + if (oe->scope & OPTIONS_TABLE_WINDOW) options_default(global_w_options, oe); } diff --git a/tmux.h b/tmux.h index 0557e98d..8adfcba8 100644 --- a/tmux.h +++ b/tmux.h @@ -810,6 +810,7 @@ struct window_pane { u_int active_point; struct window *window; + struct options *options; struct layout_cell *layout_cell; struct layout_cell *saved_layout_cell; @@ -836,6 +837,7 @@ struct window_pane { #define PANE_STATUSREADY 0x200 #define PANE_STATUSDRAWN 0x400 #define PANE_EMPTY 0x800 +#define PANE_STYLECHANGED 0x1000 int argc; char **argv; @@ -854,7 +856,8 @@ struct window_pane { struct input_ctx *ictx; - struct style style; + struct style cached_style; + struct style cached_active_style; int *palette; int pipe_fd; @@ -914,7 +917,6 @@ struct window { #define WINDOW_ACTIVITY 0x2 #define WINDOW_SILENCE 0x4 #define WINDOW_ZOOMED 0x8 -#define WINDOW_STYLECHANGED 0x10 #define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE) int alerts_queued; @@ -922,9 +924,6 @@ struct window { struct options *options; - struct style style; - struct style active_style; - u_int references; TAILQ_HEAD(, winlink) winlinks; @@ -1605,12 +1604,11 @@ enum options_table_type { OPTIONS_TABLE_COMMAND }; -enum options_table_scope { - OPTIONS_TABLE_NONE, - OPTIONS_TABLE_SERVER, - OPTIONS_TABLE_SESSION, - OPTIONS_TABLE_WINDOW -}; +#define OPTIONS_TABLE_NONE 0 +#define OPTIONS_TABLE_SERVER 0x1 +#define OPTIONS_TABLE_SESSION 0x2 +#define OPTIONS_TABLE_WINDOW 0x4 +#define OPTIONS_TABLE_PANE 0x8 #define OPTIONS_TABLE_IS_ARRAY 0x1 #define OPTIONS_TABLE_IS_HOOK 0x2 @@ -1618,7 +1616,7 @@ enum options_table_scope { struct options_table_entry { const char *name; enum options_table_type type; - enum options_table_scope scope; + int scope; int flags; u_int minimum; @@ -1780,6 +1778,7 @@ void notify_pane(const char *, struct window_pane *); /* options.c */ struct options *options_create(struct options *); void options_free(struct options *); +void options_set_parent(struct options *, struct options *); struct options_entry *options_first(struct options *); struct options_entry *options_next(struct options_entry *); struct options_entry *options_empty(struct options *, @@ -1819,10 +1818,10 @@ struct options_entry *options_set_number(struct options *, const char *, long long); struct options_entry *options_set_style(struct options *, const char *, int, const char *); -enum options_table_scope options_scope_from_name(struct args *, int, +int options_scope_from_name(struct args *, int, const char *, struct cmd_find_state *, struct options **, char **); -enum options_table_scope options_scope_from_flags(struct args *, int, +int options_scope_from_flags(struct args *, int, struct cmd_find_state *, struct options **, char **); /* options-table.c */ diff --git a/tty.c b/tty.c index 05df4f0f..8d3b2858 100644 --- a/tty.c +++ b/tty.c @@ -2132,7 +2132,7 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc, /* Ignore cell if it is the same as the last one. */ if (wp != NULL && (int)wp->id == tty->last_wp && - ~(wp->window->flags & WINDOW_STYLECHANGED) && + ~(wp->flags & PANE_STYLECHANGED) && gc->attr == tty->last_cell.attr && gc->fg == tty->last_cell.fg && gc->bg == tty->last_cell.bg) @@ -2514,30 +2514,28 @@ fallback_256: static void tty_default_colours(struct grid_cell *gc, struct window_pane *wp) { - struct window *w = wp->window; - struct options *oo = w->options; - struct style *active, *pane, *window; - int c; + struct options *oo = wp->options; + struct style *style, *active_style; + int c; - if (w->flags & WINDOW_STYLECHANGED) { - w->flags &= ~WINDOW_STYLECHANGED; - active = options_get_style(oo, "window-active-style"); - style_copy(&w->active_style, active); - window = options_get_style(oo, "window-style"); - style_copy(&w->style, window); + if (wp->flags & PANE_STYLECHANGED) { + wp->flags &= ~PANE_STYLECHANGED; + + active_style = options_get_style(oo, "window-active-style"); + style = options_get_style(oo, "window-style"); + + style_copy(&wp->cached_active_style, active_style); + style_copy(&wp->cached_style, style); } else { - active = &w->active_style; - window = &w->style; + active_style = &wp->cached_active_style; + style = &wp->cached_style; } - pane = &wp->style; if (gc->fg == 8) { - if (pane->gc.fg != 8) - gc->fg = pane->gc.fg; - else if (wp == w->active && active->gc.fg != 8) - gc->fg = active->gc.fg; + if (wp == wp->window->active && active_style->gc.fg != 8) + gc->fg = active_style->gc.fg; else - gc->fg = window->gc.fg; + gc->fg = style->gc.fg; if (gc->fg != 8) { c = window_pane_get_palette(wp, gc->fg); @@ -2547,12 +2545,10 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp) } if (gc->bg == 8) { - if (pane->gc.bg != 8) - gc->bg = pane->gc.bg; - else if (wp == w->active && active->gc.bg != 8) - gc->bg = active->gc.bg; + if (wp == wp->window->active && active_style->gc.bg != 8) + gc->bg = active_style->gc.bg; else - gc->bg = window->gc.bg; + gc->bg = style->gc.bg; if (gc->bg != 8) { c = window_pane_get_palette(wp, gc->bg); diff --git a/window.c b/window.c index e7941c70..25784454 100644 --- a/window.c +++ b/window.c @@ -313,7 +313,7 @@ window_create(u_int sx, u_int sy) w = xcalloc(1, sizeof *w); w->name = NULL; - w->flags = WINDOW_STYLECHANGED; + w->flags = 0; TAILQ_INIT(&w->panes); w->active = NULL; @@ -450,31 +450,37 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify) void window_redraw_active_switch(struct window *w, struct window_pane *wp) { - struct style *sy; + struct style *sy1, *sy2; + int c1, c2; if (wp == w->active) return; - /* - * If window-style and window-active-style are the same, we don't need - * to redraw panes when switching active panes. - */ - sy = options_get_style(w->options, "window-active-style"); - if (style_equal(sy, options_get_style(w->options, "window-style"))) - return; - - /* - * If the now active or inactive pane do not have a custom style or if - * the palette is different, they need to be redrawn. - */ - if (window_pane_get_palette(w->active, w->active->style.gc.fg) != -1 || - window_pane_get_palette(w->active, w->active->style.gc.bg) != -1 || - style_is_default(&w->active->style)) - w->active->flags |= PANE_REDRAW; - if (window_pane_get_palette(wp, wp->style.gc.fg) != -1 || - window_pane_get_palette(wp, wp->style.gc.bg) != -1 || - style_is_default(&wp->style)) - wp->flags |= PANE_REDRAW; + for (;;) { + /* + * If the active and inactive styles or palettes are different, + * need to redraw the panes. + */ + sy1 = &wp->cached_style; + sy2 = &wp->cached_active_style; + if (!style_equal(sy1, sy2)) + wp->flags |= PANE_REDRAW; + else { + c1 = window_pane_get_palette(wp, sy1->gc.fg); + c2 = window_pane_get_palette(wp, sy2->gc.fg); + if (c1 != c2) + wp->flags |= PANE_REDRAW; + else { + c1 = window_pane_get_palette(wp, sy1->gc.bg); + c2 = window_pane_get_palette(wp, sy2->gc.bg); + if (c1 != c2) + wp->flags |= PANE_REDRAW; + } + } + if (wp == w->active) + break; + wp = w->active; + } } struct window_pane * @@ -778,6 +784,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) wp = xcalloc(1, sizeof *wp); wp->window = w; + wp->options = options_create(w->options); + wp->flags = PANE_STYLECHANGED; wp->id = next_window_pane_id++; RB_INSERT(window_pane_tree, &all_window_panes, wp); @@ -808,8 +816,6 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) wp->saved_cx = UINT_MAX; wp->saved_cy = UINT_MAX; - style_set(&wp->style, &grid_default_cell); - screen_init(&wp->base, sx, sy, hlimit); wp->screen = &wp->base; @@ -852,6 +858,7 @@ window_pane_destroy(struct window_pane *wp) RB_REMOVE(window_pane_tree, &all_window_panes, wp); + options_free(wp->options); free((void *)wp->cwd); free(wp->shell); cmd_free_argv(wp->argc, wp->argv);