It needs a bit of love again after the mouse keys stuff that just went in so it may not be for a while...
On Sun, Apr 19, 2015 at 10:45:38PM +0100, Nicholas Marriott wrote: > 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