Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam
2026-06-13 12:00:06 +01:00
5 changed files with 154 additions and 6 deletions

View File

@@ -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:hK:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse }, .args = { "F:f:hiK:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-hkNrZ] [-F format] [-f filter] [-K key-format] " .usage = "[-hikNrZ] [-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 },

View File

@@ -49,6 +49,7 @@ struct mode_tree_data {
const struct menu_item *menu; const struct menu_item *menu;
struct sort_criteria sort_crit; struct sort_criteria sort_crit;
const char *view_name;
mode_tree_build_cb buildcb; mode_tree_build_cb buildcb;
mode_tree_draw_cb drawcb; mode_tree_draw_cb drawcb;
@@ -700,6 +701,12 @@ mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent,
return (mti); return (mti);
} }
void
mode_tree_view_name(struct mode_tree_data *mtd, const char *name)
{
mtd->view_name = name;
}
void void
mode_tree_draw_as_parent(struct mode_tree_item *mti) mode_tree_draw_as_parent(struct mode_tree_item *mti)
{ {
@@ -884,9 +891,12 @@ mode_tree_draw(struct mode_tree_data *mtd)
screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL); screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL);
if (mtd->sort_crit.order_seq != NULL) { if (mtd->sort_crit.order_seq != NULL) {
xasprintf(&text, " %s (sort: %s%s)", mti->name, xasprintf(&text, " %s (sort: %s%s)%s%s%s", mti->name,
sort_order_to_string(mtd->sort_crit.order), sort_order_to_string(mtd->sort_crit.order),
mtd->sort_crit.reversed ? ", reversed" : ""); mtd->sort_crit.reversed ? ", reversed" : "",
mtd->view_name == NULL ? "" : " (view: ",
mtd->view_name == NULL ? "" : mtd->view_name,
mtd->view_name == NULL ? "" : ")");
} else } else
xasprintf(&text, " %s", mti->name); xasprintf(&text, " %s", mti->name);
if (w - 2 >= strlen(text)) { if (w - 2 >= strlen(text)) {

5
tmux.1
View File

@@ -2866,7 +2866,7 @@ The
command works only if at least one client is attached. command works only if at least one client is attached.
.It Xo .It Xo
.Ic choose\-tree .Ic choose\-tree
.Op Fl GhkNrswyZ .Op Fl GhikNrswyZ
.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
@@ -2918,6 +2918,7 @@ The following keys may be used in tree mode:
.It Li "O" Ta "Change sort order" .It Li "O" Ta "Change sort order"
.It Li "r" Ta "Reverse sort order" .It Li "r" Ta "Reverse sort order"
.It Li "v" Ta "Toggle preview" .It Li "v" Ta "Toggle preview"
.It Li "i" Ta "Change view (preview and client information)"
.It Li "F1 or C\-h" Ta "Display help" .It Li "F1 or C\-h" Ta "Display help"
.It Li "q" Ta "Exit mode" .It Li "q" Ta "Exit mode"
.El .El
@@ -2957,6 +2958,8 @@ first.
.Pp .Pp
.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 i
starts showing client information instead of the preview.
.Fl h .Fl h
hides the pane containing the mode. hides the pane containing the mode.
.Fl k .Fl k

3
tmux.h
View File

@@ -3614,6 +3614,7 @@ void mode_tree_resize(struct mode_tree_data *, u_int, u_int);
struct mode_tree_item *mode_tree_add(struct mode_tree_data *, struct mode_tree_item *mode_tree_add(struct mode_tree_data *,
struct mode_tree_item *, void *, uint64_t, const char *, struct mode_tree_item *, void *, uint64_t, const char *,
const char *, int); const char *, int);
void mode_tree_view_name(struct mode_tree_data *, const char *);
void mode_tree_draw_as_parent(struct mode_tree_item *); void mode_tree_draw_as_parent(struct mode_tree_item *);
void mode_tree_no_tag(struct mode_tree_item *); void mode_tree_no_tag(struct mode_tree_item *);
void mode_tree_align(struct mode_tree_item *, int); void mode_tree_align(struct mode_tree_item *, int);
@@ -3655,7 +3656,7 @@ int window_copy_get_current_offset(struct window_pane *, u_int *,
char *window_copy_get_hyperlink(struct window_pane *, u_int, u_int); char *window_copy_get_hyperlink(struct window_pane *, u_int, u_int);
void window_copy_set_line_numbers(struct window_pane *, int); void window_copy_set_line_numbers(struct window_pane *, int);
/* window-option.c */ /* window-customize.c */
extern const struct window_mode window_customize_mode; extern const struct window_mode window_customize_mode;
/* names.c */ /* names.c */

View File

@@ -47,6 +47,93 @@ static void window_client_key(struct window_mode_entry *,
"M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \ "M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \
"}" "}"
#define WINDOW_CLIENT_FEATURE(f) \
"#{?#{I/f:" #f "}," \
"#[fg=green],#[dim]}#{p/15:#{l:" #f "}}" \
"#[default]"
static const char *window_client_info_lines[] = {
"Client Name #[acs]x#[default] "
"#{client_name} "
"#[dim](PID #{client_pid})#[default]",
"Session #[acs]x#[default] "
"#{session_name}",
"Attach Time #[acs]x#[default] "
"#{t:client_created} "
"#[dim](#{t/r:client_created})#[default]",
"Activity Time #[acs]x#[default] "
"#{t:client_created} "
"#[dim](#{t/r:client_created})#[default]",
"Terminal Type #[acs]x#[default] "
"#{?client_termtype,#{client_termtype},Unknown}",
"TERM #[acs]x#[default] "
"#{client_termname}",
"Size #[acs]x#[default] "
"#{client_width}x#{client_height} "
"#[dim](cell #{client_cell_width}x#{client_cell_height})#[default]",
"Bytes Written #[acs]x#[default] "
"#{client_written} "
"#[dim](#{client_discarded} discarded)#[default]",
"Features #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(256) " "
WINDOW_CLIENT_FEATURE(RGB) " "
WINDOW_CLIENT_FEATURE(bpaste) " "
WINDOW_CLIENT_FEATURE(ccolour),
" #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(clipboard) " "
WINDOW_CLIENT_FEATURE(cstyle) " "
WINDOW_CLIENT_FEATURE(extkeys) " "
WINDOW_CLIENT_FEATURE(focus),
" #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(hyperlinks) " "
WINDOW_CLIENT_FEATURE(ignorefkeys) " "
WINDOW_CLIENT_FEATURE(margins) " "
WINDOW_CLIENT_FEATURE(mouse),
" #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(osc7) " "
WINDOW_CLIENT_FEATURE(overline) " "
WINDOW_CLIENT_FEATURE(progressbar) " "
WINDOW_CLIENT_FEATURE(rectfill),
" #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(sixel) " "
WINDOW_CLIENT_FEATURE(strikethrough) " "
WINDOW_CLIENT_FEATURE(sync) " "
WINDOW_CLIENT_FEATURE(title),
" #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(usstyle),
"#[acs]qqqqqqqqqqqqqqn#{R:q,#{window_width}}#[default]",
"prefix #[acs]x#[default] "
"#{prefix}",
"mouse #[acs]x#[default] "
"#{?mouse,#{?#{I/c:kmous},,#[fg=red]}on,#[dim]off} "
"#{?#{I/c:kmous},,#[align=right]unavailable: [kmous] missing}",
"set-clipboard #[acs]x#[default] "
"#{?#{!=:#{set-clipboard},off},#{?#{I/f:clipboard},,#[fg=red]}#{set-clipboard},#[dim]off} "
"#{?#{I/f:clipboard},,#[align=right]unavailable: [Ms] missing}",
"get-clipboard #[acs]x#[default] "
"#{?#{!=:#{get-clipboard},off},#{?#{I/f:clipboard},,#[fg=red]}#{get-clipboard},#[dim]off} "
"#{?#{I/f:clipboard},,#[align=right]unavailable: [Ms] missing}",
"focus-events #[acs]x#[default] "
"#{?focus-events,#{?#{I/f:focus},,#[fg=red]}on,#[dim]off} "
"#{?#{I/f:focus},,#[align=right]unavailable: [Enfcs] or [Dcfcs] missing}",
"extended-keys #[acs]x#[default] "
"#{?#{!=:#{extended-keys},off},#{?#{I/f:extkeys},,#[fg=red]}#{extended-keys},#[dim]off} "
"#{?#{I/f:extkeys},,#[align=right]unavailable: [Eneks] or [Dseks] missing}",
"set-titles #[acs]x#[default] "
"#{?set-titles,on,#[dim]off}",
"escape-time #[acs]x#[default] "
"#{escape-time} ms",
};
static const struct menu_item window_client_menu_items[] = { static const struct menu_item window_client_menu_items[] = {
{ "Detach", 'd', NULL }, { "Detach", 'd', NULL },
{ "Detach Tagged", 'D', NULL }, { "Detach Tagged", 'D', NULL },
@@ -82,7 +169,9 @@ struct window_client_modedata {
char *format; char *format;
char *key_format; char *key_format;
char *command; char *command;
int hide_preview_this_pane; int hide_preview_this_pane;
int preview_is_info;
struct window_client_itemdata **item_list; struct window_client_itemdata **item_list;
u_int item_size; u_int item_size;
@@ -162,6 +251,32 @@ window_client_build(void *modedata, struct sort_criteria *sort_crit,
} }
} }
static void
window_client_draw_info(__unused void *modedata, void *itemdata,
struct screen_write_ctx *ctx, u_int sx, u_int sy)
{
struct window_client_itemdata *item = itemdata;
struct client *c = item->c;
struct screen *s = ctx->s;
u_int cx = s->cx, cy = s->cy, i;
struct format_tree *ft;
char *expanded;
ft = format_create_defaults(NULL, c, NULL, NULL, NULL);
screen_write_cursormove(ctx, cx, cy, 0);
for (i = 0; i < nitems(window_client_info_lines); i++) {
if (i == sy)
break;
expanded = format_expand(ft, window_client_info_lines[i]);
screen_write_cursormove(ctx, cx, cy + i, 0);
format_draw(ctx, &grid_default_cell, sx, expanded, NULL, 0);
free(expanded);
}
format_free(ft);
}
static void static void
window_client_draw(void *modedata, void *itemdata, window_client_draw(void *modedata, void *itemdata,
struct screen_write_ctx *ctx, u_int sx, u_int sy) struct screen_write_ctx *ctx, u_int sx, u_int sy)
@@ -175,6 +290,10 @@ window_client_draw(void *modedata, void *itemdata,
if (c->session == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS)) if (c->session == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
return; return;
if (data->preview_is_info) {
window_client_draw_info(modedata, itemdata, ctx, sx, sy);
return;
}
wp = c->session->curw->window->active; wp = c->session->curw->window->active;
if (data->hide_preview_this_pane && wp == data->wp) { if (data->hide_preview_this_pane && wp == data->wp) {
if (!TAILQ_EMPTY(&c->session->curw->window->last_panes)) if (!TAILQ_EMPTY(&c->session->curw->window->last_panes))
@@ -250,6 +369,7 @@ window_client_sort(struct sort_criteria *sort_crit)
} }
static const char* window_client_help_lines[] = { static const char* window_client_help_lines[] = {
"\r\033[1m i \033[0m\016x\017 \033[0mToggle info view\n",
"\r\033[1m Enter \033[0m\016x\017 \033[0mChoose selected %1\n", "\r\033[1m Enter \033[0m\016x\017 \033[0mChoose selected %1\n",
"\r\033[1m d \033[0m\016x\017 \033[0mDetach selected %1\n", "\r\033[1m d \033[0m\016x\017 \033[0mDetach selected %1\n",
"\r\033[1m D \033[0m\016x\017 \033[0mDetach tagged %1s\n", "\r\033[1m D \033[0m\016x\017 \033[0mDetach tagged %1s\n",
@@ -280,6 +400,7 @@ window_client_init(struct window_mode_entry *wme,
wme->data = data = xcalloc(1, sizeof *data); wme->data = data = xcalloc(1, sizeof *data);
data->wp = wp; data->wp = wp;
data->hide_preview_this_pane = args != NULL && args_has(args, 'h'); data->hide_preview_this_pane = args != NULL && args_has(args, 'h');
data->preview_is_info = args != NULL && args_has(args, 'i');
if (args == NULL || !args_has(args, 'F')) if (args == NULL || !args_has(args, 'F'))
data->format = xstrdup(WINDOW_CLIENT_DEFAULT_FORMAT); data->format = xstrdup(WINDOW_CLIENT_DEFAULT_FORMAT);
@@ -300,6 +421,11 @@ window_client_init(struct window_mode_entry *wme,
window_client_help, data, window_client_menu_items, &s); window_client_help, data, window_client_menu_items, &s);
mode_tree_zoom(data->data, args); mode_tree_zoom(data->data, args);
if (data->preview_is_info)
mode_tree_view_name(data->data, "info");
else
mode_tree_view_name(data->data, "preview");
mode_tree_build(data->data); mode_tree_build(data->data);
mode_tree_draw(data->data); mode_tree_draw(data->data);
@@ -389,6 +515,14 @@ window_client_key(struct window_mode_entry *wme, struct client *c,
mode_tree_each_tagged(mtd, window_client_do_detach, c, key, 0); mode_tree_each_tagged(mtd, window_client_do_detach, c, key, 0);
mode_tree_build(mtd); mode_tree_build(mtd);
break; break;
case 'i':
data->preview_is_info = !data->preview_is_info;
if (data->preview_is_info)
mode_tree_view_name(mtd, "info");
else
mode_tree_view_name(mtd, "preview");
mode_tree_build(mtd);
break;
case '\r': case '\r':
item = mode_tree_get_current(mtd); item = mode_tree_get_current(mtd);
mode_tree_run_command(c, NULL, data->command, item->c->ttyname); mode_tree_run_command(c, NULL, data->command, item->c->ttyname);