mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Permit commands to be bound to key presses without the prefix key first. The
new -n flag to bind-key and unbind-key sets or removes these bindings, and list-key shows them in []s.
This commit is contained in:
		@@ -39,7 +39,7 @@ struct cmd_bind_key_data {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const struct cmd_entry cmd_bind_key_entry = {
 | 
					const struct cmd_entry cmd_bind_key_entry = {
 | 
				
			||||||
	"bind-key", "bind",
 | 
						"bind-key", "bind",
 | 
				
			||||||
	"[-r] key command [arguments]",
 | 
						"[-nr] key command [arguments]",
 | 
				
			||||||
	0, 0,
 | 
						0, 0,
 | 
				
			||||||
	NULL,
 | 
						NULL,
 | 
				
			||||||
	cmd_bind_key_parse,
 | 
						cmd_bind_key_parse,
 | 
				
			||||||
@@ -54,14 +54,17 @@ int
 | 
				
			|||||||
cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
 | 
					cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cmd_bind_key_data	*data;
 | 
						struct cmd_bind_key_data	*data;
 | 
				
			||||||
	int				 opt;
 | 
						int				 opt, no_prefix = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	self->data = data = xmalloc(sizeof *data);
 | 
						self->data = data = xmalloc(sizeof *data);
 | 
				
			||||||
	data->can_repeat = 0;
 | 
						data->can_repeat = 0;
 | 
				
			||||||
	data->cmdlist = NULL;
 | 
						data->cmdlist = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((opt = getopt(argc, argv, "r")) != -1) {
 | 
						while ((opt = getopt(argc, argv, "nr")) != -1) {
 | 
				
			||||||
		switch (opt) {
 | 
							switch (opt) {
 | 
				
			||||||
 | 
							case 'n':
 | 
				
			||||||
 | 
								no_prefix = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case 'r':
 | 
							case 'r':
 | 
				
			||||||
			data->can_repeat = 1;
 | 
								data->can_repeat = 1;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
@@ -78,6 +81,8 @@ cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
 | 
				
			|||||||
		xasprintf(cause, "unknown key: %s", argv[0]);
 | 
							xasprintf(cause, "unknown key: %s", argv[0]);
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (!no_prefix)
 | 
				
			||||||
 | 
							data->key |= KEYC_PREFIX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	argc--;
 | 
						argc--;
 | 
				
			||||||
	argv++;
 | 
						argv++;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,27 +46,33 @@ cmd_list_keys_exec(unused struct cmd *self, struct cmd_ctx *ctx)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	struct key_binding	*bd;
 | 
						struct key_binding	*bd;
 | 
				
			||||||
	const char		*key;
 | 
						const char		*key;
 | 
				
			||||||
	char			 tmp[BUFSIZ];
 | 
						char			 tmp[BUFSIZ], keytmp[64];
 | 
				
			||||||
	int			 width, keywidth;
 | 
						int			 width, keywidth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	width = 0;
 | 
						width = 0;
 | 
				
			||||||
	SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
 | 
						SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
 | 
				
			||||||
		if ((key = key_string_lookup_key(bd->key)) == NULL)
 | 
							key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
 | 
				
			||||||
 | 
							if (key == NULL)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		keywidth = strlen(key) + 1;
 | 
							keywidth = strlen(key) + 1;
 | 
				
			||||||
 | 
							if (!(bd->key & KEYC_PREFIX))
 | 
				
			||||||
 | 
								keywidth += 2;
 | 
				
			||||||
		if (keywidth > width)
 | 
							if (keywidth > width)
 | 
				
			||||||
			width = keywidth;
 | 
								width = keywidth;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
 | 
						SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
 | 
				
			||||||
		if ((key = key_string_lookup_key(bd->key)) == NULL)
 | 
							key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
 | 
				
			||||||
 | 
							if (key == NULL)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		*tmp = '\0';
 | 
							*tmp = '\0';
 | 
				
			||||||
		cmd_list_print(bd->cmdlist, tmp, sizeof tmp);
 | 
							cmd_list_print(bd->cmdlist, tmp, sizeof tmp);
 | 
				
			||||||
 | 
							if (!(bd->key & KEYC_PREFIX)) {
 | 
				
			||||||
 | 
								xsnprintf(keytmp, sizeof keytmp, "[%s]", key);
 | 
				
			||||||
 | 
								key = keytmp;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		ctx->print(ctx, "%*s: %s", width, key, tmp);
 | 
							ctx->print(ctx, "%*s: %s", width, key, tmp);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,7 @@ struct cmd_unbind_key_data {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const struct cmd_entry cmd_unbind_key_entry = {
 | 
					const struct cmd_entry cmd_unbind_key_entry = {
 | 
				
			||||||
	"unbind-key", "unbind",
 | 
						"unbind-key", "unbind",
 | 
				
			||||||
	"key",
 | 
						"[-n] key",
 | 
				
			||||||
	0, 0,
 | 
						0, 0,
 | 
				
			||||||
	NULL,
 | 
						NULL,
 | 
				
			||||||
	cmd_unbind_key_parse,
 | 
						cmd_unbind_key_parse,
 | 
				
			||||||
@@ -51,12 +51,15 @@ int
 | 
				
			|||||||
cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
 | 
					cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cmd_unbind_key_data	*data;
 | 
						struct cmd_unbind_key_data	*data;
 | 
				
			||||||
	int				 opt;
 | 
						int				 opt, no_prefix = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	self->data = data = xmalloc(sizeof *data);
 | 
						self->data = data = xmalloc(sizeof *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((opt = getopt(argc, argv, "")) != -1) {
 | 
						while ((opt = getopt(argc, argv, "n")) != -1) {
 | 
				
			||||||
		switch (opt) {
 | 
							switch (opt) {
 | 
				
			||||||
 | 
							case 'n':
 | 
				
			||||||
 | 
								no_prefix = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			goto usage;
 | 
								goto usage;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -70,6 +73,8 @@ cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
 | 
				
			|||||||
		xasprintf(cause, "unknown key: %s", argv[0]);
 | 
							xasprintf(cause, "unknown key: %s", argv[0]);
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (!no_prefix)
 | 
				
			||||||
 | 
							data->key |= KEYC_PREFIX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,18 @@ struct key_bindings	dead_key_bindings;
 | 
				
			|||||||
int
 | 
					int
 | 
				
			||||||
key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
 | 
					key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return (bd1->key - bd2->key);
 | 
						int	key1, key2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key1 = bd1->key & ~KEYC_PREFIX;
 | 
				
			||||||
 | 
						key2 = bd2->key & ~KEYC_PREFIX;
 | 
				
			||||||
 | 
						if (key1 != key2)
 | 
				
			||||||
 | 
							return (key1 - key2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bd1->key & KEYC_PREFIX && !(bd2->key & KEYC_PREFIX))
 | 
				
			||||||
 | 
							return (-1);
 | 
				
			||||||
 | 
						if (bd2->key & KEYC_PREFIX && !(bd1->key & KEYC_PREFIX))
 | 
				
			||||||
 | 
							return (1);
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct key_binding *
 | 
					struct key_binding *
 | 
				
			||||||
@@ -170,7 +181,8 @@ key_bindings_init(void)
 | 
				
			|||||||
			cmd->entry->init(cmd, table[i].key);
 | 
								cmd->entry->init(cmd, table[i].key);
 | 
				
			||||||
		TAILQ_INSERT_HEAD(cmdlist, cmd, qentry);
 | 
							TAILQ_INSERT_HEAD(cmdlist, cmd, qentry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		key_bindings_add(table[i].key, table[i].can_repeat, cmdlist);
 | 
							key_bindings_add(
 | 
				
			||||||
 | 
							    table[i].key | KEYC_PREFIX, table[i].can_repeat, cmdlist);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								server.c
									
									
									
									
									
								
							@@ -802,14 +802,19 @@ server_handle_client(struct client *c)
 | 
				
			|||||||
		if (!(c->flags & CLIENT_PREFIX)) {
 | 
							if (!(c->flags & CLIENT_PREFIX)) {
 | 
				
			||||||
			if (key == prefix)
 | 
								if (key == prefix)
 | 
				
			||||||
				c->flags |= CLIENT_PREFIX;
 | 
									c->flags |= CLIENT_PREFIX;
 | 
				
			||||||
			else
 | 
								else {
 | 
				
			||||||
 | 
									/* Try as a non-prefix key binding. */
 | 
				
			||||||
 | 
									if ((bd = key_bindings_lookup(key)) == NULL)
 | 
				
			||||||
					window_pane_key(wp, c, key);
 | 
										window_pane_key(wp, c, key);
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
										key_bindings_dispatch(bd, c);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Prefix key already pressed. Reset prefix and lookup key. */
 | 
							/* Prefix key already pressed. Reset prefix and lookup key. */
 | 
				
			||||||
		c->flags &= ~CLIENT_PREFIX;
 | 
							c->flags &= ~CLIENT_PREFIX;
 | 
				
			||||||
		if ((bd = key_bindings_lookup(key)) == NULL) {
 | 
							if ((bd = key_bindings_lookup(key | KEYC_PREFIX)) == NULL) {
 | 
				
			||||||
			/* If repeating, treat this as a key, else ignore. */
 | 
								/* If repeating, treat this as a key, else ignore. */
 | 
				
			||||||
			if (c->flags & CLIENT_REPEAT) {
 | 
								if (c->flags & CLIENT_REPEAT) {
 | 
				
			||||||
				c->flags &= ~CLIENT_REPEAT;
 | 
									c->flags &= ~CLIENT_REPEAT;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								tmux.1
									
									
									
									
									
								
							@@ -617,7 +617,7 @@ If no server is started,
 | 
				
			|||||||
will attempt to start it; this will fail unless sessions are created in the
 | 
					will attempt to start it; this will fail unless sessions are created in the
 | 
				
			||||||
configuration file.
 | 
					configuration file.
 | 
				
			||||||
.It Xo Ic bind-key
 | 
					.It Xo Ic bind-key
 | 
				
			||||||
.Op Fl r
 | 
					.Op Fl nr
 | 
				
			||||||
.Ar key Ar command Op Ar arguments
 | 
					.Ar key Ar command Op Ar arguments
 | 
				
			||||||
.Xc
 | 
					.Xc
 | 
				
			||||||
.D1 (alias: Ic bind )
 | 
					.D1 (alias: Ic bind )
 | 
				
			||||||
@@ -632,6 +632,13 @@ or
 | 
				
			|||||||
for Ctrl keys, or
 | 
					for Ctrl keys, or
 | 
				
			||||||
.Ql M-
 | 
					.Ql M-
 | 
				
			||||||
for Alt (meta) keys.
 | 
					for Alt (meta) keys.
 | 
				
			||||||
 | 
					If
 | 
				
			||||||
 | 
					.Fl n
 | 
				
			||||||
 | 
					is specified, it is not necessary to use the prefix key,
 | 
				
			||||||
 | 
					.Ar command
 | 
				
			||||||
 | 
					is bound to
 | 
				
			||||||
 | 
					.Ar key
 | 
				
			||||||
 | 
					alone.
 | 
				
			||||||
The
 | 
					The
 | 
				
			||||||
.Fl r
 | 
					.Fl r
 | 
				
			||||||
flag indicates this key may repeat, see the
 | 
					flag indicates this key may repeat, see the
 | 
				
			||||||
@@ -842,6 +849,10 @@ List the syntax of all commands supported by
 | 
				
			|||||||
.Xc
 | 
					.Xc
 | 
				
			||||||
.D1 (alias: Ic lsk )
 | 
					.D1 (alias: Ic lsk )
 | 
				
			||||||
List all key bindings.
 | 
					List all key bindings.
 | 
				
			||||||
 | 
					Keys bound without the prefix key (see
 | 
				
			||||||
 | 
					.Ic bind-key
 | 
				
			||||||
 | 
					.Fl n )
 | 
				
			||||||
 | 
					are enclosed in square brackets.
 | 
				
			||||||
.It Xo Ic list-sessions
 | 
					.It Xo Ic list-sessions
 | 
				
			||||||
.Xc
 | 
					.Xc
 | 
				
			||||||
.D1 (alias: Ic ls )
 | 
					.D1 (alias: Ic ls )
 | 
				
			||||||
@@ -1613,11 +1624,17 @@ Switch the current session for client
 | 
				
			|||||||
to
 | 
					to
 | 
				
			||||||
.Ar target-session .
 | 
					.Ar target-session .
 | 
				
			||||||
.It Xo Ic unbind-key
 | 
					.It Xo Ic unbind-key
 | 
				
			||||||
 | 
					.Op Fl n
 | 
				
			||||||
.Ar key
 | 
					.Ar key
 | 
				
			||||||
.Xc
 | 
					.Xc
 | 
				
			||||||
.D1 (alias: Ic unbind )
 | 
					.D1 (alias: Ic unbind )
 | 
				
			||||||
Unbind the command bound to
 | 
					Unbind the command bound to
 | 
				
			||||||
.Ar key .
 | 
					.Ar key .
 | 
				
			||||||
 | 
					If
 | 
				
			||||||
 | 
					.Fl n
 | 
				
			||||||
 | 
					is specified, the command bound to
 | 
				
			||||||
 | 
					.Ar key
 | 
				
			||||||
 | 
					without a prefix (if any) is removed.
 | 
				
			||||||
.It Xo Ic unlink-window
 | 
					.It Xo Ic unlink-window
 | 
				
			||||||
.Op Fl k
 | 
					.Op Fl k
 | 
				
			||||||
.Op Fl t Ar target-window
 | 
					.Op Fl t Ar target-window
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								tmux.h
									
									
									
									
									
								
							@@ -102,10 +102,12 @@ struct buffer {
 | 
				
			|||||||
#define BELL_CURRENT 2
 | 
					#define BELL_CURRENT 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Key codes. ncurses defines KEY_*. Grrr. */
 | 
					/* Key codes. ncurses defines KEY_*. Grrr. */
 | 
				
			||||||
#define KEYC_NONE    0x0fff
 | 
					#define KEYC_NONE 0xfff
 | 
				
			||||||
 | 
					/* 0x1000 is base for special keys */
 | 
				
			||||||
#define KEYC_ESCAPE 0x2000
 | 
					#define KEYC_ESCAPE 0x2000
 | 
				
			||||||
#define KEYC_CTRL 0x4000
 | 
					#define KEYC_CTRL 0x4000
 | 
				
			||||||
#define KEYC_SHIFT 0x8000
 | 
					#define KEYC_SHIFT 0x8000
 | 
				
			||||||
 | 
					#define KEYC_PREFIX 0x10000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum key_code {
 | 
					enum key_code {
 | 
				
			||||||
	/* Mouse key. */
 | 
						/* Mouse key. */
 | 
				
			||||||
@@ -856,8 +858,6 @@ struct client_ctx {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Key/command line command. */
 | 
					/* Key/command line command. */
 | 
				
			||||||
struct cmd_ctx {
 | 
					struct cmd_ctx {
 | 
				
			||||||
	struct client  *cmdclient;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * curclient is the client where this command was executed if inside
 | 
						 * curclient is the client where this command was executed if inside
 | 
				
			||||||
	 * tmux. This is NULL if the command came from the command-line.
 | 
						 * tmux. This is NULL if the command came from the command-line.
 | 
				
			||||||
@@ -869,6 +869,8 @@ struct cmd_ctx {
 | 
				
			|||||||
	 * configuration file.
 | 
						 * configuration file.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	struct client  *curclient;
 | 
						struct client  *curclient;
 | 
				
			||||||
 | 
						struct client  *cmdclient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct session *cursession;
 | 
						struct session *cursession;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct msg_command_data	*msgdata;
 | 
						struct msg_command_data	*msgdata;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user