We don't need a merge request, I'll commit it when I'm happy with it. Thanks


On Sun, Apr 19, 2015 at 06:49:30PM +0000, Ross Hadden wrote:
>    Would you mind making a merge request for it?** I could, but it wouldn't
>    really be right to make a merge request with someone else's hard work!**
>    Your name should be on this.
>    Thanks,
>    ~Ross
>    On Mon, Apr 13, 2015 at 5:30 PM Nicholas Marriott
>    <[1]nicholas.marri...@gmail.com> wrote:
> 
>      Here's the latest diff.
> 
>      It actually seems to work fine, although I haven't done a lot of
>      testing.
> 
>      IIRC I wasn't wild about the cmd-list-keys.c and cmd-bind-key.c changes;
>      certainly lsk -T should error on an unknown table, same as bind -T. I
>      think the manpage bits could do with some improvement too.
> 
>      Index: cmd-bind-key.c
>      ===================================================================
>      RCS file: /cvs/src/usr.bin/tmux/cmd-bind-key.c,v
>      retrieving revision 1.20
>      diff -u -p -r1.20 cmd-bind-key.c
>      --- cmd-bind-key.c** ** ** 10 Apr 2015 16:00:08 -0000** ** ** 1.20
>      +++ cmd-bind-key.c** ** ** 13 Apr 2015 21:29:21 -0000
>      @@ -33,8 +33,8 @@ enum cmd_retval** ** ** ** cmd_bind_key_mode_table
> 
>      **const struct cmd_entry cmd_bind_key_entry = {
>      ** ** ** ** "bind-key", "bind",
>      -** ** ** **"cnrt:", 1, -1,
>      -** ** ** **"[-cnr] [-t mode-table] key command [arguments]",
>      +** ** ** **"cnrt:T:", 1, -1,
>      +** ** ** **"[-cnr] [-t mode-table] [-T key-table] key command
>      [arguments]",
>      ** ** ** ** 0,
>      ** ** ** ** cmd_bind_key_exec
>      **};
>      @@ -46,6 +46,7 @@ cmd_bind_key_exec(struct cmd *self, stru
>      ** ** ** ** char** ** ** ** ** ** *cause;
>      ** ** ** ** struct cmd_list *cmdlist;
>      ** ** ** ** int** ** ** ** ** ** ** key;
>      +** ** ** **const char** ** ** *tablename;
> 
>      ** ** ** ** if (args_has(args, 't')) {
>      ** ** ** ** ** ** ** ** if (args->argc != 2 && args->argc != 3) {
>      @@ -68,6 +69,13 @@ cmd_bind_key_exec(struct cmd *self, stru
>      ** ** ** ** if (args_has(args, 't'))
>      ** ** ** ** ** ** ** ** return (cmd_bind_key_mode_table(self, cmdq,
>      key));
> 
>      +** ** ** **if (args_has(args, 'T'))
>      +** ** ** ** ** ** ** **tablename = args_get(args, 'T');
>      +** ** ** **else if (args_has(args, 'n'))
>      +** ** ** ** ** ** ** **tablename = "root";
>      +** ** ** **else
>      +** ** ** ** ** ** ** **tablename = "prefix";
>      +
>      ** ** ** ** cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1,
>      NULL, 0,
>      ** ** ** ** ** ** &cause);
>      ** ** ** ** if (cmdlist == NULL) {
>      @@ -76,9 +84,7 @@ cmd_bind_key_exec(struct cmd *self, stru
>      ** ** ** ** ** ** ** ** return (CMD_RETURN_ERROR);
>      ** ** ** ** }
> 
>      -** ** ** **if (!args_has(args, 'n'))
>      -** ** ** ** ** **key |= KEYC_PREFIX;
>      -** ** ** **key_bindings_add(key, args_has(args, 'r'), cmdlist);
>      +** ** ** **key_bindings_add(tablename, key, args_has(args, 'r'),
>      cmdlist);
>      ** ** ** ** return (CMD_RETURN_NORMAL);
>      **}
> 
>      Index: cmd-list-keys.c
>      ===================================================================
>      RCS file: /cvs/src/usr.bin/tmux/cmd-list-keys.c,v
>      retrieving revision 1.25
>      diff -u -p -r1.25 cmd-list-keys.c
>      --- cmd-list-keys.c** ** **20 Oct 2014 23:27:14 -0000** ** ** 1.25
>      +++ cmd-list-keys.c** ** **13 Apr 2015 21:29:21 -0000
>      @@ -33,8 +33,8 @@ enum cmd_retval** ** ** ** cmd_list_keys_commands(
> 
>      **const struct cmd_entry cmd_list_keys_entry = {
>      ** ** ** ** "list-keys", "lsk",
>      -** ** ** **"t:", 0, 0,
>      -** ** ** **"[-t key-table]",
>      +** ** ** **"t:T:", 0, 0,
>      +** ** ** **"[-t mode-table] [-T key-table]",
>      ** ** ** ** 0,
>      ** ** ** ** cmd_list_keys_exec
>      **};
>      @@ -51,58 +51,65 @@ enum cmd_retval
>      **cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
>      **{
>      ** ** ** ** struct args** ** ** ** ** ** ***args = self->args;
>      +** ** ** **struct key_table** ** ** ** *table;
>      ** ** ** ** struct key_binding** ** ** *bd;
>      -** ** ** **const char** ** ** ** ** ** ** *key;
>      -** ** ** **char** ** ** ** ** ** ** ** ** ** **tmp[BUFSIZ], flags[8];
>      +** ** ** **const char** ** ** ** ** ** ** *key, *tablename, *r;
>      +** ** ** **char** ** ** ** ** ** ** ** ** ** **tmp[BUFSIZ];
>      ** ** ** ** size_t** ** ** ** ** ** ** ** ** **used;
>      -** ** ** **int** ** ** ** ** ** ** ** ** ** ** width, keywidth;
>      +** ** ** **int** ** ** ** ** ** ** ** ** ** ** repeat, width,
>      tablewidth, keywidth;
> 
>      ** ** ** ** if (self->entry == &cmd_list_commands_entry)
>      ** ** ** ** ** ** ** ** return (cmd_list_keys_commands(self, cmdq));
> 
>      ** ** ** ** if (args_has(args, 't'))
>      ** ** ** ** ** ** ** ** return (cmd_list_keys_table(self, cmdq));
>      +** ** ** **tablename = args_get(args, 'T');
> 
>      -** ** ** **width = 0;
>      -
>      -** ** ** **RB_FOREACH(bd, key_bindings, &key_bindings) {
>      -** ** ** ** ** ** ** **key = key_string_lookup_key(bd->key &
>      ~KEYC_PREFIX);
>      -** ** ** ** ** ** ** **if (key == NULL)
>      +** ** ** **repeat = 0;
>      +** ** ** **tablewidth = keywidth = 0;
>      +** ** ** **RB_FOREACH(table, key_tables, &key_tables) {
>      +** ** ** ** ** ** ** **if (tablename != NULL && strcmp(table->name,
>      tablename) != 0)
>      ** ** ** ** ** ** ** ** ** ** ** ** continue;
>      +** ** ** ** ** ** ** **RB_FOREACH(bd, key_bindings,
>      &(table->key_bindings)) {
>      +** ** ** ** ** ** ** ** ** ** ** **key =
>      key_string_lookup_key(bd->key);
>      +** ** ** ** ** ** ** ** ** ** ** **if (key == NULL)
>      +** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **continue;
> 
>      -** ** ** ** ** ** ** **keywidth = strlen(key);
>      -** ** ** ** ** ** ** **if (!(bd->key & KEYC_PREFIX)) {
>      ** ** ** ** ** ** ** ** ** ** ** ** if (bd->can_repeat)
>      -** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **keywidth += 4;
>      -** ** ** ** ** ** ** ** ** ** ** **else
>      -** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **keywidth += 3;
>      -** ** ** ** ** ** ** **} else if (bd->can_repeat)
>      -** ** ** ** ** ** ** ** ** ** ** **keywidth += 3;
>      -** ** ** ** ** ** ** **if (keywidth > width)
>      -** ** ** ** ** ** ** ** ** ** ** **width = keywidth;
>      +** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **repeat = 1;
>      +
>      +** ** ** ** ** ** ** ** ** ** ** **width = strlen(table->name);
>      +** ** ** ** ** ** ** ** ** ** ** **if (width > tablewidth)
>      +** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **tablewidth =width;
>      +** ** ** ** ** ** ** ** ** ** ** **width = strlen(key);
>      +** ** ** ** ** ** ** ** ** ** ** **if (width > keywidth)
>      +** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **keywidth = width;
>      +** ** ** ** ** ** ** **}
>      ** ** ** ** }
> 
>      -** ** ** **RB_FOREACH(bd, key_bindings, &key_bindings) {
>      -** ** ** ** ** ** ** **key = key_string_lookup_key(bd->key &
>      ~KEYC_PREFIX);
>      -** ** ** ** ** ** ** **if (key == NULL)
>      +** ** ** **RB_FOREACH(table, key_tables, &key_tables) {
>      +** ** ** ** ** ** ** **if (tablename != NULL && strcmp(table->name,
>      tablename) != 0)
>      ** ** ** ** ** ** ** ** ** ** ** ** continue;
>      -
>      -** ** ** ** ** ** ** ***flags = '\0';
>      -** ** ** ** ** ** ** **if (!(bd->key & KEYC_PREFIX)) {
>      -** ** ** ** ** ** ** ** ** ** ** **if (bd->can_repeat)
>      -** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **xsnprintf(flags, sizeof
>      flags, "-rn ");
>      +** ** ** ** ** ** ** **RB_FOREACH(bd, key_bindings,
>      &(table->key_bindings)) {
>      +** ** ** ** ** ** ** ** ** ** ** **key =
>      key_string_lookup_key(bd->key);
>      +** ** ** ** ** ** ** ** ** ** ** **if (key == NULL)
>      +** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **continue;
>      +
>      +** ** ** ** ** ** ** ** ** ** ** **if (!repeat)
>      +** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **r = "";
>      +** ** ** ** ** ** ** ** ** ** ** **else if (bd->can_repeat)
>      +** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **r = "-r ";
>      ** ** ** ** ** ** ** ** ** ** ** ** else
>      -** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **xsnprintf(flags, sizeof
>      flags, "-n ");
>      -** ** ** ** ** ** ** **} else if (bd->can_repeat)
>      -** ** ** ** ** ** ** ** ** ** ** **xsnprintf(flags, sizeof flags, "-r
>      ");
>      -
>      -** ** ** ** ** ** ** **used = xsnprintf(tmp, sizeof tmp, "%s%*s ",
>      -** ** ** ** ** ** ** ** ** **flags, (int) (width - strlen(flags)),
>      key);
>      -** ** ** ** ** ** ** **if (used >= sizeof tmp)
>      -** ** ** ** ** ** ** ** ** ** ** **continue;
>      +** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **r = "** **";
>      +** ** ** ** ** ** ** ** ** ** ** **used = xsnprintf(tmp, sizeof tmp,
>      "%s-T %-*s %-*s ", r,
>      +** ** ** ** ** ** ** ** ** ** ** ** ** **(int)tablewidth, table->name,
>      (int)keywidth, key);
>      +** ** ** ** ** ** ** ** ** ** ** **if (used < sizeof tmp) {
>      +** ** ** ** ** ** ** ** ** ** ** ** ** ** **
>      **cmd_list_print(bd->cmdlist, tmp + used,
>      +** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **(sizeof tmp) -
>      used);
>      +** ** ** ** ** ** ** ** ** ** ** **}
> 
>      -** ** ** ** ** ** ** **cmd_list_print(bd->cmdlist, tmp + used, (sizeof
>      tmp) - used);
>      -** ** ** ** ** ** ** **cmdq_print(cmdq, "bind-key %s", tmp);
>      +** ** ** ** ** ** ** ** ** ** ** **cmdq_print(cmdq, "bind-key %s",
>      tmp);
>      +** ** ** ** ** ** ** **}
>      ** ** ** ** }
> 
>      ** ** ** ** return (CMD_RETURN_NORMAL);
>      Index: cmd-switch-client.c
>      ===================================================================
>      RCS file: /cvs/src/usr.bin/tmux/cmd-switch-client.c,v
>      retrieving revision 1.22
>      diff -u -p -r1.22 cmd-switch-client.c
>      --- cmd-switch-client.c 20 Oct 2014 22:29:25 -0000** ** ** 1.22
>      +++ cmd-switch-client.c 13 Apr 2015 21:29:21 -0000
>      @@ -31,8 +31,8 @@ enum cmd_retval** ** ** ** cmd_switch_client_exec(
> 
>      **const struct cmd_entry cmd_switch_client_entry = {
>      ** ** ** ** "switch-client", "switchc",
>      -** ** ** **"lc:npt:r", 0, 0,
>      -** ** ** **"[-lnpr] [-c target-client] [-t target-session]",
>      +** ** ** **"lc:npt:rT:", 0, 0,
>      +** ** ** **"[-lnpr] [-c target-client] [-t target-session] [-T
>      key-table]",
>      ** ** ** ** CMD_READONLY,
>      ** ** ** ** cmd_switch_client_exec
>      **};
>      @@ -46,7 +46,8 @@ cmd_switch_client_exec(struct cmd *self,
>      ** ** ** ** struct winlink** ** ** ** ** *wl = NULL;
>      ** ** ** ** struct window** ** ** ** ** ***w = NULL;
>      ** ** ** ** struct window_pane** ** ** *wp = NULL;
>      -** ** ** **const char** ** ** ** ** ** ** *tflag;
>      +** ** ** **const char** ** ** ** ** ** ** *tflag, *tablename;
>      +** ** ** **struct key_table** ** ** ** *table;
> 
>      ** ** ** ** if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 0)) ==
>      NULL)
>      ** ** ** ** ** ** ** ** return (CMD_RETURN_ERROR);
>      @@ -56,6 +57,18 @@ cmd_switch_client_exec(struct cmd *self,
>      ** ** ** ** ** ** ** ** ** ** ** ** c->flags &= ~CLIENT_READONLY;
>      ** ** ** ** ** ** ** ** else
>      ** ** ** ** ** ** ** ** ** ** ** ** c->flags |= CLIENT_READONLY;
>      +** ** ** **}
>      +
>      +** ** ** **tablename = args_get(args, 'T');
>      +** ** ** **if (tablename != NULL) {
>      +** ** ** ** ** ** ** **table = key_bindings_get_table(tablename, 0);
>      +** ** ** ** ** ** ** **if (table == NULL) {
>      +** ** ** ** ** ** ** ** ** ** ** **cmdq_error(cmdq, "table %s doesn't
>      exist", tablename);
>      +** ** ** ** ** ** ** ** ** ** ** **return (CMD_RETURN_ERROR);
>      +** ** ** ** ** ** ** **}
>      +** ** ** ** ** ** ** **table->references++;
>      +** ** ** ** ** ** ** **key_bindings_unref_table(c->keytable);
>      +** ** ** ** ** ** ** **c->keytable = table;
>      ** ** ** ** }
> 
>      ** ** ** ** tflag = args_get(args, 't');
>      Index: cmd-unbind-key.c
>      ===================================================================
>      RCS file: /cvs/src/usr.bin/tmux/cmd-unbind-key.c,v
>      retrieving revision 1.20
>      diff -u -p -r1.20 cmd-unbind-key.c
>      --- cmd-unbind-key.c** ** 20 Oct 2014 22:29:25 -0000** ** ** 1.20
>      +++ cmd-unbind-key.c** ** 13 Apr 2015 21:29:21 -0000
>      @@ -31,8 +31,8 @@ enum cmd_retval** ** ** ** cmd_unbind_key_mode_tab
> 
>      **const struct cmd_entry cmd_unbind_key_entry = {
>      ** ** ** ** "unbind-key", "unbind",
>      -** ** ** **"acnt:", 0, 1,
>      -** ** ** **"[-acn] [-t mode-table] key",
>      +** ** ** **"acnt:T:", 0, 1,
>      +** ** ** **"[-acn] [-t mode-table] [-T key-table] key",
>      ** ** ** ** 0,
>      ** ** ** ** cmd_unbind_key_exec
>      **};
>      @@ -40,9 +40,9 @@ const struct cmd_entry cmd_unbind_key_en
>      **enum cmd_retval
>      **cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
>      **{
>      -** ** ** **struct args** ** ** ** ** ** ***args = self->args;
>      -** ** ** **struct key_binding** ** ** *bd;
>      -** ** ** **int** ** ** ** ** ** ** ** ** ** ** key;
>      +** ** ** **struct args** ** ***args = self->args;
>      +** ** ** **int** ** ** ** ** ** ** key;
>      +** ** ** **const char** ** ** *tablename;
> 
>      ** ** ** ** if (!args_has(args, 'a')) {
>      ** ** ** ** ** ** ** ** if (args->argc != 1) {
>      @@ -66,16 +66,23 @@ cmd_unbind_key_exec(struct cmd *self, st
>      ** ** ** ** ** ** ** ** return (cmd_unbind_key_mode_table(self, cmdq,
>      key));
> 
>      ** ** ** ** if (key == KEYC_NONE) {
>      -** ** ** ** ** ** ** **while (!RB_EMPTY(&key_bindings)) {
>      -** ** ** ** ** ** ** ** ** ** ** **bd = RB_ROOT(&key_bindings);
>      -** ** ** ** ** ** ** ** ** ** ** **key_bindings_remove(bd->key);
>      +** ** ** ** ** ** ** **if (args_has(args, 'T')) {
>      +** ** ** ** ** ** ** ** ** ** **
>      **key_bindings_remove_table(args_get(args, 'T'));
>      +** ** ** ** ** ** ** ** ** ** ** **return (CMD_RETURN_NORMAL);
>      ** ** ** ** ** ** ** ** }
>      +** ** ** ** ** ** ** **key_bindings_remove_table("root");
>      +** ** ** ** ** ** ** **key_bindings_remove_table("prefix");
>      ** ** ** ** ** ** ** ** return (CMD_RETURN_NORMAL);
>      ** ** ** ** }
> 
>      -** ** ** **if (!args_has(args, 'n'))
>      -** ** ** ** ** ** ** **key |= KEYC_PREFIX;
>      -** ** ** **key_bindings_remove(key);
>      +** ** ** **if (args_has(args, 'T'))
>      +** ** ** ** ** ** ** **tablename = args_get(args, 'T');
>      +** ** ** **else if (args_has(args, 'n'))
>      +** ** ** ** ** ** ** **tablename = "root";
>      +** ** ** **else
>      +** ** ** ** ** ** ** **tablename = "prefix";
>      +
>      +** ** ** **key_bindings_remove(tablename, key);
>      ** ** ** ** return (CMD_RETURN_NORMAL);
>      **}
> 
>      Index: format.c
>      ===================================================================
>      RCS file: /cvs/src/usr.bin/tmux/format.c,v
>      retrieving revision 1.60
>      diff -u -p -r1.60 format.c
>      --- format.c** ** 31 Mar 2015 17:58:36 -0000** ** ** 1.60
>      +++ format.c** ** 13 Apr 2015 21:29:21 -0000
>      @@ -545,7 +545,11 @@ format_defaults_client(struct format_tre
>      ** ** ** ** format_add(ft, "client_activity", "%lld", (long long) t);
>      ** ** ** ** format_add(ft, "client_activity_string", "%s",
>      format_time_string(t));
> 
>      -** ** ** **format_add(ft, "client_prefix", "%d", !!(c->flags &
>      CLIENT_PREFIX));
>      +** ** ** **if (strcmp(c->keytable->name, "root") == 0)
>      +** ** ** ** ** ** ** **format_add(ft, "client_prefix", "%d", 0);
>      +** ** ** **else
>      +** ** ** ** ** ** ** **format_add(ft, "client_prefix", "%d", 1);
>      +** ** ** **format_add(ft, "client_key_table", "%s", c->keytable->name);
> 
>      ** ** ** ** if (c->tty.flags & TTY_UTF8)
>      ** ** ** ** ** ** ** ** format_add(ft, "client_utf8", "%d", 1);
>      Index: key-bindings.c
>      ===================================================================
>      RCS file: /cvs/src/usr.bin/tmux/key-bindings.c,v
>      retrieving revision 1.43
>      diff -u -p -r1.43 key-bindings.c
>      --- key-bindings.c** ** ** 22 Oct 2014 23:18:53 -0000** ** ** 1.43
>      +++ key-bindings.c** ** ** 13 Apr 2015 21:29:21 -0000
>      @@ -25,60 +25,121 @@
>      **#include "tmux.h"
> 
>      **RB_GENERATE(key_bindings, key_binding, entry, key_bindings_cmp);
>      +RB_GENERATE(key_tables, key_table, entry, key_table_cmp);
>      +struct key_tables key_tables = RB_INITIALIZER(&key_tables);
> 
>      -struct key_bindings** ** key_bindings;
>      +int
>      +key_table_cmp(struct key_table *e1, struct key_table *e2)
>      +{
>      +** ** ** **return (strcmp(e1->name, e2->name));
>      +}
> 
>      **int
>      **key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
>      **{
>      -** ** ** **int** ** **key1, key2;
>      +** ** ** **return (bd1->key - bd2->key);
>      +}
>      +
>      +struct key_table *
>      +key_bindings_get_table(const char *name, int create)
>      +{
>      +** ** ** **struct key_table** ** ** ** table_search, *table;
>      +
>      +** ** ** **[2]table_search.name = name;
>      +** ** ** **table = RB_FIND(key_tables, &key_tables, &table_search);
>      +** ** ** **if (table != NULL || !create)
>      +** ** ** ** ** ** ** **return (table);
> 
>      -** ** ** **key1 = bd1->key & ~KEYC_PREFIX;
>      -** ** ** **key2 = bd2->key & ~KEYC_PREFIX;
>      -** ** ** **if (key1 != key2)
>      -** ** ** ** ** ** ** **return (key1 - key2);
>      +** ** ** **table = xmalloc(sizeof *table);
>      +** ** ** **table->name = xstrdup(name);
>      +** ** ** **RB_INIT(&table->key_bindings);
> 
>      -** ** ** **if (bd1->key & KEYC_PREFIX && !(bd2->key & KEYC_PREFIX))
>      -** ** ** ** ** ** ** **return (-1);
>      -** ** ** **if (bd2->key & KEYC_PREFIX && !(bd1->key & KEYC_PREFIX))
>      -** ** ** ** ** ** ** **return (1);
>      -** ** ** **return (0);
>      +** ** ** **table->references = 1; /* one reference in key_tables */
>      +** ** ** **RB_INSERT(key_tables, &key_tables, table);
>      +
>      +** ** ** **return (table);
>      **}
> 
>      -struct key_binding *
>      -key_bindings_lookup(int key)
>      +void
>      +key_bindings_unref_table(struct key_table *table)
>      **{
>      -** ** ** **struct key_binding** ** ** bd;
>      +** ** ** **struct key_binding** ** ** *bd;
> 
>      -** ** ** **bd.key = key;
>      -** ** ** **return (RB_FIND(key_bindings, &key_bindings, &bd));
>      +** ** ** **if (--table->references != 0)
>      +** ** ** ** ** ** ** **return;
>      +
>      +** ** ** **while (!RB_EMPTY(&table->key_bindings)) {
>      +** ** ** ** ** ** ** **bd = RB_ROOT(&table->key_bindings);
>      +** ** ** ** ** ** ** **RB_REMOVE(key_bindings, &table->key_bindings,
>      bd);
>      +** ** ** ** ** ** ** **cmd_list_free(bd->cmdlist);
>      +** ** ** ** ** ** ** **free(bd);
>      +** ** ** **}
>      +
>      +** ** ** **free((void *)table->name);
>      +** ** ** **free(table);
>      **}
> 
>      **void
>      -key_bindings_add(int key, int can_repeat, struct cmd_list *cmdlist)
>      +key_bindings_add(const char *name, int key, int can_repeat,
>      +** ** struct cmd_list *cmdlist)
>      **{
>      -** ** ** **struct key_binding** ** ** *bd;
>      +** ** ** **struct key_table** ** ** ** *table;
>      +** ** ** **struct key_binding** ** ** **bd_search, *bd;
> 
>      -** ** ** **key_bindings_remove(key);
>      +** ** ** **table = key_bindings_get_table(name, 1);
>      +
>      +** ** ** **bd_search.key = key;
>      +** ** ** **bd = RB_FIND(key_bindings, &table->key_bindings,
>      &bd_search);
>      +** ** ** **if (bd != NULL) {
>      +** ** ** ** ** ** ** **RB_REMOVE(key_bindings, &table->key_bindings,
>      bd);
>      +** ** ** ** ** ** ** **cmd_list_free(bd->cmdlist);
>      +** ** ** ** ** ** ** **free(bd);
>      +** ** ** **}
> 
>      ** ** ** ** bd = xmalloc(sizeof *bd);
>      ** ** ** ** bd->key = key;
>      -** ** ** **RB_INSERT(key_bindings, &key_bindings, bd);
>      +** ** ** **RB_INSERT(key_bindings, &table->key_bindings, bd);
> 
>      ** ** ** ** bd->can_repeat = can_repeat;
>      ** ** ** ** bd->cmdlist = cmdlist;
>      **}
> 
>      **void
>      -key_bindings_remove(int key)
>      +key_bindings_remove(const char *name, int key)
>      **{
>      -** ** ** **struct key_binding** ** ** *bd;
>      +** ** ** **struct key_table** ** ** ** *table;
>      +** ** ** **struct key_binding** ** ** **bd_search, *bd;
>      +
>      +** ** ** **table = key_bindings_get_table(name, 0);
>      +** ** ** **if (table == NULL)
>      +** ** ** ** ** ** ** **return;
> 
>      -** ** ** **if ((bd = key_bindings_lookup(key)) == NULL)
>      +** ** ** **bd_search.key = key;
>      +** ** ** **bd = RB_FIND(key_bindings, &table->key_bindings,
>      &bd_search);
>      +** ** ** **if (bd == NULL)
>      ** ** ** ** ** ** ** ** return;
>      -** ** ** **RB_REMOVE(key_bindings, &key_bindings, bd);
>      +
>      +** ** ** **RB_REMOVE(key_bindings, &table->key_bindings, bd);
>      ** ** ** ** cmd_list_free(bd->cmdlist);
>      ** ** ** ** free(bd);
>      +
>      +** ** ** **if (RB_EMPTY(&table->key_bindings)) {
>      +** ** ** ** ** ** ** **RB_REMOVE(key_tables, &key_tables, table);
>      +** ** ** ** ** ** ** **key_bindings_unref_table(table);
>      +** ** ** **}
>      +}
>      +
>      +void
>      +key_bindings_remove_table(const char *name)
>      +{
>      +** ** ** **struct key_table** ** ** ** *table;
>      +
>      +** ** ** **table = key_bindings_get_table(name, 0);
>      +** ** ** **if (table == NULL)
>      +** ** ** ** ** ** ** **return;
>      +
>      +** ** ** **RB_REMOVE(key_tables, &key_tables, table);
>      +** ** ** **key_bindings_unref_table(table);
>      **}
> 
>      **void
>      @@ -164,8 +225,6 @@ key_bindings_init(void)
>      ** ** ** ** char*** ** ** ** ** ** cause;
>      ** ** ** ** int** ** ** ** ** ** ** error;
>      ** ** ** ** struct cmd_q** ** *cmdq;
>      -
>      -** ** ** **RB_INIT(&key_bindings);
> 
>      ** ** ** ** cmdq = cmdq_new(NULL);
>      ** ** ** ** for (i = 0; i < nitems(defaults); i++) {
>      Index: server-client.c
>      ===================================================================
>      RCS file: /cvs/src/usr.bin/tmux/server-client.c,v
>      retrieving revision 1.129
>      diff -u -p -r1.129 server-client.c
>      --- server-client.c** ** **31 Mar 2015 17:45:10 -0000** ** ** 1.129
>      +++ server-client.c** ** **13 Apr 2015 21:29:21 -0000
>      @@ -100,6 +100,9 @@ server_client_create(int fd)
> 
>      ** ** ** ** c->flags |= CLIENT_FOCUSED;
> 
>      +** ** ** **c->keytable = key_bindings_get_table("root", 1);
>      +** ** ** **c->keytable->references++;
>      +
>      ** ** ** ** evtimer_set(&c->repeat_timer, server_client_repeat_timer,
>      c);
> 
>      ** ** ** ** for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
>      @@ -171,6 +174,8 @@ server_client_lost(struct client *c)
> 
>      ** ** ** ** evtimer_del(&c->repeat_timer);
> 
>      +** ** ** **key_bindings_unref_table(c->keytable);
>      +
>      ** ** ** ** if (event_initialized(&c->identify_timer))
>      ** ** ** ** ** ** ** ** evtimer_del(&c->identify_timer);
> 
>      @@ -362,33 +367,28 @@ server_client_assume_paste(struct sessio
>      **void
>      **server_client_handle_key(struct client *c, int key)
>      **{
>      -** ** ** **struct session** ** ** ** ** *s;
>      +** ** ** **struct session** ** ** ** ** *s = c->session;
>      ** ** ** ** struct window** ** ** ** ** ***w;
>      ** ** ** ** struct window_pane** ** ** *wp;
>      ** ** ** ** struct timeval** ** ** ** ** **tv;
>      -** ** ** **struct key_binding** ** ** *bd;
>      -** ** ** **int** ** ** ** ** ** ** ** ** ** ** xtimeout, isprefix,
>      ispaste;
>      +** ** ** **struct key_table** ** ** ** *table = c->keytable;
>      +** ** ** **struct key_binding** ** ** **bd_search, *bd;
>      +** ** ** **int** ** ** ** ** ** ** ** ** ** ** xtimeout;
> 
>      ** ** ** ** /* Check the client is good to accept input. */
>      -** ** ** **if ((c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
>      -** ** ** ** ** ** ** **return;
>      -
>      -** ** ** **if (c->session == NULL)
>      +** ** ** **if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED))
>      != 0)
>      ** ** ** ** ** ** ** ** return;
>      -** ** ** **s = c->session;
>      +** ** ** **w = c->session->curw->window;
>      +** ** ** **wp = w->active;
> 
>      ** ** ** ** /* Update the activity timer. */
>      ** ** ** ** if (gettimeofday(&c->activity_time, NULL) != 0)
>      ** ** ** ** ** ** ** ** fatal("gettimeofday failed");
>      -
>      ** ** ** ** memcpy(&s->last_activity_time, &s->activity_time,
>      ** ** ** ** ** ** sizeof s->last_activity_time);
>      ** ** ** ** memcpy(&s->activity_time, &c->activity_time, sizeof
>      s->activity_time);
> 
>      -** ** ** **w = c->session->curw->window;
>      -** ** ** **wp = w->active;
>      -
>      -** ** ** **/* Special case: number keys jump to pane in identify mode.
>      */
>      +** ** ** **/* Number keys jump to pane in identify mode. */
>      ** ** ** ** if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9')
>      {
>      ** ** ** ** ** ** ** ** if (c->flags & CLIENT_READONLY)
>      ** ** ** ** ** ** ** ** ** ** ** ** return;
>      @@ -419,74 +419,89 @@ server_client_handle_key(struct client *
>      ** ** ** ** ** ** ** ** return;
>      ** ** ** ** }
> 
>      -** ** ** **/* Is this a prefix key? */
>      -** ** ** **if (key == options_get_number(&s->options, "prefix"))
>      -** ** ** ** ** ** ** **isprefix = 1;
>      -** ** ** **else if (key == options_get_number(&s->options, "prefix2"))
>      -** ** ** ** ** ** ** **isprefix = 1;
>      -** ** ** **else
>      -** ** ** ** ** ** ** **isprefix = 0;
>      +** ** ** **/* Treat everything as a regular key when pasting is
>      detected. */
>      +** ** ** **if (server_client_assume_paste(s)) {
>      +** ** ** ** ** ** ** **if (!(c->flags & CLIENT_READONLY))
>      +** ** ** ** ** ** ** ** ** ** ** **window_pane_key(wp, s, key);
>      +** ** ** ** ** ** ** **return;
>      +** ** ** **}
> 
>      -** ** ** **/* Treat prefix as a regular key when pasting is detected.
>      */
>      -** ** ** **ispaste = server_client_assume_paste(s);
>      -** ** ** **if (ispaste)
>      -** ** ** ** ** ** ** **isprefix = 0;
>      -
>      -** ** ** **/* No previous prefix key. */
>      -** ** ** **if (!(c->flags & CLIENT_PREFIX)) {
>      -** ** ** ** ** ** ** **if (isprefix) {
>      -** ** ** ** ** ** ** ** ** ** ** **c->flags |= CLIENT_PREFIX;
>      +retry:
>      +** ** ** **/* Try to see if there is a key binding in the current
>      table. */
>      +** ** ** **bd_search.key = key;
>      +** ** ** **bd = RB_FIND(key_bindings, &table->key_bindings,
>      &bd_search);
>      +** ** ** **if (bd != NULL) {
>      +** ** ** ** ** ** ** **/*
>      +** ** ** ** ** ** ** ** * Key was matched in this table. If currently
>      repeating but
>      +** ** ** ** ** ** ** ** * a non-repeating binding was found, stop
>      repeating and try
>      +** ** ** ** ** ** ** ** * again in the root table.
>      +** ** ** ** ** ** ** ** */
>      +** ** ** ** ** ** ** **if ((c->flags & CLIENT_REPEAT) &&
>      !bd->can_repeat) {
>      +** ** ** ** ** ** ** ** ** ** ** **server_set_key_table(c, "root");
>      +** ** ** ** ** ** ** ** ** ** ** **c->flags &= ~CLIENT_REPEAT;
>      ** ** ** ** ** ** ** ** ** ** ** ** server_status_client(c);
>      -** ** ** ** ** ** ** ** ** ** ** **return;
>      +** ** ** ** ** ** ** ** ** ** ** **goto retry;
>      ** ** ** ** ** ** ** ** }
> 
>      -** ** ** ** ** ** ** **/* Try as a non-prefix key binding. */
>      -** ** ** ** ** ** ** **if (ispaste || (bd = key_bindings_lookup(key))
>      == NULL) {
>      -** ** ** ** ** ** ** ** ** ** ** **if (!(c->flags & CLIENT_READONLY))
>      -** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **window_pane_key(wp, s,
>      key);
>      -** ** ** ** ** ** ** **} else
>      -** ** ** ** ** ** ** ** ** ** ** **key_bindings_dispatch(bd, c);
>      -** ** ** ** ** ** ** **return;
>      -** ** ** **}
>      -
>      -** ** ** **/* Prefix key already pressed. Reset prefix and lookup key.
>      */
>      -** ** ** **c->flags &= ~CLIENT_PREFIX;
>      -** ** ** **server_status_client(c);
>      -** ** ** **if ((bd = key_bindings_lookup(key | KEYC_PREFIX)) == NULL) {
>      -** ** ** ** ** ** ** **/* If repeating, treat this as a key, else
>      ignore. */
>      -** ** ** ** ** ** ** **if (c->flags & CLIENT_REPEAT) {
>      +** ** ** ** ** ** ** **/*
>      +** ** ** ** ** ** ** ** * Take a reference to this table to make sure
>      the key binding
>      +** ** ** ** ** ** ** ** * doesn't disappear.
>      +** ** ** ** ** ** ** ** */
>      +** ** ** ** ** ** ** **table->references++;
>      +
>      +** ** ** ** ** ** ** **/*
>      +** ** ** ** ** ** ** ** * If this is a repeating key, start the timer.
>      Otherwise reset
>      +** ** ** ** ** ** ** ** * the client back to the root table.
>      +** ** ** ** ** ** ** ** */
>      +** ** ** ** ** ** ** **xtimeout = options_get_number(&s->options,
>      "repeat-time");
>      +** ** ** ** ** ** ** **if (xtimeout != 0 && bd->can_repeat) {
>      +** ** ** ** ** ** ** ** ** ** ** **c->flags |= CLIENT_REPEAT;
>      +
>      +** ** ** ** ** ** ** ** ** ** ** **tv.tv_sec = xtimeout / 1000;
>      +** ** ** ** ** ** ** ** ** ** ** **tv.tv_usec = (xtimeout % 1000) *
>      1000L;
>      +** ** ** ** ** ** ** ** ** ** ** **evtimer_del(&c->repeat_timer);
>      +** ** ** ** ** ** ** ** ** ** ** **evtimer_add(&c->repeat_timer, &tv);
>      +** ** ** ** ** ** ** **} else {
>      ** ** ** ** ** ** ** ** ** ** ** ** c->flags &= ~CLIENT_REPEAT;
>      -** ** ** ** ** ** ** ** ** ** ** **if (isprefix)
>      -** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **c->flags |=
>      CLIENT_PREFIX;
>      -** ** ** ** ** ** ** ** ** ** ** **else if (!(c->flags &
>      CLIENT_READONLY))
>      -** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **window_pane_key(wp, s,
>      key);
>      +** ** ** ** ** ** ** ** ** ** ** **server_set_key_table(c, "root");
>      ** ** ** ** ** ** ** ** }
>      +** ** ** ** ** ** ** **server_status_client(c);
>      +
>      +** ** ** ** ** ** ** **/* Dispatch the key binding. */
>      +** ** ** ** ** ** ** **key_bindings_dispatch(bd, c);
>      +** ** ** ** ** ** ** **key_bindings_unref_table(table);
>      +
>      ** ** ** ** ** ** ** ** return;
>      ** ** ** ** }
> 
>      -** ** ** **/* If already repeating, but this key can't repeat, skip it.
>      */
>      -** ** ** **if (c->flags & CLIENT_REPEAT && !bd->can_repeat) {
>      +** ** ** **/*
>      +** ** ** ** * No match in this table. If repeating, switch the client
>      back to the
>      +** ** ** ** * root table and try again.
>      +** ** ** ** */
>      +** ** ** **if (c->flags & CLIENT_REPEAT) {
>      +** ** ** ** ** ** ** **server_set_key_table(c, "root");
>      ** ** ** ** ** ** ** ** c->flags &= ~CLIENT_REPEAT;
>      -** ** ** ** ** ** ** **if (isprefix)
>      -** ** ** ** ** ** ** ** ** ** ** **c->flags |= CLIENT_PREFIX;
>      -** ** ** ** ** ** ** **else if (!(c->flags & CLIENT_READONLY))
>      -** ** ** ** ** ** ** ** ** ** ** **window_pane_key(wp, s, key);
>      -** ** ** ** ** ** ** **return;
>      +** ** ** ** ** ** ** **server_status_client(c);
>      +** ** ** ** ** ** ** **goto retry;
>      ** ** ** ** }
> 
>      -** ** ** **/* If this key can repeat, reset the repeat flags and timer.
>      */
>      -** ** ** **xtimeout = options_get_number(&s->options, "repeat-time");
>      -** ** ** **if (xtimeout != 0 && bd->can_repeat) {
>      -** ** ** ** ** ** ** **c->flags |= CLIENT_PREFIX|CLIENT_REPEAT;
>      -
>      -** ** ** ** ** ** ** **tv.tv_sec = xtimeout / 1000;
>      -** ** ** ** ** ** ** **tv.tv_usec = (xtimeout % 1000) * 1000L;
>      -** ** ** ** ** ** ** **evtimer_del(&c->repeat_timer);
>      -** ** ** ** ** ** ** **evtimer_add(&c->repeat_timer, &tv);
>      +** ** ** **/* If no match and we're not in the root table, that's it.
>      */
>      +** ** ** **if (strcmp(c->keytable->name, "root") != 0) {
>      +** ** ** ** ** ** ** **server_set_key_table(c, "root");
>      +** ** ** ** ** ** ** **server_status_client(c);
>      +** ** ** ** ** ** ** **return;
>      ** ** ** ** }
> 
>      -** ** ** **/* Dispatch the command. */
>      -** ** ** **key_bindings_dispatch(bd, c);
>      +** ** ** **/*
>      +** ** ** ** * No match, but in the root table. Prefix switches to the
>      prefix table
>      +** ** ** ** * and everything else is passed through.
>      +** ** ** ** */
>      +** ** ** **if (key == options_get_number(&s->options, "prefix") ||
>      +** ** ** ** ** **key == options_get_number(&s->options, "prefix2")) {
>      +** ** ** ** ** ** ** **server_set_key_table(c, "prefix");
>      +** ** ** ** ** ** ** **server_status_client(c);
>      +** ** ** **} else if (!(c->flags & CLIENT_READONLY))
>      +** ** ** ** ** ** ** **window_pane_key(wp, s, key);
>      **}
> 
>      **/* Client functions that need to happen every loop. */
>      @@ -692,9 +707,9 @@ server_client_repeat_timer(unused int fd
>      ** ** ** ** struct client** ***c = data;
> 
>      ** ** ** ** if (c->flags & CLIENT_REPEAT) {
>      -** ** ** ** ** ** ** **if (c->flags & CLIENT_PREFIX)
>      -** ** ** ** ** ** ** ** ** ** ** **server_status_client(c);
>      -** ** ** ** ** ** ** **c->flags &= ~(CLIENT_PREFIX|CLIENT_REPEAT);
>      +** ** ** ** ** ** ** **server_set_key_table(c, "root");
>      +** ** ** ** ** ** ** **c->flags &= ~CLIENT_REPEAT;
>      +** ** ** ** ** ** ** **server_status_client(c);
>      ** ** ** ** }
>      **}
> 
>      Index: server-fn.c
>      ===================================================================
>      RCS file: /cvs/src/usr.bin/tmux/server-fn.c,v
>      retrieving revision 1.79
>      diff -u -p -r1.79 server-fn.c
>      --- server-fn.c 31 Mar 2015 17:45:10 -0000** ** ** 1.79
>      +++ server-fn.c 13 Apr 2015 21:29:22 -0000
>      @@ -101,6 +101,14 @@ server_status_client(struct client *c)
>      **}
> 
>      **void
>      +server_set_key_table(struct client *c, const char *name)
>      +{
>      +** ** ** **key_bindings_unref_table(c->keytable);
>      +** ** ** **c->keytable = key_bindings_get_table(name, 1);
>      +** ** ** **c->keytable->references++;
>      +}
>      +
>      +void
>      **server_redraw_session(struct session *s)
>      **{
>      ** ** ** ** struct client** ***c;
>      Index: tmux.1
>      ===================================================================
>      RCS file: /cvs/src/usr.bin/tmux/tmux.1,v
>      retrieving revision 1.417
>      diff -u -p -r1.417 tmux.1
>      --- tmux.1** ** ** 10 Apr 2015 16:00:08 -0000** ** ** 1.417
>      +++ tmux.1** ** ** 13 Apr 2015 21:29:23 -0000
>      @@ -838,6 +838,7 @@ Suspend a client by sending
>      **.Op Fl lnpr
>      **.Op Fl c Ar target-client
>      **.Op Fl t Ar target-session
>      +.Op Fl T Ar key-table
>      **.Xc
>      **.D1 (alias: Ic switchc )
>      **Switch the current session for client
>      @@ -855,6 +856,9 @@ respectively.
>      **toggles whether a client is read-only (see the
>      **.Ic attach-session
>      **command).
>      +.Fl T
>      +sets the client's key table; the next key from the client will be
>      interpreted from
>      +.Ar key-table .
>      **.El
>      **.Sh WINDOWS AND PANES
>      **A
>      @@ -1905,6 +1909,7 @@ Commands related to key bindings are as
>      **.It Xo Ic bind-key
>      **.Op Fl cnr
>      **.Op Fl t Ar mode-table
>      +.Op Fl T Ar key-table
>      **.Ar key Ar command Op Ar arguments
>      **.Xc
>      **.D1 (alias: Ic bind )
>      @@ -1940,18 +1945,41 @@ or for normal mode without.
>      **To view the default bindings and possible commands, see the
>      **.Ic list-keys
>      **command.
>      -.It Ic list-keys Op Fl t Ar key-table
>      +.Pp
>      +If
>      +.Fl T
>      +is present,
>      +.Ar key
>      +is bound in
>      +.Ar key-table :
>      +.Em prefix
>      +corresponds to the default,
>      +.Em root
>      +corresponds to
>      +.Fl n ,
>      +and custom values may be used with
>      +.Ic switch-client
>      +.Fl T .
>      +.It Xo Ic list-keys
>      +.Op Fl t Ar mode-table
>      +.Op Fl T Ar key-table
>      +.Xc
>      **.D1 (alias: Ic lsk )
>      **List all key bindings.
>      **Without
>      **.Fl t
>      -the primary key bindings - those executed when preceded by the prefix
>      key -
>      -are printed.
>      +or
>      +.Fl T
>      +all key tables are printed.
>      +With
>      +.Fl T
>      +only
>      +.Ar key-table .
>      **.Pp
>      **With
>      **.Fl t ,
>      **the key bindings in
>      -.Ar key-table
>      +.Ar mode-table
>      **are listed; this may be one of:
>      **.Em vi-edit ,
>      **.Em emacs-edit ,
>      @@ -1992,6 +2020,7 @@ the secondary prefix key, to a window as
>      **.It Xo Ic unbind-key
>      **.Op Fl acn
>      **.Op Fl t Ar mode-table
>      +.Op Fl T Ar key-table
>      **.Ar key
>      **.Xc
>      **.D1 (alias: Ic unbind )
>      @@ -2017,6 +2046,22 @@ in
>      **is unbound: the binding for command mode with
>      **.Fl c
>      **or for normal mode without.
>      +.Pp
>      +If
>      +.Fl T
>      +is present,
>      +.Ar key
>      +in
>      +.Ar key-table
>      +is unbound:
>      +.Em prefix
>      +corresponds to the default,
>      +.Em root
>      +corresponds to
>      +.Fl n ,
>      +and custom values may be used with
>      +.Ic switch-client
>      +.Fl T .
>      **.El
>      **.Sh OPTIONS
>      **The appearance and behaviour of
>      Index: tmux.h
>      ===================================================================
>      RCS file: /cvs/src/usr.bin/tmux/tmux.h,v
>      retrieving revision 1.490
>      diff -u -p -r1.490 tmux.h
>      --- tmux.h** ** ** 6 Feb 2015 17:21:08 -0000** ** ** **1.490
>      +++ tmux.h** ** ** 13 Apr 2015 21:29:23 -0000
>      @@ -89,10 +89,9 @@ extern char** ****environ;
>      **#define KEYC_ESCAPE 0x2000
>      **#define KEYC_CTRL 0x4000
>      **#define KEYC_SHIFT 0x8000
>      -#define KEYC_PREFIX 0x10000
> 
>      **/* Mask to obtain key w/o modifiers. */
>      -#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT|KEYC_PREFIX)
>      +#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT)
>      **#define KEYC_MASK_KEY (~KEYC_MASK_MOD)
> 
>      **/* Other key codes. */
>      @@ -1287,7 +1286,7 @@ struct client {
>      ** ** ** ** struct screen** ** status;
> 
>      **#define CLIENT_TERMINAL 0x1
>      -#define CLIENT_PREFIX 0x2
>      +/* 0x2 unused */
>      **#define CLIENT_EXIT 0x4
>      **#define CLIENT_REDRAW 0x8
>      **#define CLIENT_STATUS 0x10
>      @@ -1306,6 +1305,7 @@ struct client {
>      **#define CLIENT_256COLOURS 0x20000
>      **#define CLIENT_IDENTIFIED 0x40000
>      ** ** ** ** int** ** ** ** ** ** ** flags;
>      +** ** ** **struct key_table *keytable;
> 
>      ** ** ** ** struct event** ** **identify_timer;
> 
>      @@ -1423,15 +1423,24 @@ struct cmd_entry {
>      ** ** ** ** enum cmd_retval** (*exec)(struct cmd *, struct cmd_q *);
>      **};
> 
>      -/* Key binding. */
>      +/* Key binding and key table. */
>      **struct key_binding {
>      -** ** ** **int** ** ** ** ** ** ** key;
>      -** ** ** **struct cmd_list *cmdlist;
>      -** ** ** **int** ** ** ** ** ** ** can_repeat;
>      +** ** ** **int** ** ** ** ** ** ** ** ** ** ** key;
>      +** ** ** **struct cmd_list** ** ** ** ***cmdlist;
>      +** ** ** **int** ** ** ** ** ** ** ** ** ** ** can_repeat;
> 
>      -** ** ** **RB_ENTRY(key_binding) entry;
>      +** ** ** **RB_ENTRY(key_binding)** ** entry;
>      **};
>      **RB_HEAD(key_bindings, key_binding);
>      +struct key_table {
>      +** ** ** **const char** ** ** ** ** ** ** ***name;
>      +** ** ** **struct key_bindings** ** ** key_bindings;
>      +
>      +** ** ** **u_int** ** ** ** ** ** ** ** ** ** references;
>      +
>      +** ** ** **RB_ENTRY(key_table)** ** ** entry;
>      +};
>      +RB_HEAD(key_tables, key_table);
> 
>      **/*
>      ** * Option table entries. The option table is the user-visible part of
>      the
>      @@ -1848,12 +1857,16 @@ void** ** cmd_wait_for_flush(void);
>      **int** ** client_main(int, char **, int);
> 
>      **/* key-bindings.c */
>      -extern struct key_bindings key_bindings;
>      -int** ** **key_bindings_cmp(struct key_binding *, struct key_binding
>      *);
>      **RB_PROTOTYPE(key_bindings, key_binding, entry, key_bindings_cmp);
>      -struct key_binding *key_bindings_lookup(int);
>      -void** ** key_bindings_add(int, int, struct cmd_list *);
>      -void** ** key_bindings_remove(int);
>      +RB_PROTOTYPE(key_tables, key_table, entry, key_table_cmp);
>      +extern struct key_tables key_tables;
>      +int** ** **key_table_cmp(struct key_table *, struct key_table *);
>      +int** ** **key_bindings_cmp(struct key_binding *, struct key_binding
>      *);
>      +struct** ** ** ** ** key_table *key_bindings_get_table(const char *,
>      int);
>      +void** ** key_bindings_unref_table(struct key_table *);
>      +void** ** key_bindings_add(const char *, int, int, struct cmd_list *);
>      +void** ** key_bindings_remove(const char *, int);
>      +void** ** key_bindings_remove_table(const char *);
>      **void** ** key_bindings_init(void);
>      **void** ** key_bindings_dispatch(struct key_binding *, struct client
>      *);
> 
>      @@ -1889,6 +1902,7 @@ void** ** ** **server_write_session(struct sessio
>      ** ** ** ** ** ** **size_t);
>      **void** ** server_redraw_client(struct client *);
>      **void** ** server_status_client(struct client *);
>      +void** ** server_set_key_table(struct client *, const char *);
>      **void** ** server_redraw_session(struct session *);
>      **void** ** server_redraw_session_group(struct session *);
>      **void** ** server_status_session(struct session *);
> 
>      On Mon, Apr 13, 2015 at 03:21:52PM +0000, Ross Hadden wrote:
>      > Keith Amling <amling <at> [3]palantir.com> writes:
>      >
>      > >
>      > > > > > Or are you thinking of creating the table after running the
>      set
>      > command?
>      > > > > > This shouldn't work - you shouldn't be able to set a client to
>      a
>      > > > > > nonexistent table.
>      > > > >
>      > > > > I guess I don't super care what happens since I won't personally
>      be
>      > > > > writing any switch-client -T into an empty table but I had
>      assumed we
>      > > > > would allow switching to a new [and ephemeral] table since
>      otherwise
>      > > > > switch-client -T can fail which just seems weird to me.
>      > > >
>      > > > I'd say it should fail if the table doesn't exist.
>      > > >
>      > > > I can't think of a case where I would want it to automatically
>      create a
>      > > > table, except to confuse people who make a typo in the table name.
>      Do
>      > > > you have a use in mind?
>      > >
>      > > Not specifically, I just prefer to see tools degrade what might be
>      > > described as "uniformly" where possible.** Nonuniform behaviour
>      makes
>      > > tools dangerous for automated use because when writing a script
>      you're
>      > > unlikely to think of things like "what if this table is empty" or
>      "what
>      > > if this command barfs on no args when really no args means I just
>      didn't
>      > > need it to do anything".
>      > >
>      > > I'll switch it and the next set of patches will be up shortly.
>      > >
>      > > Keith
>      > >
>      > >
>      
> --------------------------------------------------------------------------
>      > ----
>      > > "Accelerate Dev Cycles with Automated Cross-Browser Testing - For
>      FREE
>      > > Instantly run your Selenium tests across 300+ browser/OS combos.
>      > > Get unparalleled scalability from the best Selenium testing platform
>      > available
>      > > Simple to use. Nothing to install. Get started now for free."
>      > > [4]http://p.sf.net/sfu/SauceLabs
>      > >
>      >
>      >
>      > Has work on this continued?** I made an issue about it
>      > ([5]https://sourceforge.net/p/tmux/tickets/172/) in an effort to bring
>      > attention to this patch, but Thomas said it's pretty much not going
>      anywhere
>      > unless the original patch author continues or makes an effort to get
>      it
>      > merged himself.
>      >
>      > I would love to see this landed in tmux!** My current workaround can
>      be seen
>      > at
>      
> [6]https://github.com/rosshadden/dotfiles/blob/master/src/.tmux.conf#L79-L85
>      > and
>      [7]https://github.com/rosshadden/dotfiles/blob/master/src/lib/tmux-
>      > cords.sh.
>      >
>      >
>      >
>      
> ------------------------------------------------------------------------------
>      > BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
>      > Develop your own process in accordance with the BPMN 2 standard
>      > Learn Process modeling best practices with Bonita BPM through live
>      exercises
>      > [8]http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual-
>      event?utm_
>      > source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
>      > _______________________________________________
>      > tmux-users mailing list
>      > [9]tmux-users@lists.sourceforge.net
>      > [10]https://lists.sourceforge.net/lists/listinfo/tmux-users
> 
> References
> 
>    Visible links
>    1. mailto:nicholas.marri...@gmail.com
>    2. http://table_search.name/
>    3. http://palantir.com/
>    4. http://p.sf.net/sfu/SauceLabs
>    5. https://sourceforge.net/p/tmux/tickets/172/
>    6. 
> https://github.com/rosshadden/dotfiles/blob/master/src/.tmux.conf#L79-L85
>    7. https://github.com/rosshadden/dotfiles/blob/master/src/lib/tmux-
>    8. http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual-
>    9. mailto:tmux-users@lists.sourceforge.net
>   10. https://lists.sourceforge.net/lists/listinfo/tmux-users

------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to