1
0
mirror of https://github.com/openbsd/src.git synced 2026-06-18 07:13:36 +02:00

Extend client mode so the preview can be changed to a view with a

summary of the client terminal and its features, intended to make
troubleshooting easier. "choose-client -i" or the "i" key in the mode.
This commit is contained in:
nicm
2026-06-13 10:32:54 +00:00
parent 4ee6e01dfc
commit a8844f8c56
5 changed files with 159 additions and 11 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: cmd-choose-tree.c,v 1.55 2026/06/08 21:01:33 nicm Exp $ */
/* $OpenBSD: cmd-choose-tree.c,v 1.56 2026/06/13 10:32:54 nicm Exp $ */
/*
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
@@ -47,8 +47,8 @@ const struct cmd_entry cmd_choose_client_entry = {
.name = "choose-client",
.alias = NULL,
.args = { "F:f:hK:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-hkNrZ] [-F format] [-f filter] [-K key-format] "
.args = { "F:f:hiK:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-hikNrZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
.target = { 't', CMD_FIND_PANE, 0 },
+13 -3
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: mode-tree.c,v 1.83 2026/06/08 15:16:21 nicm Exp $ */
/* $OpenBSD: mode-tree.c,v 1.84 2026/06/13 10:32:54 nicm Exp $ */
/*
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -49,6 +49,7 @@ struct mode_tree_data {
const struct menu_item *menu;
struct sort_criteria sort_crit;
const char *view_name;
mode_tree_build_cb buildcb;
mode_tree_draw_cb drawcb;
@@ -700,6 +701,12 @@ mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent,
return (mti);
}
void
mode_tree_view_name(struct mode_tree_data *mtd, const char *name)
{
mtd->view_name = name;
}
void
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);
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),
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
xasprintf(&text, " %s", mti->name);
if (w - 2 >= strlen(text)) {
+5 -2
View File
@@ -1,4 +1,4 @@
.\" $OpenBSD: tmux.1,v 1.1082 2026/06/13 09:17:29 nicm Exp $
.\" $OpenBSD: tmux.1,v 1.1083 2026/06/13 10:32:54 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\"
@@ -2864,7 +2864,7 @@ The
command works only if at least one client is attached.
.It Xo
.Ic choose\-tree
.Op Fl GhkNrswyZ
.Op Fl GhikNrswyZ
.Op Fl F Ar format
.Op Fl f Ar filter
.Op Fl K Ar key\-format
@@ -2916,6 +2916,7 @@ The following keys may be used in tree mode:
.It Li "O" Ta "Change sort order"
.It Li "r" Ta "Reverse sort order"
.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 "q" Ta "Exit mode"
.El
@@ -2955,6 +2956,8 @@ first.
.Pp
.Fl N
starts without the preview or if given twice with the larger preview.
.Fl i
starts showing client information instead of the preview.
.Fl h
hides the pane containing the mode.
.Fl k
+3 -2
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: tmux.h,v 1.1347 2026/06/13 09:17:29 nicm Exp $ */
/* $OpenBSD: tmux.h,v 1.1348 2026/06/13 10:32:54 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -3565,6 +3565,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 *, void *, uint64_t, const char *,
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_no_tag(struct mode_tree_item *);
void mode_tree_align(struct mode_tree_item *, int);
@@ -3606,7 +3607,7 @@ int window_copy_get_current_offset(struct window_pane *, u_int *,
char *window_copy_get_hyperlink(struct window_pane *, u_int, u_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;
/* names.c */
+135 -1
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: window-client.c,v 1.39 2026/06/08 21:01:33 nicm Exp $ */
/* $OpenBSD: window-client.c,v 1.40 2026/06/13 10:32:54 nicm Exp $ */
/*
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -47,6 +47,93 @@ static void window_client_key(struct window_mode_entry *,
"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[] = {
{ "Detach", 'd', NULL },
{ "Detach Tagged", 'D', NULL },
@@ -82,7 +169,9 @@ struct window_client_modedata {
char *format;
char *key_format;
char *command;
int hide_preview_this_pane;
int preview_is_info;
struct window_client_itemdata **item_list;
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
window_client_draw(void *modedata, void *itemdata,
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))
return;
if (data->preview_is_info) {
window_client_draw_info(modedata, itemdata, ctx, sx, sy);
return;
}
wp = c->session->curw->window->active;
if (data->hide_preview_this_pane && wp == data->wp) {
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[] = {
"\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 d \033[0m\016x\017 \033[0mDetach selected %1\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);
data->wp = wp;
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'))
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);
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_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_build(mtd);
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':
item = mode_tree_get_current(mtd);
mode_tree_run_command(c, NULL, data->command, item->c->ttyname);