Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam
2026-06-08 22:00:07 +01:00
10 changed files with 117 additions and 40 deletions

View File

@@ -33,8 +33,8 @@ const struct cmd_entry cmd_choose_tree_entry = {
.name = "choose-tree", .name = "choose-tree",
.alias = NULL, .alias = NULL,
.args = { "F:f:GK:NO:rst:wyZ", 0, 1, cmd_choose_tree_args_parse }, .args = { "F:f:GK:kNO:rst:wyZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-GNrswZ] [-F format] [-f filter] [-K key-format] " .usage = "[-GkNrswZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]", "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },
@@ -47,8 +47,8 @@ const struct cmd_entry cmd_choose_client_entry = {
.name = "choose-client", .name = "choose-client",
.alias = NULL, .alias = NULL,
.args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse }, .args = { "F:f:K:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] " .usage = "[-kNrZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]", "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },
@@ -61,8 +61,8 @@ const struct cmd_entry cmd_choose_buffer_entry = {
.name = "choose-buffer", .name = "choose-buffer",
.alias = NULL, .alias = NULL,
.args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse }, .args = { "F:f:K:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] " .usage = "[-kNrZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]", "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },
@@ -75,8 +75,8 @@ const struct cmd_entry cmd_customize_mode_entry = {
.name = "customize-mode", .name = "customize-mode",
.alias = NULL, .alias = NULL,
.args = { "F:f:Nt:yZ", 0, 0, NULL }, .args = { "F:f:kNt:yZ", 0, 0, NULL },
.usage = "[-NZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE, .usage = "[-kNZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },

View File

@@ -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 static void
cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
struct window_pane *wp) 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 pane, idx, px, py, i, j, xoff, yoff, sx, sy;
u_int cx, cy; u_int cx, cy;
int colour, active_colour; int colour, active_colour;
char buf[16], lbuf[16], rbuf[16], *ptr; char buf[16], lbuf[16], *ptr;
size_t len, llen, rlen; size_t len, llen;
if (wp->xoff + (int)wp->sx <= ctx->ox || if (wp->xoff + (int)wp->sx <= ctx->ox ||
wp->xoff >= ctx->ox + (int)ctx->sx || wp->xoff >= ctx->ox + (int)ctx->sx ||
@@ -159,7 +193,6 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
bgc.bg = colour; bgc.bg = colour;
} }
rlen = xsnprintf(rbuf, sizeof rbuf, "%ux%u", wp->sx, wp->sy);
if (pane > 9 && pane < 35) if (pane > 9 && pane < 35)
llen = xsnprintf(lbuf, sizeof lbuf, "%c", 'a' + (pane - 10)); llen = xsnprintf(lbuf, sizeof lbuf, "%c", 'a' + (pane - 10));
else else
@@ -207,13 +240,9 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
if (sy <= 6) if (sy <= 6)
goto out; goto out;
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL); cmd_display_panes_draw_format(ctx, wp, xoff, yoff, sx, &fgc);
if (rlen != 0 && sx >= rlen) {
cx = xoff + sx - rlen;
cy = yoff;
cmd_display_panes_put(ctx, wp, cx, cy, rbuf, rlen);
}
if (llen != 0) { if (llen != 0) {
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
cx = xoff + sx / 2 + len * 3 - llen - 1; cx = xoff + sx / 2 + len * 3 - llen - 1;
cy = yoff + py + 5; cy = yoff + py + 5;
cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen); cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen);

View File

@@ -38,11 +38,11 @@ const struct cmd_entry cmd_new_pane_entry = {
.name = "new-pane", .name = "new-pane",
.alias = "newp", .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] " .usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] "
"[-F format] [-l size] [-m message] [-p percentage] " "[-F format] [-l size] [-m message] [-p percentage] "
"[-s style] [-S active-border-style] " "[-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 " " "[-X x-position] [-Y y-position] " CMD_TARGET_PANE_USAGE " "
"[shell-command [argument ...]]", "[shell-command [argument ...]]",
@@ -56,11 +56,11 @@ const struct cmd_entry cmd_split_window_entry = {
.name = "split-window", .name = "split-window",
.alias = "splitw", .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] " .usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] "
"[-F format] [-l size] [-m message] [-p percentage] " "[-F format] [-l size] [-m message] [-p percentage] "
"[-s style] [-S active-border-style] " "[-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 ...]]", "[shell-command [argument ...]]",
.target = { 't', CMD_FIND_PANE, 0 }, .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; struct cmd_find_state fs;
int input, empty, is_floating, flags = 0; int input, empty, is_floating, flags = 0;
const char *template, *style; const char *template, *style;
char *cause = NULL, *cp; char *cause = NULL, *cp, *title;
struct args_value *av; struct args_value *av;
u_int count = args_count(args); 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", "remain-on-exit-format",
0, "%s", args_get(args, 'm')); 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) { if (input) {
switch (window_pane_start_input(new_wp, item, &cause)) { switch (window_pane_start_input(new_wp, item, &cause)) {

View File

@@ -647,6 +647,14 @@ const struct options_table_entry options_table[] = {
.text = "Colour of not active panes for 'display-panes'." .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", { .name = "display-panes-time",
.type = OPTIONS_TABLE_NUMBER, .type = OPTIONS_TABLE_NUMBER,
.scope = OPTIONS_TABLE_SESSION, .scope = OPTIONS_TABLE_SESSION,

View File

@@ -2916,16 +2916,22 @@ void
screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc, screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc,
int cursor) int cursor)
{ {
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
struct window_pane *wp = ctx->wp; struct window_pane *wp = ctx->wp;
struct window_pane_resize *r, *r1;
if (wp != NULL && !options_get_number(wp->options, "alternate-screen")) if (wp != NULL && !options_get_number(wp->options, "alternate-screen"))
return; return;
screen_write_collect_flush(ctx, 0, __func__); 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) { 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); layout_fix_panes(wp->window, NULL);
server_redraw_window_borders(wp->window); server_redraw_window_borders(wp->window);
} }
@@ -2947,7 +2953,8 @@ screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc,
return; return;
screen_write_collect_flush(ctx, 0, __func__); 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) { if (wp != NULL) {
layout_fix_panes(wp->window, NULL); layout_fix_panes(wp->window, NULL);

View File

@@ -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 * Enter alternative screen mode. A copy of the visible screen is saved and the
* history is not updated. * history is not updated.
*/ */
void int
screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor) screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
{ {
u_int sx, sy; u_int sx, sy;
@@ -681,7 +681,7 @@ screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
#endif #endif
if (SCREEN_IS_ALTERNATE(s)) if (SCREEN_IS_ALTERNATE(s))
return; return 0;
sx = screen_size_x(s); sx = screen_size_x(s);
sy = screen_size_y(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->saved_flags = s->grid->flags;
s->grid->flags &= ~GRID_HISTORY; s->grid->flags &= ~GRID_HISTORY;
return 1;
} }
/* Exit alternate screen mode and restore the copied grid. */ /* Exit alternate screen mode and restore the copied grid. */
void int
screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
{ {
u_int sx = screen_size_x(s), sy = screen_size_y(s); 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; s->cx = screen_size_x(s) - 1;
if (s->cy > screen_size_y(s) - 1) if (s->cy > screen_size_y(s) - 1)
s->cy = screen_size_y(s) - 1; s->cy = screen_size_y(s) - 1;
return; return 0;
} }
/* Restore the saved grid. */ /* 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; s->cx = screen_size_x(s) - 1;
if (s->cy > screen_size_y(s) - 1) if (s->cy > screen_size_y(s) - 1)
s->cy = screen_size_y(s) - 1; s->cy = screen_size_y(s) - 1;
return 1;
} }
/* Get mode as a string. */ /* Get mode as a string. */

View File

@@ -1586,10 +1586,7 @@ server_client_resize_timer(__unused int fd, __unused short events, void *data)
static void static void
server_client_check_pane_resize(struct window_pane *wp) server_client_check_pane_resize(struct window_pane *wp)
{ {
struct window_pane_resize *r; struct window_pane_resize *r, *r1, *first, *last;
struct window_pane_resize *r1;
struct window_pane_resize *first;
struct window_pane_resize *last;
struct timeval tv = { .tv_usec = 250000 }; struct timeval tv = { .tv_usec = 250000 };
if (TAILQ_EMPTY(&wp->resize_queue)) if (TAILQ_EMPTY(&wp->resize_queue))

26
tmux.1
View File

@@ -2743,7 +2743,7 @@ the end of the visible pane.
The default is to capture only the visible contents of the pane. The default is to capture only the visible contents of the pane.
.It Xo .It Xo
.Ic choose\-client .Ic choose\-client
.Op Fl NryZ .Op Fl kNryZ
.Op Fl F Ar format .Op Fl F Ar format
.Op Fl f Ar filter .Op Fl f Ar filter
.Op Fl K Ar key\-format .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. a format for each shortcut key; both are evaluated once for each line.
.Fl N .Fl N
starts without the preview or if given twice with the larger preview. 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. This command works only if at least one client is attached.
.It Xo .It Xo
.Ic choose\-tree .Ic choose\-tree
.Op Fl GNrswyZ .Op Fl GkNrswyZ
.Op Fl F Ar format .Op Fl F Ar format
.Op Fl f Ar filter .Op Fl f Ar filter
.Op Fl K Ar key\-format .Op Fl K Ar key\-format
@@ -2909,10 +2911,12 @@ starts without the preview or if given twice with the larger preview.
.Fl G .Fl G
includes all sessions in any session groups in the tree rather than only the includes all sessions in any session groups in the tree rather than only the
first. first.
.Fl k
kills the pane when the mode is exited.
This command works only if at least one client is attached. This command works only if at least one client is attached.
.It Xo .It Xo
.Ic customize\-mode .Ic customize\-mode
.Op Fl NZ .Op Fl kNZ
.Op Fl F Ar format .Op Fl F Ar format
.Op Fl f Ar filter .Op Fl f Ar filter
.Op Fl t Ar target\-pane .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. specifies the format for each item in the tree.
.Fl N .Fl N
starts without the option information. 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. This command works only if at least one client is attached.
.It Xo .It Xo
.Tg displayp .Tg displayp
@@ -3341,6 +3347,7 @@ but a different format may be specified with
.Op Fl s Ar style .Op Fl s Ar style
.Op Fl S Ar active\-border\-style .Op Fl S Ar active\-border\-style
.Op Fl t Ar target\-pane .Op Fl t Ar target\-pane
.Op Fl T Ar title
.Op Ar shell\-command Op Ar argument ... .Op Ar shell\-command Op Ar argument ...
.Xc .Xc
.D1 Pq alias: Ic newp .D1 Pq alias: Ic newp
@@ -3359,6 +3366,8 @@ sets the border style when the pane is active and
.Fl R .Fl R
sets the border style when the pane is inactive (see sets the border style when the pane is inactive (see
.Sx STYLES ) . .Sx STYLES ) .
.Fl T
sets the pane title.
.Pp .Pp
.Fl h .Fl h
does a horizontal split and does a horizontal split and
@@ -3756,6 +3765,7 @@ the command behaves like
.Op Fl s Ar style .Op Fl s Ar style
.Op Fl S Ar active\-border\-style .Op Fl S Ar active\-border\-style
.Op Fl t Ar target\-pane .Op Fl t Ar target\-pane
.Op Fl T Ar title
.Op Ar shell\-command Op Ar argument ... .Op Ar shell\-command Op Ar argument ...
.Xc .Xc
.D1 Pq alias: Ic splitw .D1 Pq alias: Ic splitw
@@ -4794,6 +4804,12 @@ command to show the indicator for the active pane.
Set the colour used by the Set the colour used by the
.Ic display\-panes .Ic display\-panes
command to show the indicators for inactive 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 .It Ic display\-panes\-time Ar time
Set the time in milliseconds for which the indicators shown by the Set the time in milliseconds for which the indicators shown by the
.Ic display\-panes .Ic display\-panes
@@ -7617,7 +7633,7 @@ The buffer commands are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Xo .It Xo
.Ic choose\-buffer .Ic choose\-buffer
.Op Fl NryZ .Op Fl kNryZ
.Op Fl F Ar format .Op Fl F Ar format
.Op Fl f Ar filter .Op Fl f Ar filter
.Op Fl K Ar key\-format .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. a format for each shortcut key; both are evaluated once for each line.
.Fl N .Fl N
starts without the preview. 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. This command works only if at least one client is attached.
.Tg clearhist .Tg clearhist
.It Xo Ic clear\-history .It Xo Ic clear\-history

6
tmux.h
View File

@@ -1181,6 +1181,8 @@ struct window_mode_entry {
struct screen *screen; struct screen *screen;
u_int prefix; u_int prefix;
int kill;
TAILQ_ENTRY(window_mode_entry) entry; 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_check_selection(struct screen *, u_int, u_int);
int screen_select_cell(struct screen *, struct grid_cell *, int screen_select_cell(struct screen *, struct grid_cell *,
const struct grid_cell *); const struct grid_cell *);
void screen_alternate_on(struct screen *, struct grid_cell *, int); int screen_alternate_on(struct screen *, struct grid_cell *, int);
void screen_alternate_off(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_mode_to_string(int);
const char *screen_print(struct screen *, int); const char *screen_print(struct screen *, int);

View File

@@ -1224,6 +1224,7 @@ window_pane_set_mode(struct window_pane *wp, struct window_pane *swp,
TAILQ_INSERT_HEAD(&wp->modes, wme, entry); TAILQ_INSERT_HEAD(&wp->modes, wme, entry);
wme->screen = wme->mode->init(wme, fs, args); wme->screen = wme->mode->init(wme, fs, args);
} }
wme->kill = args_has(args, 'k');
wp->screen = wme->screen; wp->screen = wme->screen;
wp->flags |= (PANE_REDRAW|PANE_REDRAWSCROLLBAR|PANE_CHANGED); 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_mode_entry *wme, *next;
struct window *w = wp->window; struct window *w = wp->window;
int kill;
if (TAILQ_EMPTY(&wp->modes)) if (TAILQ_EMPTY(&wp->modes))
return; return;
wme = TAILQ_FIRST(&wp->modes); wme = TAILQ_FIRST(&wp->modes);
kill = wme->kill;
TAILQ_REMOVE(&wp->modes, wme, entry); TAILQ_REMOVE(&wp->modes, wme, entry);
wme->mode->free(wme); wme->mode->free(wme);
free(wme); free(wme);
@@ -1268,6 +1271,9 @@ window_pane_reset_mode(struct window_pane *wp)
server_redraw_window_borders(wp->window); server_redraw_window_borders(wp->window);
server_status_window(wp->window); server_status_window(wp->window);
notify_pane("pane-mode-changed", wp); notify_pane("pane-mode-changed", wp);
if (kill)
server_kill_pane(wp);
} }
void void