Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam
2026-03-12 16:01:08 +00:00
9 changed files with 222 additions and 24 deletions

View File

@@ -949,7 +949,7 @@ input_set_state(struct input_ctx *ictx, const struct input_transition *itr)
/* Parse data. */
static void
input_parse(struct input_ctx *ictx, u_char *buf, size_t len)
input_parse(struct input_ctx *ictx, const u_char *buf, size_t len)
{
struct screen_write_ctx *sctx = &ictx->ctx;
const struct input_state *state = NULL;
@@ -1020,7 +1020,7 @@ input_parse_pane(struct window_pane *wp)
/* Parse given input. */
void
input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len)
input_parse_buffer(struct window_pane *wp, const u_char *buf, size_t len)
{
struct input_ctx *ictx = wp->ictx;
struct screen_write_ctx *sctx = &ictx->ctx;
@@ -1051,7 +1051,7 @@ input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len)
/* Parse given input for screen. */
void
input_parse_screen(struct input_ctx *ictx, struct screen *s,
screen_write_init_ctx_cb cb, void *arg, u_char *buf, size_t len)
screen_write_init_ctx_cb cb, void *arg, const u_char *buf, size_t len)
{
struct screen_write_ctx *sctx = &ictx->ctx;

View File

@@ -58,6 +58,7 @@ struct mode_tree_data {
mode_tree_key_cb keycb;
mode_tree_swap_cb swapcb;
mode_tree_sort_cb sortcb;
mode_tree_help_cb helpcb;
struct mode_tree_list children;
struct mode_tree_list saved;
@@ -132,6 +133,36 @@ static const struct menu_item mode_tree_menu_items[] = {
{ NULL, KEYC_NONE, NULL }
};
static const char* mode_tree_help_start[] = {
"\r\033[1m Up, k \033[0m\016x\017 \033[0mMove cursor up\n",
"\r\033[1m Down, j \033[0m\016x\017 \033[0mMove cursor down\n",
"\r\033[1m g \033[0m\016x\017 \033[0mGo to top\n",
"\r\033[1m G \033[0m\016x\017 \033[0mGo to bottom\n",
"\r\033[1m PPage, C-b \033[0m\016x\017 \033[0mPage up\n",
"\r\033[1m NPage, C-f \033[0m\016x\017 \033[0mPage down\n",
"\r\033[1m Left, h \033[0m\016x\017 \033[0mCollapse %1\n",
"\r\033[1m Right, l \033[0m\016x\017 \033[0mExpand %1\n",
"\r\033[1m M-- \033[0m\016x\017 \033[0mCollapse all %1s\n",
"\r\033[1m M-+ \033[0m\016x\017 \033[0mExpand all %1s\n",
"\r\033[1m t \033[0m\016x\017 \033[0mToggle %1 tag\n",
"\r\033[1m T \033[0m\016x\017 \033[0mUntag all %1s\n",
"\r\033[1m C-t \033[0m\016x\017 \033[0mTag all %1s\n",
"\r\033[1m C-s \033[0m\016x\017 \033[0mSearch forward\n",
"\r\033[1m C-r \033[0m\016x\017 \033[0mSearch backward\n",
"\r\033[1m n \033[0m\016x\017 \033[0mRepeat search forward\n",
"\r\033[1m N \033[0m\016x\017 \033[0mRepeat search backward\n",
"\r\033[1m f \033[0m\016x\017 \033[0mFilter %1s\n",
"\r\033[1m O \033[0m\016x\017 \033[0mChange sort order\n",
"\r\033[1m r \033[0m\016x\017 \033[0mReverse sort order\n",
"\r\033[1m v \033[0m\016x\017 \033[0mToggle preview\n",
NULL
};
static const char* mode_tree_help_end[] = {
"\r\033[1m q, Escape \033[0m\016x\017 \033[0mExit mode\033[H",
NULL
};
#define MODE_TREE_HELP_DEFAULT_WIDTH 39
static int
mode_tree_is_lowercase(const char *ptr)
{
@@ -453,8 +484,9 @@ mode_tree_start(struct window_pane *wp, struct args *args,
mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb,
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
mode_tree_height_cb heightcb, mode_tree_key_cb keycb,
mode_tree_swap_cb swapcb, mode_tree_sort_cb sortcb, void *modedata,
const struct menu_item *menu, struct screen **s)
mode_tree_swap_cb swapcb, mode_tree_sort_cb sortcb,
mode_tree_help_cb helpcb, void *modedata, const struct menu_item *menu,
struct screen **s)
{
struct mode_tree_data *mtd;
@@ -488,6 +520,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
mtd->keycb = keycb;
mtd->swapcb = swapcb;
mtd->sortcb = sortcb;
mtd->helpcb = helpcb;
TAILQ_INIT(&mtd->children);
@@ -1123,6 +1156,57 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x,
}
}
static void
mode_tree_display_help(__unused struct mode_tree_data *mtd, struct client *c)
{
struct session *s = c->session;
u_int px, py, w, h = 0;
const char **line, **lines = NULL, *item = "item";
char *new_line;
if (mtd->helpcb == NULL)
w = MODE_TREE_HELP_DEFAULT_WIDTH;
else {
lines = mtd->helpcb(&w, &item);
if (w < MODE_TREE_HELP_DEFAULT_WIDTH)
w = MODE_TREE_HELP_DEFAULT_WIDTH;
}
for (line = mode_tree_help_start; *line != NULL; line++)
h++;
for (line = lines; *line != NULL; line++)
h++;
for (line = mode_tree_help_end; *line != NULL; line++)
h++;
if (c->tty.sx < w || c->tty.sy < h)
return;
px = (c->tty.sx - w) / 2;
py = (c->tty.sy - h) / 2;
if (popup_display(POPUP_CLOSEANYKEY|POPUP_NOJOB, BOX_LINES_DEFAULT,
NULL, px, py, w, h, NULL, NULL, 0, NULL, NULL, NULL, c, s, NULL,
NULL, NULL, NULL) != 0)
return;
popup_write(c, "\033[H\033[?25l\033[?7l\033)0", 17);
for (line = mode_tree_help_start; *line != NULL; line++) {
new_line = cmd_template_replace(*line, item, 1);
popup_write(c, new_line, strlen(new_line));
free(new_line);
}
for (line = lines; *line != NULL; line++) {
new_line = cmd_template_replace(*line, item, 1);
popup_write(c, new_line, strlen(new_line));
free(new_line);
}
for (line = mode_tree_help_end; *line != NULL; line++) {
new_line = cmd_template_replace(*line, item, 1);
popup_write(c, new_line, strlen(new_line));
free(new_line);
}
popup_write(c, "\033[H", 3);
}
int
mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
struct mouse_event *m, u_int *xp, u_int *yp)
@@ -1193,6 +1277,10 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
case '\033': /* Escape */
case 'g'|KEYC_CTRL:
return (1);
case KEYC_F1:
case 'h'|KEYC_CTRL:
mode_tree_display_help(mtd, c);
break;
case KEYC_UP:
case 'k':
case KEYC_WHEELUP_PANE:

