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.
This commit is contained in:
nicm 2020-01-27 08:53:13 +00:00
parent 2e39b621c9
commit d0b8d036be
7 changed files with 292 additions and 105 deletions

View File

@ -33,8 +33,8 @@ const struct cmd_entry cmd_bind_key_entry = {
.name = "bind-key", .name = "bind-key",
.alias = "bind", .alias = "bind",
.args = { "cnrT:", 2, -1 }, .args = { "cnrN:T:", 2, -1 },
.usage = "[-cnr] [-T key-table] key " .usage = "[-cnr] [-T key-table] [-N note] key "
"command [arguments]", "command [arguments]",
.flags = CMD_AFTERHOOK, .flags = CMD_AFTERHOOK,
@ -46,10 +46,10 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
{ {
struct args *args = self->args; struct args *args = self->args;
key_code key; key_code key;
const char *tablename; const char *tablename, *note;
struct cmd_parse_result *pr; struct cmd_parse_result *pr;
char **argv = args->argv; char **argv = args->argv;
int argc = args->argc; int argc = args->argc, repeat;
key = key_string_lookup_string(argv[0]); key = key_string_lookup_string(argv[0]);
if (key == KEYC_NONE || key == KEYC_UNKNOWN) { if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
@ -63,6 +63,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
tablename = "root"; tablename = "root";
else else
tablename = "prefix"; tablename = "prefix";
repeat = args_has(args, 'r');
if (argc == 2) if (argc == 2)
pr = cmd_parse_from_string(argv[1], NULL); 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: case CMD_PARSE_SUCCESS:
break; 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); return (CMD_RETURN_NORMAL);
} }

View File

@ -40,8 +40,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
.name = "command-prompt", .name = "command-prompt",
.alias = NULL, .alias = NULL,
.args = { "1iI:Np:t:", 0, 1 }, .args = { "1kiI:Np:t:", 0, 1 },
.usage = "[-1Ni] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " " .usage = "[-1kiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
"[template]", "[template]",
.flags = 0, .flags = 0,
@ -122,6 +122,8 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
cdata->flags |= PROMPT_NUMERIC; cdata->flags |= PROMPT_NUMERIC;
else if (args_has(args, 'i')) else if (args_has(args, 'i'))
cdata->flags |= PROMPT_INCREMENTAL; cdata->flags |= PROMPT_INCREMENTAL;
else if (args_has(args, 'k'))
cdata->flags |= PROMPT_KEY;
status_prompt_set(c, prompt, input, cmd_command_prompt_callback, status_prompt_set(c, prompt, input, cmd_command_prompt_callback,
cmd_command_prompt_free, cdata, cdata->flags); cmd_command_prompt_free, cdata, cdata->flags);
free(prompt); free(prompt);

View File

@ -36,8 +36,8 @@ const struct cmd_entry cmd_list_keys_entry = {
.name = "list-keys", .name = "list-keys",
.alias = "lsk", .alias = "lsk",
.args = { "T:", 0, 0 }, .args = { "1NP:T:", 0, 1 },
.usage = "[-T key-table]", .usage = "[-1N] [-P prefix-string] [-T key-table] [key]",
.flags = CMD_STARTSERVER|CMD_AFTERHOOK, .flags = CMD_STARTSERVER|CMD_AFTERHOOK,
.exec = cmd_list_keys_exec .exec = cmd_list_keys_exec
@ -54,6 +54,88 @@ const struct cmd_entry cmd_list_commands_entry = {
.exec = cmd_list_keys_exec .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 static enum cmd_retval
cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) 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_table *table;
struct key_binding *bd; struct key_binding *bd;
const char *tablename, *r; const char *tablename, *r;
char *key, *cp, *tmp; char *key, *cp, *tmp, *start, *empty;
int repeat, width, tablewidth, keywidth; key_code prefix, only = KEYC_UNKNOWN;
int repeat, width, tablewidth, keywidth, found = 0;
size_t tmpsize, tmpused, cplen; size_t tmpsize, tmpused, cplen;
if (self->entry == &cmd_list_commands_entry) if (self->entry == &cmd_list_commands_entry)
return (cmd_list_keys_commands(self, item)); 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'); tablename = args_get(args, 'T');
if (tablename != NULL && key_bindings_get_table(tablename, 0) == NULL) { if (tablename != NULL && key_bindings_get_table(tablename, 0) == NULL) {
cmdq_error(item, "table %s doesn't exist", tablename); cmdq_error(item, "table %s doesn't exist", tablename);
return (CMD_RETURN_ERROR); 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; repeat = 0;
tablewidth = keywidth = 0; tablewidth = keywidth = 0;
table = key_bindings_first_table (); 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); bd = key_bindings_first(table);
while (bd != NULL) { 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)); key = args_escape(key_string_lookup_key(bd->key));
if (bd->flags & KEY_BINDING_REPEAT) 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); bd = key_bindings_first(table);
while (bd != NULL) { 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)); key = args_escape(key_string_lookup_key(bd->key));
if (!repeat) if (!repeat)
@ -162,13 +297,18 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
free(tmp); 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); return (CMD_RETURN_NORMAL);
} }
static enum cmd_retval static enum cmd_retval
cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item) 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 **entryp;
const struct cmd_entry *entry; const struct cmd_entry *entry;
struct format_tree *ft; struct format_tree *ft;

