diff --git a/input.c b/input.c index 42bafa89..f8e95e19 100644 --- a/input.c +++ b/input.c @@ -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; diff --git a/mode-tree.c b/mode-tree.c index d76ff93d..0cd17e39 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -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: diff --git a/popup.c b/popup.c index d4100998..9bfa3880 100644 --- a/popup.c +++ b/popup.c @@ -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) { diff --git a/tmux.1 b/tmux.1 index e224015d..e9863792 100644 --- a/tmux.1 +++ b/tmux.1 @@ -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 diff --git a/tmux.h b/tmux.h index 0d30facc..e45b58e2 100644 --- a/tmux.h +++ b/tmux.h @@ -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 *); diff --git a/window-buffer.c b/window-buffer.c index ca8d4630..ac604a34 100644 --- a/window-buffer.c +++ b/window-buffer.c @@ -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); diff --git a/window-client.c b/window-client.c index 9f2d5dce..be1fd5fa 100644 --- a/window-client.c +++ b/window-client.c @@ -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); diff --git a/window-customize.c b/window-customize.c index 0887aa5c..3f78eca9 100644 --- a/window-customize.c +++ b/window-customize.c @@ -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); diff --git a/window-tree.c b/window-tree.c index 31bb6805..20877809 100644 --- a/window-tree.c +++ b/window-tree.c @@ -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);