From c43527a32cf0e7b4b63c25d17e0dee0aa2d554ac Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 27 Jan 2020 08:53:14 +0000 Subject: Add support for adding a note to a key binding (with bind-key -N) and use this to add descriptions to the default key bindings. A new -N flag to list-keys shows key bindings with notes rather than the default bind-key command used to create them. Change the default ? binding to use this to show a readable summary of keys. Also extend command-prompt to return the name of the key pressed and add a default binding (/) to show the note for the next key pressed Suggested by Alex Tremblay in GitHub issue 2000. --- usr.bin/tmux/cmd-bind-key.c | 14 ++-- usr.bin/tmux/cmd-command-prompt.c | 8 +- usr.bin/tmux/cmd-list-keys.c | 152 ++++++++++++++++++++++++++++++++-- usr.bin/tmux/key-bindings.c | 170 +++++++++++++++++++------------------- usr.bin/tmux/status.c | 10 ++- usr.bin/tmux/tmux.1 | 52 +++++++++--- usr.bin/tmux/tmux.h | 7 +- 7 files changed, 300 insertions(+), 113 deletions(-) (limited to 'usr.bin') diff --git a/usr.bin/tmux/cmd-bind-key.c b/usr.bin/tmux/cmd-bind-key.c index e5c6ca2878b..136d260c5e4 100644 --- a/usr.bin/tmux/cmd-bind-key.c +++ b/usr.bin/tmux/cmd-bind-key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-bind-key.c,v 1.34 2019/05/27 12:16:27 nicm Exp $ */ +/* $OpenBSD: cmd-bind-key.c,v 1.35 2020/01/27 08:53:13 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -33,8 +33,8 @@ const struct cmd_entry cmd_bind_key_entry = { .name = "bind-key", .alias = "bind", - .args = { "cnrT:", 2, -1 }, - .usage = "[-cnr] [-T key-table] key " + .args = { "cnrN:T:", 2, -1 }, + .usage = "[-cnr] [-T key-table] [-N note] key " "command [arguments]", .flags = CMD_AFTERHOOK, @@ -46,10 +46,10 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = self->args; key_code key; - const char *tablename; + const char *tablename, *note; struct cmd_parse_result *pr; char **argv = args->argv; - int argc = args->argc; + int argc = args->argc, repeat; key = key_string_lookup_string(argv[0]); if (key == KEYC_NONE || key == KEYC_UNKNOWN) { @@ -63,6 +63,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item) tablename = "root"; else tablename = "prefix"; + repeat = args_has(args, 'r'); if (argc == 2) pr = cmd_parse_from_string(argv[1], NULL); @@ -79,6 +80,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item) case CMD_PARSE_SUCCESS: break; } - key_bindings_add(tablename, key, args_has(args, 'r'), pr->cmdlist); + note = args_get(args, 'N'); + key_bindings_add(tablename, key, note, repeat, pr->cmdlist); return (CMD_RETURN_NORMAL); } diff --git a/usr.bin/tmux/cmd-command-prompt.c b/usr.bin/tmux/cmd-command-prompt.c index f297195b509..92486be0e17 100644 --- a/usr.bin/tmux/cmd-command-prompt.c +++ b/usr.bin/tmux/cmd-command-prompt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-command-prompt.c,v 1.46 2019/05/23 11:13:30 nicm Exp $ */ +/* $OpenBSD: cmd-command-prompt.c,v 1.47 2020/01/27 08:53:13 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -40,8 +40,8 @@ const struct cmd_entry cmd_command_prompt_entry = { .name = "command-prompt", .alias = NULL, - .args = { "1iI:Np:t:", 0, 1 }, - .usage = "[-1Ni] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " " + .args = { "1kiI:Np:t:", 0, 1 }, + .usage = "[-1kiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " " "[template]", .flags = 0, @@ -122,6 +122,8 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item) cdata->flags |= PROMPT_NUMERIC; else if (args_has(args, 'i')) cdata->flags |= PROMPT_INCREMENTAL; + else if (args_has(args, 'k')) + cdata->flags |= PROMPT_KEY; status_prompt_set(c, prompt, input, cmd_command_prompt_callback, cmd_command_prompt_free, cdata, cdata->flags); free(prompt); diff --git a/usr.bin/tmux/cmd-list-keys.c b/usr.bin/tmux/cmd-list-keys.c index 53e53a4eba6..f3a70c71776 100644 --- a/usr.bin/tmux/cmd-list-keys.c +++ b/usr.bin/tmux/cmd-list-keys.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-list-keys.c,v 1.49 2019/10/14 09:16:48 nicm Exp $ */ +/* $OpenBSD: cmd-list-keys.c,v 1.50 2020/01/27 08:53:13 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -36,8 +36,8 @@ const struct cmd_entry cmd_list_keys_entry = { .name = "list-keys", .alias = "lsk", - .args = { "T:", 0, 0 }, - .usage = "[-T key-table]", + .args = { "1NP:T:", 0, 1 }, + .usage = "[-1N] [-P prefix-string] [-T key-table] [key]", .flags = CMD_STARTSERVER|CMD_AFTERHOOK, .exec = cmd_list_keys_exec @@ -54,6 +54,88 @@ const struct cmd_entry cmd_list_commands_entry = { .exec = cmd_list_keys_exec }; +static u_int +cmd_list_keys_get_width(const char *tablename, key_code only) +{ + struct key_table *table; + struct key_binding *bd; + u_int width, keywidth = 0; + + table = key_bindings_get_table(tablename, 0); + if (table == NULL) + return (0); + bd = key_bindings_first(table); + while (bd != NULL) { + if ((only != KEYC_UNKNOWN && bd->key != only) || + KEYC_IS_MOUSE(bd->key) || + bd->note == NULL) { + bd = key_bindings_next(table, bd); + continue; + } + width = utf8_cstrwidth(key_string_lookup_key(bd->key)); + if (width > keywidth) + keywidth = width; + + bd = key_bindings_next(table, bd); + } + return (keywidth); +} + +static int +cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args, + const char *tablename, u_int keywidth, key_code only, const char *prefix) +{ + struct client *c = cmd_find_client(item, NULL, 1); + struct key_table *table; + struct key_binding *bd; + const char *key; + char *tmp; + int found = 0; + + table = key_bindings_get_table(tablename, 0); + if (table == NULL) + return (0); + bd = key_bindings_first(table); + while (bd != NULL) { + if ((only != KEYC_UNKNOWN && bd->key != only) || + KEYC_IS_MOUSE(bd->key) || + bd->note == NULL) { + bd = key_bindings_next(table, bd); + continue; + } + found = 1; + key = key_string_lookup_key(bd->key); + + tmp = utf8_padcstr(key, keywidth + 1); + if (args_has(args, '1') && c != NULL) + status_message_set(c, "%s%s%s", prefix, tmp, bd->note); + else + cmdq_print(item, "%s%s%s", prefix, tmp, bd->note); + free(tmp); + + if (args_has(args, '1')) + break; + bd = key_bindings_next(table, bd); + } + return (found); +} + +static char * +cmd_list_keys_get_prefix(struct args *args, key_code *prefix) +{ + char *s; + + *prefix = options_get_number(global_s_options, "prefix"); + if (!args_has(args, 'P')) { + if (*prefix != KEYC_NONE) + xasprintf(&s, "%s ", key_string_lookup_key(*prefix)); + else + s = xstrdup(""); + } else + s = xstrdup(args_get(args, 'P')); + return (s); +} + static enum cmd_retval cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) { @@ -61,19 +143,63 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) struct key_table *table; struct key_binding *bd; const char *tablename, *r; - char *key, *cp, *tmp; - int repeat, width, tablewidth, keywidth; + char *key, *cp, *tmp, *start, *empty; + key_code prefix, only = KEYC_UNKNOWN; + int repeat, width, tablewidth, keywidth, found = 0; size_t tmpsize, tmpused, cplen; if (self->entry == &cmd_list_commands_entry) return (cmd_list_keys_commands(self, item)); + if (args->argc != 0) { + only = key_string_lookup_string(args->argv[0]); + if (only == KEYC_UNKNOWN) { + cmdq_error(item, "invalid key: %s", args->argv[0]); + return (CMD_RETURN_ERROR); + } + } + tablename = args_get(args, 'T'); if (tablename != NULL && key_bindings_get_table(tablename, 0) == NULL) { cmdq_error(item, "table %s doesn't exist", tablename); return (CMD_RETURN_ERROR); } + if (args_has(args, 'N')) { + if (tablename == NULL) { + start = cmd_list_keys_get_prefix(args, &prefix); + keywidth = cmd_list_keys_get_width("root", only); + if (prefix != KEYC_NONE) { + width = cmd_list_keys_get_width("prefix", only); + if (width == 0) + prefix = KEYC_NONE; + else if (width > keywidth) + keywidth = width; + } + empty = utf8_padcstr("", utf8_cstrwidth(start)); + + found = cmd_list_keys_print_notes(item, args, "root", + keywidth, only, empty); + if (prefix != KEYC_NONE) { + if (cmd_list_keys_print_notes(item, args, + "prefix", keywidth, only, start)) + found = 1; + } + free(empty); + } else { + if (args_has(args, 'P')) + start = xstrdup(args_get(args, 'P')); + else + start = xstrdup(""); + keywidth = cmd_list_keys_get_width(tablename, only); + found = cmd_list_keys_print_notes(item, args, tablename, + keywidth, only, start); + + } + free(start); + goto out; + } + repeat = 0; tablewidth = keywidth = 0; table = key_bindings_first_table (); @@ -84,6 +210,10 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) } bd = key_bindings_first(table); while (bd != NULL) { + if (only != KEYC_UNKNOWN && bd->key != only) { + bd = key_bindings_next(table, bd); + continue; + } key = args_escape(key_string_lookup_key(bd->key)); if (bd->flags & KEY_BINDING_REPEAT) @@ -113,6 +243,11 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) } bd = key_bindings_first(table); while (bd != NULL) { + if (only != KEYC_UNKNOWN && bd->key != only) { + bd = key_bindings_next(table, bd); + continue; + } + found = 1; key = args_escape(key_string_lookup_key(bd->key)); if (!repeat) @@ -162,13 +297,18 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) free(tmp); +out: + if (only != KEYC_UNKNOWN && !found) { + cmdq_error(item, "unknown key: %s", args->argv[0]); + return (CMD_RETURN_ERROR); + } return (CMD_RETURN_NORMAL); } static enum cmd_retval cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item) { - struct args *args = self->args; + struct args *args = self->args; const struct cmd_entry **entryp; const struct cmd_entry *entry; struct format_tree *ft; diff --git a/usr.bin/tmux/key-bindings.c b/usr.bin/tmux/key-bindings.c index 4514e971f95..4ff38ccf0a9 100644 --- a/usr.bin/tmux/key-bindings.c +++ b/usr.bin/tmux/key-bindings.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key-bindings.c,v 1.106 2020/01/05 20:39:25 nicm Exp $ */ +/* $OpenBSD: key-bindings.c,v 1.107 2020/01/27 08:53:13 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -90,6 +90,7 @@ key_bindings_free(struct key_table *table, struct key_binding *bd) { RB_REMOVE(key_bindings, &table->key_bindings, bd); cmd_list_free(bd->cmdlist); + free((void *)bd->note); free(bd); } @@ -163,7 +164,7 @@ key_bindings_next(__unused struct key_table *table, struct key_binding *bd) } void -key_bindings_add(const char *name, key_code key, int repeat, +key_bindings_add(const char *name, key_code key, const char *note, int repeat, struct cmd_list *cmdlist) { struct key_table *table; @@ -177,6 +178,8 @@ key_bindings_add(const char *name, key_code key, int repeat, bd = xcalloc(1, sizeof *bd); bd->key = key; + if (note != NULL) + bd->note = xstrdup(note); RB_INSERT(key_bindings, &table->key_bindings, bd); if (repeat) @@ -226,87 +229,88 @@ void key_bindings_init(void) { static const char *defaults[] = { - "bind C-b send-prefix", - "bind C-o rotate-window", - "bind C-z suspend-client", - "bind Space next-layout", - "bind ! break-pane", - "bind '\"' split-window", - "bind '#' list-buffers", - "bind '$' command-prompt -I'#S' \"rename-session -- '%%'\"", - "bind % split-window -h", - "bind & confirm-before -p\"kill-window #W? (y/n)\" kill-window", - "bind \"'\" command-prompt -pindex \"select-window -t ':%%'\"", - "bind ( switch-client -p", - "bind ) switch-client -n", - "bind , command-prompt -I'#W' \"rename-window -- '%%'\"", - "bind - delete-buffer", - "bind . command-prompt \"move-window -t '%%'\"", - "bind 0 select-window -t:=0", - "bind 1 select-window -t:=1", - "bind 2 select-window -t:=2", - "bind 3 select-window -t:=3", - "bind 4 select-window -t:=4", - "bind 5 select-window -t:=5", - "bind 6 select-window -t:=6", - "bind 7 select-window -t:=7", - "bind 8 select-window -t:=8", - "bind 9 select-window -t:=9", - "bind : command-prompt", - "bind \\; last-pane", - "bind = choose-buffer -Z", - "bind ? list-keys", - "bind D choose-client -Z", - "bind E select-layout -E", - "bind L switch-client -l", - "bind M select-pane -M", - "bind [ copy-mode", - "bind ] paste-buffer", - "bind c new-window", - "bind d detach-client", - "bind f command-prompt \"find-window -Z -- '%%'\"", - "bind i display-message", - "bind l last-window", - "bind m select-pane -m", - "bind n next-window", - "bind o select-pane -t:.+", - "bind p previous-window", - "bind q display-panes", - "bind r refresh-client", - "bind s choose-tree -Zs", - "bind t clock-mode", - "bind w choose-tree -Zw", - "bind x confirm-before -p\"kill-pane #P? (y/n)\" kill-pane", - "bind z resize-pane -Z", - "bind '{' swap-pane -U", - "bind '}' swap-pane -D", - "bind '~' show-messages", - "bind PPage copy-mode -u", - "bind -r Up select-pane -U", - "bind -r Down select-pane -D", - "bind -r Left select-pane -L", - "bind -r Right select-pane -R", - "bind M-1 select-layout even-horizontal", - "bind M-2 select-layout even-vertical", - "bind M-3 select-layout main-horizontal", - "bind M-4 select-layout main-vertical", - "bind M-5 select-layout tiled", - "bind M-n next-window -a", - "bind M-o rotate-window -D", - "bind M-p previous-window -a", - "bind -r S-Up refresh-client -U 10", - "bind -r S-Down refresh-client -D 10", - "bind -r S-Left refresh-client -L 10", - "bind -r S-Right refresh-client -R 10", - "bind -r DC refresh-client -c", - "bind -r M-Up resize-pane -U 5", - "bind -r M-Down resize-pane -D 5", - "bind -r M-Left resize-pane -L 5", - "bind -r M-Right resize-pane -R 5", - "bind -r C-Up resize-pane -U", - "bind -r C-Down resize-pane -D", - "bind -r C-Left resize-pane -L", - "bind -r C-Right resize-pane -R", + "bind -N 'Send the prefix key' C-b send-prefix", + "bind -N 'Rotate through the panes' C-o rotate-window", + "bind -N 'Suspend the current client' C-z suspend-client", + "bind -N 'Select next layout' Space next-layout", + "bind -N 'Break pane to a new window' ! break-pane", + "bind -N 'Split window vertically' '\"' split-window", + "bind -N 'List all paste buffers' '#' list-buffers", + "bind -N 'Rename current session' '$' command-prompt -I'#S' \"rename-session -- '%%'\"", + "bind -N 'Split window horizontally' % split-window -h", + "bind -N 'Kill current window' & confirm-before -p\"kill-window #W? (y/n)\" kill-window", + "bind -N 'Prompt for window index to select' \"'\" command-prompt -pindex \"select-window -t ':%%'\"", + "bind -N 'Switch to previous client' ( switch-client -p", + "bind -N 'Switch to next client' ) switch-client -n", + "bind -N 'Rename current window' , command-prompt -I'#W' \"rename-window -- '%%'\"", + "bind -N 'Delete the most recent paste buffer' - delete-buffer", + "bind -N 'Move the current window' . command-prompt \"move-window -t '%%'\"", + "bind -N 'Describe key binding' '/' command-prompt -kpkey 'list-keys -1N \"%%%\"'", + "bind -N 'Select window 0' 0 select-window -t:=0", + "bind -N 'Select window 1' 1 select-window -t:=1", + "bind -N 'Select window 2' 2 select-window -t:=2", + "bind -N 'Select window 3' 3 select-window -t:=3", + "bind -N 'Select window 4' 4 select-window -t:=4", + "bind -N 'Select window 5' 5 select-window -t:=5", + "bind -N 'Select window 6' 6 select-window -t:=6", + "bind -N 'Select window 7' 7 select-window -t:=7", + "bind -N 'Select window 8' 8 select-window -t:=8", + "bind -N 'Select window 9' 9 select-window -t:=9", + "bind -N 'Prompt for a command' : command-prompt", + "bind -N 'Move to the previously active pane' \\; last-pane", + "bind -N 'Choose a paste buffer from a list' = choose-buffer -Z", + "bind -N 'List key bindings' ? list-keys -N", + "bind -N 'Choose a client from a list' D choose-client -Z", + "bind -N 'Spread panes out evenly' E select-layout -E", + "bind -N 'Switch to the last client' L switch-client -l", + "bind -N 'Clear the marked pane' M select-pane -M", + "bind -N 'Enter copy mode' [ copy-mode", + "bind -N 'Paste the most recent paste buffer' ] paste-buffer", + "bind -N 'Create a new window' c new-window", + "bind -N 'Detach the current client' d detach-client", + "bind -N 'Search for a pane' f command-prompt \"find-window -Z -- '%%'\"", + "bind -N 'Display window information' i display-message", + "bind -N 'Select the previously current window' l last-window", + "bind -N 'Toggle the marked pane' m select-pane -m", + "bind -N 'Select the next window' n next-window", + "bind -N 'Select the next pane' o select-pane -t:.+", + "bind -N 'Select the previous pane' p previous-window", + "bind -N 'Display pane numbers' q display-panes", + "bind -N 'Redraw the current client' r refresh-client", + "bind -N 'Choose a session from a list' s choose-tree -Zs", + "bind -N 'Show a clock' t clock-mode", + "bind -N 'Choose a window from a list' w choose-tree -Zw", + "bind -N 'Kill the active pane' x confirm-before -p\"kill-pane #P? (y/n)\" kill-pane", + "bind -N 'Zoom the active pane' z resize-pane -Z", + "bind -N 'Swap the active pane with the pane above' '{' swap-pane -U", + "bind -N 'Swap the active pane with the pane below' '}' swap-pane -D", + "bind -N 'Show messages' '~' show-messages", + "bind -N 'Enter copy mode and scroll up' PPage copy-mode -u", + "bind -N 'Select the pane above the active pane' -r Up select-pane -U", + "bind -N 'Select the pane below the active pane' -r Down select-pane -D", + "bind -N 'Select the pane to the left of the active pane' -r Left select-pane -L", + "bind -N 'Select the pane to the right of the active pane' -r Right select-pane -R", + "bind -N 'Set the even-horizontal layout' M-1 select-layout even-horizontal", + "bind -N 'Set the even-vertical layout' M-2 select-layout even-vertical", + "bind -N 'Set the main-horizontal layout' M-3 select-layout main-horizontal", + "bind -N 'Set the main-vertical layout' M-4 select-layout main-vertical", + "bind -N 'Select the tiled layout' M-5 select-layout tiled", + "bind -N 'Select the next window with an alert' M-n next-window -a", + "bind -N 'Rotate through the panes in reverse' M-o rotate-window -D", + "bind -N 'Select the previous window with an alert' M-p previous-window -a", + "bind -N 'Move the visible part of the window up' -r S-Up refresh-client -U 10", + "bind -N 'Move the visible part of the window down' -r S-Down refresh-client -D 10", + "bind -N 'Move the visible part of the window left' -r S-Left refresh-client -L 10", + "bind -N 'Move the visible part of the window right' -r S-Right refresh-client -R 10", + "bind -N 'Reset so the visible part of the window follows the cursor' -r DC refresh-client -c", + "bind -N 'Resize the pane up by 5' -r M-Up resize-pane -U 5", + "bind -N 'Resize the pane down by 5' -r M-Down resize-pane -D 5", + "bind -N 'Resize the pane left by 5' -r M-Left resize-pane -L 5", + "bind -N 'Resize the pane right by 5' -r M-Right resize-pane -R 5", + "bind -N 'Resize the pane up' -r C-Up resize-pane -U", + "bind -N 'Resize the pane down' -r C-Down resize-pane -D", + "bind -N 'Resize the pane left' -r C-Left resize-pane -L", + "bind -N 'Resize the pane right' -r C-Right resize-pane -R", "bind -n MouseDown1Pane select-pane -t=\\; send-keys -M", "bind -n MouseDrag1Border resize-pane -M", diff --git a/usr.bin/tmux/status.c b/usr.bin/tmux/status.c index 151f7310159..5e11958f7b6 100644 --- a/usr.bin/tmux/status.c +++ b/usr.bin/tmux/status.c @@ -1,4 +1,4 @@ -/* $OpenBSD: status.c,v 1.200 2019/05/28 18:53:36 nicm Exp $ */ +/* $OpenBSD: status.c,v 1.201 2020/01/27 08:53:13 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -915,11 +915,17 @@ status_prompt_key(struct client *c, key_code key) { struct options *oo = c->session->options; char *s, *cp, word[64], prefix = '='; - const char *histstr, *ws = NULL; + const char *histstr, *ws = NULL, *keystring; size_t size, n, off, idx, used; struct utf8_data tmp, *first, *last, *ud; int keys; + if (c->prompt_flags & PROMPT_KEY) { + keystring = key_string_lookup_key(key); + c->prompt_inputcb(c, c->prompt_data, keystring, 1); + status_prompt_clear(c); + return (0); + } size = utf8_strlen(c->prompt_buffer); if (c->prompt_flags & PROMPT_NUMERIC) { diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 1114dfb0348..e3c80d7acd7 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.705 2020/01/25 16:40:32 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.706 2020/01/27 08:53:13 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 25 2020 $ +.Dd $Mdocdate: January 27 2020 $ .Dt TMUX 1 .Os .Sh NAME @@ -551,7 +551,7 @@ Braces may be enclosed inside braces, for example: .Bd -literal -offset indent bind x if-shell "true" { if-shell "true" { - display "true!" + display "true!" } } .Ed @@ -1335,7 +1335,8 @@ is used, option will not be applied. .Pp .Fl T -sets the client's key table; the next key from the client will be interpreted from +sets the client's key table; the next key from the client will be interpreted +from .Ar key-table . This may be used to configure multiple prefix keys, or to bind commands to sequences of keys. @@ -2613,6 +2614,7 @@ Commands related to key bindings are as follows: .Bl -tag -width Ds .It Xo Ic bind-key .Op Fl nr +.Op Fl N Ar note .Op Fl T Ar key-table .Ar key Ar command Op Ar arguments .Xc @@ -2660,22 +2662,46 @@ The flag indicates this key may repeat, see the .Ic repeat-time option. +.Fl N +attaches a note to the key (shown with +.Ic list-keys +.Fl N ) . .Pp To view the default bindings and possible commands, see the .Ic list-keys command. .It Xo Ic list-keys -.Op Fl T Ar key-table +.Op Fl 1N +.Op Fl P Ar prefix-string Fl T Ar key-table +.Op key .Xc .D1 (alias: Ic lsk ) List all key bindings. -Without -.Fl T -all key tables are printed. +By default this shows all keys or any bindings for +.Ar key +in the syntax of the +.Ic bind-key +command. +.Fl N +instead show keys and attached notes, i +.Ar key-table +if given or in the +.Em root +and +.Em prefix +key tables by default. +.Fl P +specifies a prefix to print before each key. With +.Fl 1 +only the first matching key and note is shown. +.Pp +Without +.Fl N , .Fl T -only -.Ar key-table . +prints only keys in +.Ar key-table , +otherwise all key tables are printed. .It Xo Ic send-keys .Op Fl FHlMRX .Op Fl N Ar repeat-count @@ -4693,7 +4719,7 @@ session option. Commands related to the status line are as follows: .Bl -tag -width Ds .It Xo Ic command-prompt -.Op Fl 1Ni +.Op Fl 1ikN .Op Fl I Ar inputs .Op Fl p Ar prompts .Op Fl t Ar target-client @@ -4743,6 +4769,10 @@ but any quotation marks are escaped. .Fl 1 makes the prompt only accept one key press, in this case the resulting input is a single character. +.Fl k +is like +.Fl 1 +but the key press is translated to a key name. .Fl N makes the prompt only accept numeric key presses. .Fl i diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 578e5d748c5..d86ccad0feb 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.948 2020/01/13 11:59:21 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.949 2020/01/27 08:53:13 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1609,6 +1609,7 @@ struct client { #define PROMPT_NUMERIC 0x2 #define PROMPT_INCREMENTAL 0x4 #define PROMPT_NOFORMAT 0x8 +#define PROMPT_KEY 0x10 int prompt_flags; struct session *session; @@ -1636,6 +1637,7 @@ TAILQ_HEAD(clients, client); struct key_binding { key_code key; struct cmd_list *cmdlist; + const char *note; int flags; #define KEY_BINDING_REPEAT 0x1 @@ -2147,7 +2149,8 @@ void key_bindings_unref_table(struct key_table *); struct key_binding *key_bindings_get(struct key_table *, key_code); struct key_binding *key_bindings_first(struct key_table *); struct key_binding *key_bindings_next(struct key_table *, struct key_binding *); -void key_bindings_add(const char *, key_code, int, struct cmd_list *); +void key_bindings_add(const char *, key_code, const char *, int, + struct cmd_list *); void key_bindings_remove(const char *, key_code); void key_bindings_remove_table(const char *); void key_bindings_init(void); -- cgit v1.2.3