27
popup.c
View File

@@ -847,16 +847,35 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
pd->psx = sx;
pd->psy = sy;
pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy);
pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette, c);
if (flags & POPUP_NOJOB)
pd->ictx = input_init(NULL, NULL, &pd->palette, NULL);
else {
pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy);
pd->ictx = input_init(NULL, job_get_event(pd->job),
&pd->palette, c);
}
server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,
popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd);
return (0);
}
void
popup_write(struct client *c, const char *data, size_t size)
{
struct popup_data *pd = c->overlay_data;
if (!popup_present(c))
return;
c->overlay_check = NULL;
c->overlay_data = NULL;
input_parse_screen(pd->ictx, &pd->s, popup_init_ctx_cb, pd, data, size);
c->overlay_check = popup_check_cb;
c->overlay_data = pd;
}
static void
popup_editor_free(struct popup_editor *pe)
{

12
tmux.1
View File

@@ -2700,7 +2700,7 @@ zooms the pane.
.Fl y
disables any confirmation prompts.
The following keys may be used in client mode:
.Bl -column "Key" "Function" -offset indent
.Bl -column "KeyXXXXXX" "Function" -offset indent
.It Sy "Key" Ta Sy "Function"
.It Li "Enter" Ta "Choose selected client"
.It Li "Up" Ta "Select previous client"
@@ -2721,6 +2721,7 @@ The following keys may be used in client mode:
.It Li "O" Ta "Change sort order"
.It Li "r" Ta "Reverse sort order"
.It Li "v" Ta "Toggle preview"
.It Li "F1 or C-h" Ta "Display help"
.It Li "q" Ta "Exit mode"
.El
.Pp
@@ -2779,7 +2780,7 @@ zooms the pane.
.Fl y
disables any confirmation prompts.
The following keys may be used in tree mode:
.Bl -column "Key" "Function" -offset indent
.Bl -column "KeyXXXXXX" "Function" -offset indent
.It Sy "Key" Ta Sy "Function"
.It Li "Enter" Ta "Choose selected item"
.It Li "Up" Ta "Select previous item"
@@ -2808,6 +2809,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 "F1 or C-h" Ta "Display help"
.It Li "q" Ta "Exit mode"
.El
.Pp
@@ -2859,7 +2861,7 @@ Option values in the list are shown for the active pane in the current window.
.Fl Z
zooms the pane.
The following keys may be used in customize mode:
.Bl -column "Key" "Function" -offset indent
.Bl -column "KeyXXXXXX" "Function" -offset indent
.It Sy "Key" Ta Sy "Function"
.It Li "Enter" Ta "Set pane, window, session or global option value"
.It Li "Up" Ta "Select previous item"
@@ -2883,6 +2885,7 @@ The following keys may be used in customize mode:
.It Li "C-t" Ta "Tag all items"
.It Li "f" Ta "Enter a format to filter items"
.It Li "v" Ta "Toggle option information"
.It Li "F1 or C-h" Ta "Display help"
.It Li "q" Ta "Exit mode"
.El
.Pp
@@ -7393,7 +7396,7 @@ zooms the pane.
.Fl y
disables any confirmation prompts.
The following keys may be used in buffer mode:
.Bl -column "Key" "Function" -offset indent
.Bl -column "KeyXXXXXX" "Function" -offset indent
.It Sy "Key" Ta Sy "Function"
.It Li "Enter" Ta "Paste selected buffer"
.It Li "Up" Ta "Select previous buffer"
@@ -7413,6 +7416,7 @@ The following keys may be used in buffer mode:
.It Li "O" Ta "Change sort order"
.It Li "r" Ta "Reverse sort order"
.It Li "v" Ta "Toggle preview"
.It Li "F1 or C-h" Ta "Display help"
.It Li "q" Ta "Exit mode"
.El
.Pp

9
tmux.h
View File

@@ -3072,9 +3072,9 @@ void input_free(struct input_ctx *);
void input_reset(struct input_ctx *, int);
struct evbuffer *input_pending(struct input_ctx *);
void input_parse_pane(struct window_pane *);
void input_parse_buffer(struct window_pane *, u_char *, size_t);
void input_parse_buffer(struct window_pane *, const u_char *, size_t);
void input_parse_screen(struct input_ctx *, struct screen *,
screen_write_init_ctx_cb, void *, u_char *, size_t);
screen_write_init_ctx_cb, void *, const u_char *, size_t);
void input_reply_clipboard(struct bufferevent *, const char *, size_t,
const char *, char);
void input_set_buffer_size(size_t);
@@ -3462,6 +3462,7 @@ typedef key_code (*mode_tree_key_cb)(void *, void *, u_int);
typedef int (*mode_tree_swap_cb)(void *, void *, struct sort_criteria *);
typedef void (*mode_tree_sort_cb)(struct sort_criteria *);
typedef void (*mode_tree_each_cb)(void *, void *, struct client *, key_code);
typedef const char** (*mode_tree_help_cb)(u_int *, const char**);
u_int mode_tree_count_tagged(struct mode_tree_data *);
void *mode_tree_get_current(struct mode_tree_data *);
const char *mode_tree_get_current_name(struct mode_tree_data *);
@@ -3476,7 +3477,7 @@ int mode_tree_down(struct mode_tree_data *, int);
struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *,
mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb,
mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb,
mode_tree_swap_cb, mode_tree_sort_cb, void *,
mode_tree_swap_cb, mode_tree_sort_cb, mode_tree_help_cb, void *,
const struct menu_item *, struct screen **);
void mode_tree_zoom(struct mode_tree_data *, struct args *);
void mode_tree_build(struct mode_tree_data *);
@@ -3695,6 +3696,7 @@ int menu_key_cb(struct client *, void *, struct key_event *);
#define POPUP_CLOSEEXITZERO 0x2
#define POPUP_INTERNAL 0x4
#define POPUP_CLOSEANYKEY 0x8
#define POPUP_NOJOB 0x10
typedef void (*popup_close_cb)(int, void *);
typedef void (*popup_finish_edit_cb)(char *, size_t, void *);
int popup_display(int, enum box_lines, struct cmdq_item *, u_int,
@@ -3702,6 +3704,7 @@ int popup_display(int, enum box_lines, struct cmdq_item *, u_int,
char **, const char *, const char *, struct client *,
struct session *, const char *, const char *,
popup_close_cb, void *);
void popup_write(struct client *, const char *, size_t);
int popup_editor(struct client *, const char *, size_t,
popup_finish_edit_cb, void *);
int popup_present(struct client *);

View File

@@ -329,6 +329,25 @@ window_buffer_sort(struct sort_criteria *sort_crit)
sort_crit->order = sort_crit->order_seq[0];
}
static const char* window_buffer_help_lines[] = {
"\r\033[1m Enter \033[0m\016x\017 \033[0mPaste selected %1\n",
"\r\033[1m p \033[0m\016x\017 \033[0mPaste selected %1\n",
"\r\033[1m P \033[0m\016x\017 \033[0mPaste tagged %1s\n",
"\r\033[1m d \033[0m\016x\017 \033[0mDelete selected %1\n",
"\r\033[1m D \033[0m\016x\017 \033[0mDelete tagged %1s\n",
"\r\033[1m e \033[0m\016x\017 \033[0mOpen %1 in editor\n",
"\r\033[1m f \033[0m\016x\017 \033[0mEnter a filter\n",
NULL
};
static const char**
window_buffer_help(u_int *width, const char **item)
{
*width = 0;
*item = "buffer";
return (window_buffer_help_lines);
}
static struct screen *
window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
struct args *args)
@@ -356,8 +375,8 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_buffer_build,
window_buffer_draw, window_buffer_search, window_buffer_menu, NULL,
window_buffer_get_key, NULL, window_buffer_sort, data,
window_buffer_menu_items, &s);
window_buffer_get_key, NULL, window_buffer_sort, window_buffer_help,
data, window_buffer_menu_items, &s);
mode_tree_zoom(data->data, args);
mode_tree_build(data->data);

