regression in/with bind-key?

21 views
Skip to first unread message

Thomas Sattler

unread,
Apr 21, 2017, 5:58:38 AM4/21/17
to tmux-...@googlegroups.com
Hi Nicholas,

I used to bind keys to switch/move windows/panes to the root-table.
Until 2.3 these worked, even within copy-mode. In 2.4 they stopped
working (when in copy-mode).

Would it be possible to have a fallback from "copy-mode[-vi]" to
"root", in case there is no matching binding in the first table?

Or would it be better/easier to allow the argument to -T to be a
list, so one could define equal bindings to multiple key-tables
at once, like these:

bind-key -T root,copy-mode,copy-mode-vi C-PPage previous-window
bind-key -T root,copy-mode,copy-mode-vi C-NPage next-window

Thomas

Nicholas Marriott

unread,
Apr 21, 2017, 7:38:47 AM4/21/17
to Thomas Sattler, tmux-...@googlegroups.com
Yeah this change isn't ideal/ Perhaps falling back to root is the best
solution, but I think we should do it for all key tables, not just the
pane key table.

So basically, we pick a current table:

- if we're not in the root table, use that table;
- if we are in the root table, try the pane table if there is one;
- if no pane table, use the root table.

Then if the key isn't in that current table, try the root table
instead.

It is slightly complicated by the fact that if you started off in the
root table, keys need to go through to the pane, but if you didn't then
they don't. For something without a binding in prefix, like C-b u
shouldn't send a u in the pane.

I think this will be OK. Anyone who wants to bypass the root table will
now need to bind their keys to something in their tables, but I doubt
many people do that and I don't know how that would be a big problem.

(It unfortunately doesn't fix the annoying C-b C-b problem in copy mode,
but that's for a different reason anyway...)

Please try this:

Index: server-client.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/server-client.c,v
retrieving revision 1.221
diff -u -p -r1.221 server-client.c
--- server-client.c 20 Apr 2017 15:16:20 -0000 1.221
+++ server-client.c 21 Apr 2017 11:34:58 -0000
@@ -138,11 +138,11 @@ server_client_get_key_table(struct clien
return (name);
}

-/* Is this client using the default key table? */
-int
-server_client_is_default_key_table(struct client *c)
+/* Is this table the default key table? */
+static int
+server_client_is_default_key_table(struct client *c, struct key_table *table)
{
- return (strcmp(c->keytable->name, server_client_get_key_table(c)) == 0);
+ return (strcmp(table->name, server_client_get_key_table(c)) == 0);
}

/* Create a new client. */
@@ -793,8 +793,7 @@ server_client_handle_key(struct client *
struct window *w;
struct window_pane *wp;
struct timeval tv;
- const char *name;
- struct key_table *table;
+ struct key_table *table, *first;
struct key_binding bd_find, *bd;
int xtimeout;
struct cmd_find_state fs;
@@ -870,22 +869,18 @@ server_client_handle_key(struct client *
if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s))
goto forward;

-retry:
/*
* Work out the current key table. If the pane is in a mode, use
* the mode table instead of the default key table.
*/
- name = NULL;
- if (wp != NULL && wp->mode != NULL && wp->mode->key_table != NULL)
- name = wp->mode->key_table(wp);
- if (name == NULL || !server_client_is_default_key_table(c))
- table = c->keytable;
+ if (server_client_is_default_key_table(c, c->keytable) &&
+ wp != NULL &&
+ wp->mode != NULL &&
+ wp->mode->key_table != NULL)
+ table = key_bindings_get_table(wp->mode->key_table(wp), 1);
else
- table = key_bindings_get_table(name, 1);
- if (wp == NULL)
- log_debug("key table %s (no pane)", table->name);
- else
- log_debug("key table %s (pane %%%u)", table->name, wp->id);
+ table = c->keytable;
+ first = table;

/*
* The prefix always takes precedence and forces a switch to the prefix
@@ -899,6 +894,13 @@ retry:
return;
}

+retry:
+ /* Log key table. */
+ if (wp == NULL)
+ log_debug("key table %s (no pane)", table->name);
+ else
+ log_debug("key table %s (pane %%%u)", table->name, wp->id);
+
/* Try to see if there is a key binding in the current table. */
bd_find.key = key;
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
@@ -912,8 +914,11 @@ retry:
server_client_set_key_table(c, NULL);
c->flags &= ~CLIENT_REPEAT;
server_status_client(c);
+ table = c->keytable;
goto retry;
}
+ log_debug("got %s in key table %s", key_string_lookup_key(key),
+ table->name);

/*
* Take a reference to this table to make sure the key binding
@@ -958,19 +963,25 @@ retry:
}

/*
- * No match in this table. If repeating, switch the client back to the
- * root table and try again.
+ * No match in this table. If not in the root table or if repeating,
+ * switch the client back to the root table and try again.
*/
- if (c->flags & CLIENT_REPEAT) {
+ log_debug("no %s in key table %s", key_string_lookup_key(key),
+ table->name);
+ if (!server_client_is_default_key_table(c, table) ||
+ (c->flags & CLIENT_REPEAT)) {
server_client_set_key_table(c, NULL);
c->flags &= ~CLIENT_REPEAT;
server_status_client(c);
+ table = c->keytable;
goto retry;
}

- /* If no match and we're not in the root table, that's it. */
- if (name == NULL && !server_client_is_default_key_table(c)) {
- log_debug("no key in key table %s", table->name);
+ /*
+ * No match in the root table either. If this wasn't the first table
+ * tried, don't pass the key to the pane.
+ */
+ if (first != table) {
server_client_set_key_table(c, NULL);
server_status_client(c);
return;
Index: tmux.h
===================================================================
RCS file: /cvs/src/usr.bin/tmux/tmux.h,v
retrieving revision 1.744
diff -u -p -r1.744 tmux.h
--- tmux.h 20 Apr 2017 17:49:26 -0000 1.744
+++ tmux.h 21 Apr 2017 11:34:58 -0000
@@ -1836,7 +1836,6 @@ void server_client_set_identify(struct
void server_client_clear_identify(struct client *, struct window_pane *);
void server_client_set_key_table(struct client *, const char *);
const char *server_client_get_key_table(struct client *);
-int server_client_is_default_key_table(struct client *);
int server_client_check_nested(struct client *);
void server_client_handle_key(struct client *, key_code);
void server_client_create(int);

Thomas Sattler

unread,
Apr 21, 2017, 10:38:40 AM4/21/17
to tmux-...@googlegroups.com
Am 21.04.2017 um 13:38 schrieb Nicholas Marriott:
> Yeah this change isn't ideal/ Perhaps falling back to root is the best
> solution, but I think we should do it for all key tables, not just the
> pane key table.
>
> Please try this: [patch]

Using this patch, my key bindings seem to work again, in- and outside
copy-mode. (Without the need to define them for several tables. :-))

Thomas

Nicholas Marriott

unread,
Apr 21, 2017, 2:58:52 PM4/21/17
to Thomas Sattler, tmux-...@googlegroups.com
I have applied this now, thanks!
> --
> You received this message because you are subscribed to the Google Groups "tmux-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to tmux-users+...@googlegroups.com.
> To post to this group, send an email to tmux-...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages