diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c index 186672f4..1dfb04f5 100644 --- a/cmd-choose-tree.c +++ b/cmd-choose-tree.c @@ -33,8 +33,8 @@ const struct cmd_entry cmd_choose_tree_entry = { .name = "choose-tree", .alias = NULL, - .args = { "F:f:GK:NO:rst:wyZ", 0, 1, cmd_choose_tree_args_parse }, - .usage = "[-GNrswZ] [-F format] [-f filter] [-K key-format] " + .args = { "F:f:GK:kNO:rst:wyZ", 0, 1, cmd_choose_tree_args_parse }, + .usage = "[-GkNrswZ] [-F format] [-f filter] [-K key-format] " "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -47,8 +47,8 @@ const struct cmd_entry cmd_choose_client_entry = { .name = "choose-client", .alias = NULL, - .args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse }, - .usage = "[-NrZ] [-F format] [-f filter] [-K key-format] " + .args = { "F:f:K:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse }, + .usage = "[-kNrZ] [-F format] [-f filter] [-K key-format] " "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -61,8 +61,8 @@ const struct cmd_entry cmd_choose_buffer_entry = { .name = "choose-buffer", .alias = NULL, - .args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse }, - .usage = "[-NrZ] [-F format] [-f filter] [-K key-format] " + .args = { "F:f:K:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse }, + .usage = "[-kNrZ] [-F format] [-f filter] [-K key-format] " "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -75,8 +75,8 @@ const struct cmd_entry cmd_customize_mode_entry = { .name = "customize-mode", .alias = NULL, - .args = { "F:f:Nt:yZ", 0, 0, NULL }, - .usage = "[-NZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE, + .args = { "F:f:kNt:yZ", 0, 0, NULL }, + .usage = "[-kNZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, diff --git a/cmd-display-panes.c b/cmd-display-panes.c index efa7c7e4..5a1782ff 100644 --- a/cmd-display-panes.c +++ b/cmd-display-panes.c @@ -76,6 +76,40 @@ cmd_display_panes_put(struct screen_redraw_ctx *ctx, } } +static void +cmd_display_panes_draw_format(struct screen_redraw_ctx *ctx, + struct window_pane *wp, u_int xoff, u_int yoff, u_int sx, + const struct grid_cell *gc) +{ + struct client *c = ctx->c; + struct tty *tty = &c->tty; + struct session *s = c->session; + struct screen screen; + struct screen_write_ctx sctx; + struct visible_ranges *r; + struct visible_range *ri; + const char *format; + char *expanded; + u_int i, px = ctx->ox + xoff; + + format = options_get_string(s->options, "display-panes-format"); + expanded = format_single(NULL, format, c, s, s->curw, wp); + + screen_init(&screen, sx, 1, 0); + screen_write_start(&sctx, &screen); + format_draw(&sctx, gc, sx, expanded, NULL, 0); + screen_write_stop(&sctx); + free(expanded); + + r = screen_redraw_get_visible_ranges(wp, px, wp->yoff, sx, NULL); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + tty_draw_line(tty, &screen, ri->px - px, 0, ri->nx, + ri->px - ctx->ox, yoff, gc, NULL); + } + screen_free(&screen); +} + static void cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) @@ -89,8 +123,8 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy; u_int cx, cy; int colour, active_colour; - char buf[16], lbuf[16], rbuf[16], *ptr; - size_t len, llen, rlen; + char buf[16], lbuf[16], *ptr; + size_t len, llen; if (wp->xoff + (int)wp->sx <= ctx->ox || wp->xoff >= ctx->ox + (int)ctx->sx || @@ -159,7 +193,6 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, bgc.bg = colour; } - rlen = xsnprintf(rbuf, sizeof rbuf, "%ux%u", wp->sx, wp->sy); if (pane > 9 && pane < 35) llen = xsnprintf(lbuf, sizeof lbuf, "%c", 'a' + (pane - 10)); else @@ -207,13 +240,9 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, if (sy <= 6) goto out; - tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL); - if (rlen != 0 && sx >= rlen) { - cx = xoff + sx - rlen; - cy = yoff; - cmd_display_panes_put(ctx, wp, cx, cy, rbuf, rlen); - } + cmd_display_panes_draw_format(ctx, wp, xoff, yoff, sx, &fgc); if (llen != 0) { + tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL); cx = xoff + sx / 2 + len * 3 - llen - 1; cy = yoff + py + 5; cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen); diff --git a/cmd-split-window.c b/cmd-split-window.c index 97fa9ae3..77576901 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -38,11 +38,11 @@ const struct cmd_entry cmd_new_pane_entry = { .name = "new-pane", .alias = "newp", - .args = { "bc:de:EfF:hIkl:Lm:p:PR:s:S:t:vx:X:y:Y:Z", 0, -1, NULL }, + .args = { "bc:de:EfF:hIkl:Lm:p:PR:s:S:t:T:vx:X:y:Y:Z", 0, -1, NULL }, .usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] " "[-F format] [-l size] [-m message] [-p percentage] " "[-s style] [-S active-border-style] " - "[-R inactive-border-style] [-x width] [-y height] " + "[-R inactive-border-style] [-T title] [-x width] [-y height] " "[-X x-position] [-Y y-position] " CMD_TARGET_PANE_USAGE " " "[shell-command [argument ...]]", @@ -56,11 +56,11 @@ const struct cmd_entry cmd_split_window_entry = { .name = "split-window", .alias = "splitw", - .args = { "bc:de:EfF:hIkl:m:p:PR:s:S:t:vZ", 0, -1, NULL }, + .args = { "bc:de:EfF:hIkl:m:p:PR:s:S:t:T:vZ", 0, -1, NULL }, .usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] " "[-F format] [-l size] [-m message] [-p percentage] " "[-s style] [-S active-border-style] " - "[-R inactive-border-style] " CMD_TARGET_PANE_USAGE " " + "[-R inactive-border-style] [-T title] " CMD_TARGET_PANE_USAGE " " "[shell-command [argument ...]]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -85,7 +85,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) struct cmd_find_state fs; int input, empty, is_floating, flags = 0; const char *template, *style; - char *cause = NULL, *cp; + char *cause = NULL, *cp, *title; struct args_value *av; u_int count = args_count(args); @@ -194,6 +194,12 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) "remain-on-exit-format", 0, "%s", args_get(args, 'm')); } + if (args_has(args, 'T')) { + title = format_single_from_target(item, args_get(args, 'T')); + screen_set_title(&new_wp->base, title); + notify_pane("pane-title-changed", new_wp); + free(title); + } if (input) { switch (window_pane_start_input(new_wp, item, &cause)) { diff --git a/options-table.c b/options-table.c index d743cdf1..89f2f90e 100644 --- a/options-table.c +++ b/options-table.c @@ -647,6 +647,14 @@ const struct options_table_entry options_table[] = { .text = "Colour of not active panes for 'display-panes'." }, + { .name = "display-panes-format", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_SESSION, + .default_str = "#[align=right]#{pane_width}x#{pane_height}", + .text = "Format of text shown by 'display-panes', expanded for each " + "pane." + }, + { .name = "display-panes-time", .type = OPTIONS_TABLE_NUMBER, .scope = OPTIONS_TABLE_SESSION, diff --git a/screen-write.c b/screen-write.c index ceec45a3..30fe0053 100644 --- a/screen-write.c +++ b/screen-write.c @@ -2916,16 +2916,22 @@ void screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc, int cursor) { - struct tty_ctx ttyctx; - struct window_pane *wp = ctx->wp; + struct tty_ctx ttyctx; + struct window_pane *wp = ctx->wp; + struct window_pane_resize *r, *r1; if (wp != NULL && !options_get_number(wp->options, "alternate-screen")) return; screen_write_collect_flush(ctx, 0, __func__); - screen_alternate_on(ctx->s, gc, cursor); + if (!screen_alternate_on(ctx->s, gc, cursor)) + return; if (wp != NULL) { + TAILQ_FOREACH_SAFE (r, &wp->resize_queue, entry, r1) { + TAILQ_REMOVE(&wp->resize_queue, r, entry); + free(r); + } layout_fix_panes(wp->window, NULL); server_redraw_window_borders(wp->window); } @@ -2947,7 +2953,8 @@ screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc, return; screen_write_collect_flush(ctx, 0, __func__); - screen_alternate_off(ctx->s, gc, cursor); + if (!screen_alternate_off(ctx->s, gc, cursor)) + return; if (wp != NULL) { layout_fix_panes(wp->window, NULL); diff --git a/screen.c b/screen.c index 2c78c5ac..233f2d06 100644 --- a/screen.c +++ b/screen.c @@ -672,7 +672,7 @@ screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy, int cursor) * Enter alternative screen mode. A copy of the visible screen is saved and the * history is not updated. */ -void +int screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor) { u_int sx, sy; @@ -681,7 +681,7 @@ screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor) #endif if (SCREEN_IS_ALTERNATE(s)) - return; + return 0; sx = screen_size_x(s); sy = screen_size_y(s); @@ -703,10 +703,12 @@ screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor) s->saved_flags = s->grid->flags; s->grid->flags &= ~GRID_HISTORY; + + return 1; } /* Exit alternate screen mode and restore the copied grid. */ -void +int screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) { u_int sx = screen_size_x(s), sy = screen_size_y(s); @@ -738,7 +740,7 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) s->cx = screen_size_x(s) - 1; if (s->cy > screen_size_y(s) - 1) s->cy = screen_size_y(s) - 1; - return; + return 0; } /* Restore the saved grid. */ @@ -767,6 +769,8 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) s->cx = screen_size_x(s) - 1; if (s->cy > screen_size_y(s) - 1) s->cy = screen_size_y(s) - 1; + + return 1; } /* Get mode as a string. */ diff --git a/server-client.c b/server-client.c index 25719f36..44b85253 100644 --- a/server-client.c +++ b/server-client.c @@ -1586,10 +1586,7 @@ server_client_resize_timer(__unused int fd, __unused short events, void *data) static void server_client_check_pane_resize(struct window_pane *wp) { - struct window_pane_resize *r; - struct window_pane_resize *r1; - struct window_pane_resize *first; - struct window_pane_resize *last; + struct window_pane_resize *r, *r1, *first, *last; struct timeval tv = { .tv_usec = 250000 }; if (TAILQ_EMPTY(&wp->resize_queue)) diff --git a/tmux.1 b/tmux.1 index f0dafb1a..94597786 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2743,7 +2743,7 @@ the end of the visible pane. The default is to capture only the visible contents of the pane. .It Xo .Ic choose\-client -.Op Fl NryZ +.Op Fl kNryZ .Op Fl F Ar format .Op Fl f Ar filter .Op Fl K Ar key\-format @@ -2816,10 +2816,12 @@ specifies the format for each item in the list and a format for each shortcut key; both are evaluated once for each line. .Fl N starts without the preview or if given twice with the larger preview. +.Fl k +kills the pane when the mode is exited. This command works only if at least one client is attached. .It Xo .Ic choose\-tree -.Op Fl GNrswyZ +.Op Fl GkNrswyZ .Op Fl F Ar format .Op Fl f Ar filter .Op Fl K Ar key\-format @@ -2909,10 +2911,12 @@ starts without the preview or if given twice with the larger preview. .Fl G includes all sessions in any session groups in the tree rather than only the first. +.Fl k +kills the pane when the mode is exited. This command works only if at least one client is attached. .It Xo .Ic customize\-mode -.Op Fl NZ +.Op Fl kNZ .Op Fl F Ar format .Op Fl f Ar filter .Op Fl t Ar target\-pane @@ -2960,6 +2964,8 @@ If a filter would lead to an empty list, it is ignored. specifies the format for each item in the tree. .Fl N starts without the option information. +.Fl k +kills the pane when the mode is exited. This command works only if at least one client is attached. .It Xo .Tg displayp @@ -3341,6 +3347,7 @@ but a different format may be specified with .Op Fl s Ar style .Op Fl S Ar active\-border\-style .Op Fl t Ar target\-pane +.Op Fl T Ar title .Op Ar shell\-command Op Ar argument ... .Xc .D1 Pq alias: Ic newp @@ -3359,6 +3366,8 @@ sets the border style when the pane is active and .Fl R sets the border style when the pane is inactive (see .Sx STYLES ) . +.Fl T +sets the pane title. .Pp .Fl h does a horizontal split and @@ -3756,6 +3765,7 @@ the command behaves like .Op Fl s Ar style .Op Fl S Ar active\-border\-style .Op Fl t Ar target\-pane +.Op Fl T Ar title .Op Ar shell\-command Op Ar argument ... .Xc .D1 Pq alias: Ic splitw @@ -4794,6 +4804,12 @@ command to show the indicator for the active pane. Set the colour used by the .Ic display\-panes command to show the indicators for inactive panes. +.It Ic display\-panes\-format Ar format +Set the +.Ar format +of the text shown by the +.Ic display\-panes +command, expanded for each pane. .It Ic display\-panes\-time Ar time Set the time in milliseconds for which the indicators shown by the .Ic display\-panes @@ -7617,7 +7633,7 @@ The buffer commands are as follows: .Bl -tag -width Ds .It Xo .Ic choose\-buffer -.Op Fl NryZ +.Op Fl kNryZ .Op Fl F Ar format .Op Fl f Ar filter .Op Fl K Ar key\-format @@ -7688,6 +7704,8 @@ specifies the format for each item in the list and a format for each shortcut key; both are evaluated once for each line. .Fl N starts without the preview. +.Fl k +kills the pane when the mode is exited. This command works only if at least one client is attached. .Tg clearhist .It Xo Ic clear\-history diff --git a/tmux.h b/tmux.h index 870e778b..292d6ad1 100644 --- a/tmux.h +++ b/tmux.h @@ -1181,6 +1181,8 @@ struct window_mode_entry { struct screen *screen; u_int prefix; + int kill; + TAILQ_ENTRY(window_mode_entry) entry; }; @@ -3388,8 +3390,8 @@ void screen_hide_selection(struct screen *); int screen_check_selection(struct screen *, u_int, u_int); int screen_select_cell(struct screen *, struct grid_cell *, const struct grid_cell *); -void screen_alternate_on(struct screen *, struct grid_cell *, int); -void screen_alternate_off(struct screen *, struct grid_cell *, int); +int screen_alternate_on(struct screen *, struct grid_cell *, int); +int screen_alternate_off(struct screen *, struct grid_cell *, int); const char *screen_mode_to_string(int); const char *screen_print(struct screen *, int); diff --git a/window.c b/window.c index 0d86ac50..fefb9fe2 100644 --- a/window.c +++ b/window.c @@ -1224,6 +1224,7 @@ window_pane_set_mode(struct window_pane *wp, struct window_pane *swp, TAILQ_INSERT_HEAD(&wp->modes, wme, entry); wme->screen = wme->mode->init(wme, fs, args); } + wme->kill = args_has(args, 'k'); wp->screen = wme->screen; wp->flags |= (PANE_REDRAW|PANE_REDRAWSCROLLBAR|PANE_CHANGED); @@ -1241,11 +1242,13 @@ window_pane_reset_mode(struct window_pane *wp) { struct window_mode_entry *wme, *next; struct window *w = wp->window; + int kill; if (TAILQ_EMPTY(&wp->modes)) return; wme = TAILQ_FIRST(&wp->modes); + kill = wme->kill; TAILQ_REMOVE(&wp->modes, wme, entry); wme->mode->free(wme); free(wme); @@ -1268,6 +1271,9 @@ window_pane_reset_mode(struct window_pane *wp) server_redraw_window_borders(wp->window); server_status_window(wp->window); notify_pane("pane-mode-changed", wp); + + if (kill) + server_kill_pane(wp); } void