View File

@@ -240,6 +240,26 @@ window_client_sort(struct sort_criteria *sort_crit)
sort_crit->order = sort_crit->order_seq[0];
}
static const char* window_client_help_lines[] = {
"\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",
"\r\033[1m x \033[0m\016x\017 \033[0mDetach selected %1\n",
"\r\033[1m X \033[0m\016x\017 \033[0mDetach tagged %1s\n",
"\r\033[1m z \033[0m\016x\017 \033[0mSuspend selected %1\n",
"\r\033[1m Z \033[0m\016x\017 \033[0mSuspend tagged %1s\n",
"\r\033[1m f \033[0m\016x\017 \033[0mEnter a filter\n",
NULL
};
static const char**
window_client_help(u_int *width, const char **item)
{
*width = 0;
*item = "client";
return (window_client_help_lines);
}
static struct screen *
window_client_init(struct window_mode_entry *wme,
__unused struct cmd_find_state *fs, struct args *args)
@@ -266,8 +286,8 @@ window_client_init(struct window_mode_entry *wme,
data->data = mode_tree_start(wp, args, window_client_build,
window_client_draw, NULL, window_client_menu, NULL,
window_client_get_key, NULL, window_client_sort, data,
window_client_menu_items, &s);
window_client_get_key, NULL, window_client_sort,
window_client_help, data, window_client_menu_items, &s);
mode_tree_zoom(data->data, args);
mode_tree_build(data->data);