View File

@ -90,6 +90,7 @@ key_bindings_free(struct key_table *table, struct key_binding *bd)
{ {
RB_REMOVE(key_bindings, &table->key_bindings, bd); RB_REMOVE(key_bindings, &table->key_bindings, bd);
cmd_list_free(bd->cmdlist); cmd_list_free(bd->cmdlist);
free((void *)bd->note);
free(bd); free(bd);
} }
@ -163,7 +164,7 @@ key_bindings_next(__unused struct key_table *table, struct key_binding *bd)
} }
void 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 cmd_list *cmdlist)
{ {
struct key_table *table; 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 = xcalloc(1, sizeof *bd);
bd->key = key; bd->key = key;
if (note != NULL)
bd->note = xstrdup(note);
RB_INSERT(key_bindings, &table->key_bindings, bd); RB_INSERT(key_bindings, &table->key_bindings, bd);
if (repeat) if (repeat)
@ -226,87 +229,88 @@ void
key_bindings_init(void) key_bindings_init(void)
{ {
static const char *defaults[] = { static const char *defaults[] = {
"bind C-b send-prefix", "bind -N 'Send the prefix key' C-b send-prefix",
"bind C-o rotate-window", "bind -N 'Rotate through the panes' C-o rotate-window",
"bind C-z suspend-client", "bind -N 'Suspend the current client' C-z suspend-client",
"bind Space next-layout", "bind -N 'Select next layout' Space next-layout",
"bind ! break-pane", "bind -N 'Break pane to a new window' ! break-pane",
"bind '\"' split-window", "bind -N 'Split window vertically' '\"' split-window",
"bind '#' list-buffers", "bind -N 'List all paste buffers' '#' list-buffers",
"bind '$' command-prompt -I'#S' \"rename-session -- '%%'\"", "bind -N 'Rename current session' '$' command-prompt -I'#S' \"rename-session -- '%%'\"",
"bind % split-window -h", "bind -N 'Split window horizontally' % split-window -h",
"bind & confirm-before -p\"kill-window #W? (y/n)\" kill-window", "bind -N 'Kill current window' & confirm-before -p\"kill-window #W? (y/n)\" kill-window",
"bind \"'\" command-prompt -pindex \"select-window -t ':%%'\"", "bind -N 'Prompt for window index to select' \"'\" command-prompt -pindex \"select-window -t ':%%'\"",
"bind ( switch-client -p", "bind -N 'Switch to previous client' ( switch-client -p",
"bind ) switch-client -n", "bind -N 'Switch to next client' ) switch-client -n",
"bind , command-prompt -I'#W' \"rename-window -- '%%'\"", "bind -N 'Rename current window' , command-prompt -I'#W' \"rename-window -- '%%'\"",
"bind - delete-buffer", "bind -N 'Delete the most recent paste buffer' - delete-buffer",
"bind . command-prompt \"move-window -t '%%'\"", "bind -N 'Move the current window' . command-prompt \"move-window -t '%%'\"",
"bind 0 select-window -t:=0", "bind -N 'Describe key binding' '/' command-prompt -kpkey 'list-keys -1N \"%%%\"'",
"bind 1 select-window -t:=1", "bind -N 'Select window 0' 0 select-window -t:=0",
"bind 2 select-window -t:=2", "bind -N 'Select window 1' 1 select-window -t:=1",
"bind 3 select-window -t:=3", "bind -N 'Select window 2' 2 select-window -t:=2",
"bind 4 select-window -t:=4", "bind -N 'Select window 3' 3 select-window -t:=3",
"bind 5 select-window -t:=5", "bind -N 'Select window 4' 4 select-window -t:=4",
"bind 6 select-window -t:=6", "bind -N 'Select window 5' 5 select-window -t:=5",
"bind 7 select-window -t:=7", "bind -N 'Select window 6' 6 select-window -t:=6",
"bind 8 select-window -t:=8", "bind -N 'Select window 7' 7 select-window -t:=7",
"bind 9 select-window -t:=9", "bind -N 'Select window 8' 8 select-window -t:=8",
"bind : command-prompt", "bind -N 'Select window 9' 9 select-window -t:=9",
"bind \\; last-pane", "bind -N 'Prompt for a command' : command-prompt",
"bind = choose-buffer -Z", "bind -N 'Move to the previously active pane' \\; last-pane",
"bind ? list-keys", "bind -N 'Choose a paste buffer from a list' = choose-buffer -Z",
"bind D choose-client -Z", "bind -N 'List key bindings' ? list-keys -N",
"bind E select-layout -E", "bind -N 'Choose a client from a list' D choose-client -Z",
"bind L switch-client -l", "bind -N 'Spread panes out evenly' E select-layout -E",
"bind M select-pane -M", "bind -N 'Switch to the last client' L switch-client -l",
"bind [ copy-mode", "bind -N 'Clear the marked pane' M select-pane -M",
"bind ] paste-buffer", "bind -N 'Enter copy mode' [ copy-mode",
"bind c new-window", "bind -N 'Paste the most recent paste buffer' ] paste-buffer",
"bind d detach-client", "bind -N 'Create a new window' c new-window",
"bind f command-prompt \"find-window -Z -- '%%'\"", "bind -N 'Detach the current client' d detach-client",
"bind i display-message", "bind -N 'Search for a pane' f command-prompt \"find-window -Z -- '%%'\"",
"bind l last-window", "bind -N 'Display window information' i display-message",
"bind m select-pane -m", "bind -N 'Select the previously current window' l last-window",
"bind n next-window", "bind -N 'Toggle the marked pane' m select-pane -m",
"bind o select-pane -t:.+", "bind -N 'Select the next window' n next-window",
"bind p previous-window", "bind -N 'Select the next pane' o select-pane -t:.+",
"bind q display-panes", "bind -N 'Select the previous pane' p previous-window",
"bind r refresh-client", "bind -N 'Display pane numbers' q display-panes",
"bind s choose-tree -Zs", "bind -N 'Redraw the current client' r refresh-client",
"bind t clock-mode", "bind -N 'Choose a session from a list' s choose-tree -Zs",
"bind w choose-tree -Zw", "bind -N 'Show a clock' t clock-mode",
"bind x confirm-before -p\"kill-pane #P? (y/n)\" kill-pane", "bind -N 'Choose a window from a list' w choose-tree -Zw",
"bind z resize-pane -Z", "bind -N 'Kill the active pane' x confirm-before -p\"kill-pane #P? (y/n)\" kill-pane",
"bind '{' swap-pane -U", "bind -N 'Zoom the active pane' z resize-pane -Z",
"bind '}' swap-pane -D", "bind -N 'Swap the active pane with the pane above' '{' swap-pane -U",
"bind '~' show-messages", "bind -N 'Swap the active pane with the pane below' '}' swap-pane -D",
"bind PPage copy-mode -u", "bind -N 'Show messages' '~' show-messages",
"bind -r Up select-pane -U", "bind -N 'Enter copy mode and scroll up' PPage copy-mode -u",
"bind -r Down select-pane -D", "bind -N 'Select the pane above the active pane' -r Up select-pane -U",
"bind -r Left select-pane -L", "bind -N 'Select the pane below the active pane' -r Down select-pane -D",
"bind -r Right select-pane -R", "bind -N 'Select the pane to the left of the active pane' -r Left select-pane -L",
"bind M-1 select-layout even-horizontal", "bind -N 'Select the pane to the right of the active pane' -r Right select-pane -R",
"bind M-2 select-layout even-vertical", "bind -N 'Set the even-horizontal layout' M-1 select-layout even-horizontal",
"bind M-3 select-layout main-horizontal", "bind -N 'Set the even-vertical layout' M-2 select-layout even-vertical",
"bind M-4 select-layout main-vertical", "bind -N 'Set the main-horizontal layout' M-3 select-layout main-horizontal",
"bind M-5 select-layout tiled", "bind -N 'Set the main-vertical layout' M-4 select-layout main-vertical",
"bind M-n next-window -a", "bind -N 'Select the tiled layout' M-5 select-layout tiled",
"bind M-o rotate-window -D", "bind -N 'Select the next window with an alert' M-n next-window -a",
"bind M-p previous-window -a", "bind -N 'Rotate through the panes in reverse' M-o rotate-window -D",
"bind -r S-Up refresh-client -U 10", "bind -N 'Select the previous window with an alert' M-p previous-window -a",
"bind -r S-Down refresh-client -D 10", "bind -N 'Move the visible part of the window up' -r S-Up refresh-client -U 10",
"bind -r S-Left refresh-client -L 10", "bind -N 'Move the visible part of the window down' -r S-Down refresh-client -D 10",
"bind -r S-Right refresh-client -R 10", "bind -N 'Move the visible part of the window left' -r S-Left refresh-client -L 10",
"bind -r DC refresh-client -c", "bind -N 'Move the visible part of the window right' -r S-Right refresh-client -R 10",
"bind -r M-Up resize-pane -U 5", "bind -N 'Reset so the visible part of the window follows the cursor' -r DC refresh-client -c",
"bind -r M-Down resize-pane -D 5", "bind -N 'Resize the pane up by 5' -r M-Up resize-pane -U 5",
"bind -r M-Left resize-pane -L 5", "bind -N 'Resize the pane down by 5' -r M-Down resize-pane -D 5",
"bind -r M-Right resize-pane -R 5", "bind -N 'Resize the pane left by 5' -r M-Left resize-pane -L 5",
"bind -r C-Up resize-pane -U", "bind -N 'Resize the pane right by 5' -r M-Right resize-pane -R 5",
"bind -r C-Down resize-pane -D", "bind -N 'Resize the pane up' -r C-Up resize-pane -U",
"bind -r C-Left resize-pane -L", "bind -N 'Resize the pane down' -r C-Down resize-pane -D",
"bind -r C-Right resize-pane -R", "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 MouseDown1Pane select-pane -t=\\; send-keys -M",
"bind -n MouseDrag1Border resize-pane -M", "bind -n MouseDrag1Border resize-pane -M",

View File

@ -915,11 +915,17 @@ status_prompt_key(struct client *c, key_code key)
{ {
struct options *oo = c->session->options; struct options *oo = c->session->options;
char *s, *cp, word[64], prefix = '='; char *s, *cp, word[64], prefix = '=';
const char *histstr, *ws = NULL; const char *histstr, *ws = NULL, *keystring;
size_t size, n, off, idx, used; size_t size, n, off, idx, used;
struct utf8_data tmp, *first, *last, *ud; struct utf8_data tmp, *first, *last, *ud;
int keys; 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); size = utf8_strlen(c->prompt_buffer);
if (c->prompt_flags & PROMPT_NUMERIC) { if (c->prompt_flags & PROMPT_NUMERIC) {

48
tmux.1
View File

@ -551,7 +551,7 @@ Braces may be enclosed inside braces, for example:
.Bd -literal -offset indent .Bd -literal -offset indent
bind x if-shell "true" { bind x if-shell "true" {
if-shell "true" { if-shell "true" {
display "true!" display "true!"
} }
} }
.Ed .Ed
@ -1335,7 +1335,8 @@ is used,
option will not be applied. option will not be applied.
.Pp .Pp
.Fl T .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 . .Ar key-table .
This may be used to configure multiple prefix keys, or to bind commands to This may be used to configure multiple prefix keys, or to bind commands to
sequences of keys. sequences of keys.
@ -2613,6 +2614,7 @@ Commands related to key bindings are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Xo Ic bind-key .It Xo Ic bind-key
.Op Fl nr .Op Fl nr
.Op Fl N Ar note
.Op Fl T Ar key-table .Op Fl T Ar key-table
.Ar key Ar command Op Ar arguments .Ar key Ar command Op Ar arguments
.Xc .Xc
@ -2660,22 +2662,46 @@ The
flag indicates this key may repeat, see the flag indicates this key may repeat, see the
.Ic repeat-time .Ic repeat-time
option. option.
.Fl N
attaches a note to the key (shown with
.Ic list-keys
.Fl N ) .
.Pp .Pp
To view the default bindings and possible commands, see the To view the default bindings and possible commands, see the
.Ic list-keys .Ic list-keys
command. command.
.It Xo Ic list-keys .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 .Xc
.D1 (alias: Ic lsk ) .D1 (alias: Ic lsk )
List all key bindings. List all key bindings.
Without By default this shows all keys or any bindings for
.Fl T .Ar key
all key tables are printed. 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 With
.Fl 1
only the first matching key and note is shown.
.Pp
Without
.Fl N ,
.Fl T .Fl T
only prints only keys in
.Ar key-table . .Ar key-table ,
otherwise all key tables are printed.
.It Xo Ic send-keys .It Xo Ic send-keys
.Op Fl FHlMRX .Op Fl FHlMRX
.Op Fl N Ar repeat-count .Op Fl N Ar repeat-count
@ -4693,7 +4719,7 @@ session option.
Commands related to the status line are as follows: Commands related to the status line are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Xo Ic command-prompt .It Xo Ic command-prompt
.Op Fl 1Ni .Op Fl 1ikN
.Op Fl I Ar inputs .Op Fl I Ar inputs
.Op Fl p Ar prompts .Op Fl p Ar prompts
.Op Fl t Ar target-client .Op Fl t Ar target-client
@ -4743,6 +4769,10 @@ but any quotation marks are escaped.
.Fl 1 .Fl 1
makes the prompt only accept one key press, in this case the resulting input makes the prompt only accept one key press, in this case the resulting input
is a single character. is a single character.
.Fl k
is like
.Fl 1
but the key press is translated to a key name.
.Fl N .Fl N
makes the prompt only accept numeric key presses. makes the prompt only accept numeric key presses.
.Fl i .Fl i

5
tmux.h
View File

@ -1609,6 +1609,7 @@ struct client {
#define PROMPT_NUMERIC 0x2 #define PROMPT_NUMERIC 0x2
#define PROMPT_INCREMENTAL 0x4 #define PROMPT_INCREMENTAL 0x4
#define PROMPT_NOFORMAT 0x8 #define PROMPT_NOFORMAT 0x8
#define PROMPT_KEY 0x10
int prompt_flags; int prompt_flags;
struct session *session; struct session *session;
@ -1636,6 +1637,7 @@ TAILQ_HEAD(clients, client);
struct key_binding { struct key_binding {
key_code key; key_code key;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
const char *note;
int flags; int flags;
#define KEY_BINDING_REPEAT 0x1 #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_get(struct key_table *, key_code);
struct key_binding *key_bindings_first(struct key_table *); struct key_binding *key_bindings_first(struct key_table *);
struct key_binding *key_bindings_next(struct key_table *, struct key_binding *); 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(const char *, key_code);
void key_bindings_remove_table(const char *); void key_bindings_remove_table(const char *);
void key_bindings_init(void); void key_bindings_init(void);