Permit commands to be bound to key presses without the prefix key first. The

new -n flag to bind-key and unbind-key sets or removes these bindings, and
list-key shows them in []s.
This commit is contained in:
Nicholas Marriott 2009-07-24 14:52:47 +00:00
parent ce4eb6559e
commit 5a1a106637
7 changed files with 76 additions and 24 deletions

View File

@ -39,7 +39,7 @@ struct cmd_bind_key_data {
const struct cmd_entry cmd_bind_key_entry = { const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind", "bind-key", "bind",
"[-r] key command [arguments]", "[-nr] key command [arguments]",
0, 0, 0, 0,
NULL, NULL,
cmd_bind_key_parse, cmd_bind_key_parse,
@ -54,14 +54,17 @@ int
cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_bind_key_data *data; struct cmd_bind_key_data *data;
int opt; int opt, no_prefix = 0;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->can_repeat = 0; data->can_repeat = 0;
data->cmdlist = NULL; data->cmdlist = NULL;
while ((opt = getopt(argc, argv, "r")) != -1) { while ((opt = getopt(argc, argv, "nr")) != -1) {
switch (opt) { switch (opt) {
case 'n':
no_prefix = 1;
break;
case 'r': case 'r':
data->can_repeat = 1; data->can_repeat = 1;
break; break;
@ -78,6 +81,8 @@ cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
xasprintf(cause, "unknown key: %s", argv[0]); xasprintf(cause, "unknown key: %s", argv[0]);
goto error; goto error;
} }
if (!no_prefix)
data->key |= KEYC_PREFIX;
argc--; argc--;
argv++; argv++;

View File

@ -46,27 +46,33 @@ cmd_list_keys_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{ {
struct key_binding *bd; struct key_binding *bd;
const char *key; const char *key;
char tmp[BUFSIZ]; char tmp[BUFSIZ], keytmp[64];
int width, keywidth; int width, keywidth;
width = 0; width = 0;
SPLAY_FOREACH(bd, key_bindings, &key_bindings) { SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
if ((key = key_string_lookup_key(bd->key)) == NULL) key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue; continue;
keywidth = strlen(key) + 1; keywidth = strlen(key) + 1;
if (!(bd->key & KEYC_PREFIX))
keywidth += 2;
if (keywidth > width) if (keywidth > width)
width = keywidth; width = keywidth;
} }
SPLAY_FOREACH(bd, key_bindings, &key_bindings) { SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
if ((key = key_string_lookup_key(bd->key)) == NULL) key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue; continue;
*tmp = '\0'; *tmp = '\0';
cmd_list_print(bd->cmdlist, tmp, sizeof tmp); cmd_list_print(bd->cmdlist, tmp, sizeof tmp);
if (!(bd->key & KEYC_PREFIX)) {
xsnprintf(keytmp, sizeof keytmp, "[%s]", key);
key = keytmp;
}
ctx->print(ctx, "%*s: %s", width, key, tmp); ctx->print(ctx, "%*s: %s", width, key, tmp);
} }

View File

@ -36,7 +36,7 @@ struct cmd_unbind_key_data {
const struct cmd_entry cmd_unbind_key_entry = { const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind", "unbind-key", "unbind",
"key", "[-n] key",
0, 0, 0, 0,
NULL, NULL,
cmd_unbind_key_parse, cmd_unbind_key_parse,
@ -51,12 +51,15 @@ int
cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_unbind_key_data *data; struct cmd_unbind_key_data *data;
int opt; int opt, no_prefix = 0;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
while ((opt = getopt(argc, argv, "")) != -1) { while ((opt = getopt(argc, argv, "n")) != -1) {
switch (opt) { switch (opt) {
case 'n':
no_prefix = 1;
break;
default: default:
goto usage; goto usage;
} }
@ -70,6 +73,8 @@ cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
xasprintf(cause, "unknown key: %s", argv[0]); xasprintf(cause, "unknown key: %s", argv[0]);
goto error; goto error;
} }
if (!no_prefix)
data->key |= KEYC_PREFIX;
return (0); return (0);

View File

@ -32,7 +32,18 @@ struct key_bindings dead_key_bindings;
int int
key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2) key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
{ {
return (bd1->key - bd2->key); int key1, key2;
key1 = bd1->key & ~KEYC_PREFIX;
key2 = bd2->key & ~KEYC_PREFIX;
if (key1 != key2)
return (key1 - key2);
if (bd1->key & KEYC_PREFIX && !(bd2->key & KEYC_PREFIX))
return (-1);
if (bd2->key & KEYC_PREFIX && !(bd1->key & KEYC_PREFIX))
return (1);
return (0);
} }
struct key_binding * struct key_binding *
@ -170,7 +181,8 @@ key_bindings_init(void)
cmd->entry->init(cmd, table[i].key); cmd->entry->init(cmd, table[i].key);
TAILQ_INSERT_HEAD(cmdlist, cmd, qentry); TAILQ_INSERT_HEAD(cmdlist, cmd, qentry);
key_bindings_add(table[i].key, table[i].can_repeat, cmdlist); key_bindings_add(
table[i].key | KEYC_PREFIX, table[i].can_repeat, cmdlist);
} }
} }

View File

@ -802,14 +802,19 @@ server_handle_client(struct client *c)
if (!(c->flags & CLIENT_PREFIX)) { if (!(c->flags & CLIENT_PREFIX)) {
if (key == prefix) if (key == prefix)
c->flags |= CLIENT_PREFIX; c->flags |= CLIENT_PREFIX;
else else {
window_pane_key(wp, c, key); /* Try as a non-prefix key binding. */
if ((bd = key_bindings_lookup(key)) == NULL)
window_pane_key(wp, c, key);
else
key_bindings_dispatch(bd, c);
}
continue; continue;
} }
/* Prefix key already pressed. Reset prefix and lookup key. */ /* Prefix key already pressed. Reset prefix and lookup key. */
c->flags &= ~CLIENT_PREFIX; c->flags &= ~CLIENT_PREFIX;
if ((bd = key_bindings_lookup(key)) == NULL) { if ((bd = key_bindings_lookup(key | KEYC_PREFIX)) == NULL) {
/* If repeating, treat this as a key, else ignore. */ /* If repeating, treat this as a key, else ignore. */
if (c->flags & CLIENT_REPEAT) { if (c->flags & CLIENT_REPEAT) {
c->flags &= ~CLIENT_REPEAT; c->flags &= ~CLIENT_REPEAT;

19
tmux.1
View File

@ -617,7 +617,7 @@ If no server is started,
will attempt to start it; this will fail unless sessions are created in the will attempt to start it; this will fail unless sessions are created in the
configuration file. configuration file.
.It Xo Ic bind-key .It Xo Ic bind-key
.Op Fl r .Op Fl nr
.Ar key Ar command Op Ar arguments .Ar key Ar command Op Ar arguments
.Xc .Xc
.D1 (alias: Ic bind ) .D1 (alias: Ic bind )
@ -632,6 +632,13 @@ or
for Ctrl keys, or for Ctrl keys, or
.Ql M- .Ql M-
for Alt (meta) keys. for Alt (meta) keys.
If
.Fl n
is specified, it is not necessary to use the prefix key,
.Ar command
is bound to
.Ar key
alone.
The The
.Fl r .Fl r
flag indicates this key may repeat, see the flag indicates this key may repeat, see the
@ -842,6 +849,10 @@ List the syntax of all commands supported by
.Xc .Xc
.D1 (alias: Ic lsk ) .D1 (alias: Ic lsk )
List all key bindings. List all key bindings.
Keys bound without the prefix key (see
.Ic bind-key
.Fl n )
are enclosed in square brackets.
.It Xo Ic list-sessions .It Xo Ic list-sessions
.Xc .Xc
.D1 (alias: Ic ls ) .D1 (alias: Ic ls )
@ -1613,11 +1624,17 @@ Switch the current session for client
to to
.Ar target-session . .Ar target-session .
.It Xo Ic unbind-key .It Xo Ic unbind-key
.Op Fl n
.Ar key .Ar key
.Xc .Xc
.D1 (alias: Ic unbind ) .D1 (alias: Ic unbind )
Unbind the command bound to Unbind the command bound to
.Ar key . .Ar key .
If
.Fl n
is specified, the command bound to
.Ar key
without a prefix (if any) is removed.
.It Xo Ic unlink-window .It Xo Ic unlink-window
.Op Fl k .Op Fl k
.Op Fl t Ar target-window .Op Fl t Ar target-window

14
tmux.h
View File

@ -102,10 +102,12 @@ struct buffer {
#define BELL_CURRENT 2 #define BELL_CURRENT 2
/* Key codes. ncurses defines KEY_*. Grrr. */ /* Key codes. ncurses defines KEY_*. Grrr. */
#define KEYC_NONE 0x0fff #define KEYC_NONE 0xfff
#define KEYC_ESCAPE 0x2000 /* 0x1000 is base for special keys */
#define KEYC_CTRL 0x4000 #define KEYC_ESCAPE 0x2000
#define KEYC_SHIFT 0x8000 #define KEYC_CTRL 0x4000
#define KEYC_SHIFT 0x8000
#define KEYC_PREFIX 0x10000
enum key_code { enum key_code {
/* Mouse key. */ /* Mouse key. */
@ -856,8 +858,6 @@ struct client_ctx {
/* Key/command line command. */ /* Key/command line command. */
struct cmd_ctx { struct cmd_ctx {
struct client *cmdclient;
/* /*
* curclient is the client where this command was executed if inside * curclient is the client where this command was executed if inside
* tmux. This is NULL if the command came from the command-line. * tmux. This is NULL if the command came from the command-line.
@ -869,6 +869,8 @@ struct cmd_ctx {
* configuration file. * configuration file.
*/ */
struct client *curclient; struct client *curclient;
struct client *cmdclient;
struct session *cursession; struct session *cursession;
struct msg_command_data *msgdata; struct msg_command_data *msgdata;