View File

@@ -868,6 +868,27 @@ window_customize_height(__unused void *modedata, __unused u_int height)
return (12);
}
static const char* window_customize_help_lines[] = {
"\r\033[1m Enter, s \033[0m\016x\017 \033[0mSet %1 value\n",
"\r\033[1m S \033[0m\016x\017 \033[0mSet global %1 value\n",
"\r\033[1m w \033[0m\016x\017 \033[0mSet window %1 value\n",
"\r\033[1m d \033[0m\016x\017 \033[0mSet to default value\n",
"\r\033[1m D \033[0m\016x\017 \033[0mSet tagged %1s to default value\n",
"\r\033[1m u \033[0m\016x\017 \033[0mUnset an %1\n",
"\r\033[1m U \033[0m\016x\017 \033[0mUnset tagged %1s\n",
"\r\033[1m f \033[0m\016x\017 \033[0mEnter a filter\n",
"\r\033[1m v \033[0m\016x\017 \033[0mToggle information\n",
NULL
};
static const char**
window_customize_help(u_int *width, const char **item)
{
*width = 52;
*item = "option";
return (window_customize_help_lines);
}
static struct screen *
window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
struct args *args)
@@ -891,8 +912,8 @@ window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_customize_build,
window_customize_draw, NULL, window_customize_menu,
window_customize_height, NULL, NULL, NULL, data,
window_customize_menu_items, &s);
window_customize_height, NULL, NULL, NULL, window_customize_help,
data, window_customize_menu_items, &s);
mode_tree_zoom(data->data, args);
mode_tree_build(data->data);

View File

@@ -860,6 +860,30 @@ window_tree_sort(struct sort_criteria *sort_crit)
sort_crit->order = sort_crit->order_seq[0];
}
static const char* window_tree_help_lines[] = {
"\r\033[1m Enter \033[0m\016x\017 \033[0mChoose selected item\n",
"\r\033[1m S-Up \033[0m\016x\017 \033[0mSwap current and previous window\n",
"\r\033[1m S-Down \033[0m\016x\017 \033[0mSwap current and next window\n",
"\r\033[1m x \033[0m\016x\017 \033[0mKill selected item\n",
"\r\033[1m X \033[0m\016x\017 \033[0mKill tagged items\n",
"\r\033[1m < \033[0m\016x\017 \033[0mScroll previews left\n",
"\r\033[1m > \033[0m\016x\017 \033[0mScroll previews right\n",
"\r\033[1m m \033[0m\016x\017 \033[0mSet the marked pane\n",
"\r\033[1m M \033[0m\016x\017 \033[0mClear the marked pane\n",
"\r\033[1m : \033[0m\016x\017 \033[0mRun a command for each tagged item\n",
"\r\033[1m f \033[0m\016x\017 \033[0mEnter a format\n",
"\r\033[1m H \033[0m\016x\017 \033[0mJump to the starting pane\n",
NULL
};
static const char**
window_tree_help(u_int *width, const char **item)
{
*width = 51;
*item = "item";
return (window_tree_help_lines);
}
static struct screen *
window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
struct args *args)
@@ -898,8 +922,8 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_tree_build,
window_tree_draw, window_tree_search, window_tree_menu, NULL,
window_tree_get_key, window_tree_swap, window_tree_sort, data,
window_tree_menu_items, &s);
window_tree_get_key, window_tree_swap, window_tree_sort,
window_tree_help, data, window_tree_menu_items, &s);
mode_tree_zoom(data->data, args);
mode_tree_build(data->data);