summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2009-07-28 17:05:10 +0000
committerNicholas Marriott <nicm@openbsd.org>2009-07-28 17:05:10 +0000
commitf596be99505a0191cac9f314fb1b71528c5080b4 (patch)
tree1e765f4841da1107e11322d7ba62445f61ec67af
parent9e5d585ba4b0af6badf559cc7b275a23be8947c2 (diff)
Final pieces of mode key rebinding: bind-key and unbind-key now accept a -t
argument to modify a table.
-rw-r--r--cmd-bind-key.c70
-rw-r--r--cmd-list-keys.c6
-rw-r--r--cmd-unbind-key.c42
-rw-r--r--mode-key.c30
-rw-r--r--tmux.146
-rw-r--r--tmux.h2
6 files changed, 179 insertions, 17 deletions
diff --git a/cmd-bind-key.c b/cmd-bind-key.c
index 41d8eeb8..041f558d 100644
--- a/cmd-bind-key.c
+++ b/cmd-bind-key.c
@@ -18,6 +18,8 @@
#include <sys/types.h>
+#include <string.h>
+
#include "tmux.h"
/*
@@ -29,15 +31,21 @@ int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_bind_key_free(struct cmd *);
size_t cmd_bind_key_print(struct cmd *, char *, size_t);
+int cmd_bind_key_table(struct cmd *, struct cmd_ctx *);
+
struct cmd_bind_key_data {
int key;
int can_repeat;
struct cmd_list *cmdlist;
+
+ int command_key;
+ char *tablename;
+ char *modecmd;
};
const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind",
- "[-nr] key command [arguments]",
+ "[-cnr] [-t key-table] key command [arguments]",
0, 0,
NULL,
cmd_bind_key_parse,
@@ -55,15 +63,24 @@ cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
self->data = data = xmalloc(sizeof *data);
data->can_repeat = 0;
data->cmdlist = NULL;
+ data->command_key = 0;
+ data->tablename = NULL;
+ data->modecmd = NULL;
- while ((opt = getopt(argc, argv, "nr")) != -1) {
+ while ((opt = getopt(argc, argv, "cnrt:")) != -1) {
switch (opt) {
+ case 'c':
+ data->command_key = 1;
+ break;
case 'n':
no_prefix = 1;
break;
case 'r':
data->can_repeat = 1;
break;
+ case 't':
+ data->tablename = xstrdup(optarg);
+ break;
default:
goto usage;
}
@@ -82,8 +99,14 @@ cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
argc--;
argv++;
- if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL)
- goto error;
+ if (data->tablename != NULL) {
+ if (argc != 1)
+ goto usage;
+ data->modecmd = xstrdup(argv[0]);
+ } else {
+ if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL)
+ goto error;
+ }
return (0);
@@ -102,6 +125,8 @@ cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
if (data == NULL)
return (0);
+ if (data->tablename != NULL)
+ return (cmd_bind_key_table(self, ctx));
key_bindings_add(data->key, data->can_repeat, data->cmdlist);
data->cmdlist = NULL; /* avoid free */
@@ -109,6 +134,39 @@ cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
return (0);
}
+int
+cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx)
+{
+ struct cmd_bind_key_data *data = self->data;
+ const struct mode_key_table *mtab;
+ struct mode_key_binding *mbind, mtmp;
+ enum mode_key_cmd cmd;
+
+ if ((mtab = mode_key_findtable(data->tablename)) == NULL) {
+ ctx->error(ctx, "unknown key table: %s", data->tablename);
+ return (-1);
+ }
+
+ cmd = mode_key_fromstring(mtab->cmdstr, data->modecmd);
+ if (cmd == MODEKEY_NONE) {
+ ctx->error(ctx, "unknown command: %s", data->modecmd);
+ return (-1);
+ }
+
+ mtmp.key = data->key & ~KEYC_PREFIX;
+ mtmp.mode = data->command_key ? 1 : 0;
+ if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
+ mbind->cmd = cmd;
+ return (0);
+ }
+ mbind = xmalloc(sizeof *mbind);
+ mbind->key = mtmp.key;
+ mbind->mode = mtmp.mode;
+ mbind->cmd = cmd;
+ SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
+ return (0);
+}
+
void
cmd_bind_key_free(struct cmd *self)
{
@@ -116,6 +174,10 @@ cmd_bind_key_free(struct cmd *self)
if (data->cmdlist != NULL)
cmd_list_free(data->cmdlist);
+ if (data->tablename != NULL)
+ xfree(data->tablename);
+ if (data->modecmd != NULL)
+ xfree(data->modecmd);
xfree(data);
}
diff --git a/cmd-list-keys.c b/cmd-list-keys.c
index 0a22e82c..db64e244 100644
--- a/cmd-list-keys.c
+++ b/cmd-list-keys.c
@@ -92,11 +92,7 @@ cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
const char *key, *cmdstr, *mode;
int width, keywidth;
- for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
- if (strcasecmp(data->target, mtab->name) == 0)
- break;
- }
- if (mtab->name == NULL) {
+ if ((mtab = mode_key_findtable(data->target)) == NULL) {
ctx->error(ctx, "unknown key table: %s", data->target);
return (-1);
}
diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c
index 35c43658..8f5e794e 100644
--- a/cmd-unbind-key.c
+++ b/cmd-unbind-key.c
@@ -28,13 +28,18 @@ int cmd_unbind_key_parse(struct cmd *, int, char **, char **);
int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_unbind_key_free(struct cmd *);
+int cmd_unbind_key_table(struct cmd *, struct cmd_ctx *);
+
struct cmd_unbind_key_data {
int key;
+
+ int command_key;
+ char *tablename;
};
const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind",
- "[-n] key",
+ "[-cn] [-t key-table] key",
0, 0,
NULL,
cmd_unbind_key_parse,
@@ -50,12 +55,20 @@ cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
int opt, no_prefix = 0;
self->data = data = xmalloc(sizeof *data);
+ data->command_key = 0;
+ data->tablename = NULL;
- while ((opt = getopt(argc, argv, "n")) != -1) {
+ while ((opt = getopt(argc, argv, "cnt:")) != -1) {
switch (opt) {
+ case 'c':
+ data->command_key = 1;
+ break;
case 'n':
no_prefix = 1;
break;
+ case 't':
+ data->tablename = xstrdup(optarg);
+ break;
default:
goto usage;
}
@@ -89,16 +102,41 @@ cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
if (data == NULL)
return (0);
+ if (data->tablename != NULL)
+ return (cmd_unbind_key_table(self, ctx));
key_bindings_remove(data->key);
return (0);
}
+int
+cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx)
+{
+ struct cmd_unbind_key_data *data = self->data;
+ const struct mode_key_table *mtab;
+ struct mode_key_binding *mbind, mtmp;
+
+ if ((mtab = mode_key_findtable(data->tablename)) == NULL) {
+ ctx->error(ctx, "unknown key table: %s", data->tablename);
+ return (-1);
+ }
+
+ mtmp.key = data->key & ~KEYC_PREFIX;
+ mtmp.mode = data->command_key ? 1 : 0;
+ if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
+ SPLAY_REMOVE(mode_key_tree, mtab->tree, mbind);
+ xfree(mbind);
+ }
+ return (0);
+}
+
void
cmd_unbind_key_free(struct cmd *self)
{
struct cmd_unbind_key_data *data = self->data;
+ if (data->tablename != NULL)
+ xfree(data->tablename);
xfree(data);
}
diff --git a/mode-key.c b/mode-key.c
index e0f773d5..ccd5465c 100644
--- a/mode-key.c
+++ b/mode-key.c
@@ -18,6 +18,8 @@
#include <sys/types.h>
+#include <string.h>
+
#include "tmux.h"
/*
@@ -54,6 +56,8 @@ struct mode_key_cmdstr mode_key_cmdstr_edit[] = {
{ MODEKEYEDIT_STARTOFLINE, "start-of-line" },
{ MODEKEYEDIT_SWITCHMODE, "switch-mode" },
{ MODEKEYEDIT_SWITCHMODEAPPEND, "switch-mode-append" },
+
+ { 0, NULL }
};
/* Choice keys command strings. */
@@ -64,6 +68,8 @@ struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
{ MODEKEYCHOICE_PAGEDOWN, "page-down" },
{ MODEKEYCHOICE_PAGEUP, "page-up" },
{ MODEKEYCHOICE_UP, "up" },
+
+ { 0, NULL }
};
/* Copy keys command strings. */
@@ -83,6 +89,8 @@ struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
{ MODEKEYCOPY_STARTOFLINE, "start-of-line" },
{ MODEKEYCOPY_STARTSELECTION, "begin-selection" },
{ MODEKEYCOPY_UP, "cursor-up" },
+
+ { 0, NULL }
};
/* vi editing keys. */
@@ -278,6 +286,28 @@ mode_key_tostring(struct mode_key_cmdstr *cmdstr, enum mode_key_cmd cmd)
return (NULL);
}
+enum mode_key_cmd
+mode_key_fromstring(struct mode_key_cmdstr *cmdstr, const char *name)
+{
+ for (; cmdstr->name != NULL; cmdstr++) {
+ if (strcasecmp(cmdstr->name, name) == 0)
+ return (cmdstr->cmd);
+ }
+ return (MODEKEY_NONE);
+}
+
+const struct mode_key_table *
+mode_key_findtable(const char *name)
+{
+ const struct mode_key_table *mtab;
+
+ for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
+ if (strcasecmp(name, mtab->name) == 0)
+ return (mtab);
+ }
+ return (NULL);
+}
+
void
mode_key_init_trees(void)
{
diff --git a/tmux.1 b/tmux.1
index 1a3b1664..06bc76bd 100644
--- a/tmux.1
+++ b/tmux.1
@@ -352,7 +352,10 @@ and
used in copy and scroll modes.
The tables may be viewed with the
.Ic list-keys
-command.
+command and keys modified or removed with
+.Ic bind-key
+and
+.Ic unbind-key .
.Pp
The paste buffer key pastes the first line from the top paste buffer on the
stack.
@@ -637,7 +640,8 @@ If no server is started,
will attempt to start it; this will fail unless sessions are created in the
configuration file.
.It Xo Ic bind-key
-.Op Fl nr
+.Op Fl cnr
+.Op Fl t Ar key-table
.Ar key Ar command Op Ar arguments
.Xc
.D1 (alias: Ic bind )
@@ -652,7 +656,11 @@ or
for Ctrl keys, or
.Ql M-
for Alt (meta) keys.
-If
+.Pp
+By default (without
+.Fl t )
+the primary key bindings are modified (those normally activated with the prefix
+key); in this case, if
.Fl n
is specified, it is not necessary to use the prefix key,
.Ar command
@@ -664,6 +672,19 @@ The
flag indicates this key may repeat, see the
.Ic repeat-time
option.
+.Pp
+If
+.Fl t
+is present,
+.Ar key
+is bound in
+.Ar key-table :
+the binding for command mode with
+.Fl c
+or for normal mode without.
+To view the default bindings and possible commands, see the
+.Ic list-keys
+command.
.It Xo Ic break-pane
.Op Fl d
.Op Fl p Ar pane-index
@@ -866,7 +887,7 @@ List all clients attached to the server.
List the syntax of all commands supported by
.Nm .
.It Xo Ic list-keys
-.Op Ar Fl t Ar key-table
+.Op Fl t Ar key-table
.Xc
.D1 (alias: Ic lsk )
List all key bindings.
@@ -1665,17 +1686,30 @@ Switch the current session for client
to
.Ar target-session .
.It Xo Ic unbind-key
-.Op Fl n
+.Op Fl cn
+.Op Fl t Ar key-table
.Ar key
.Xc
.D1 (alias: Ic unbind )
Unbind the command bound to
.Ar key .
-If
+Without
+.Fl t
+the primary key bindings are modified; in this case, if
.Fl n
is specified, the command bound to
.Ar key
without a prefix (if any) is removed.
+.Pp
+If
+.Fl t
+is present,
+.Ar key
+in
+.Ar key-table
+is unbound: the binding for command mode with
+.Fl c
+or for normal mode without.
.It Xo Ic unlink-window
.Op Fl k
.Op Fl t Ar target-window
diff --git a/tmux.h b/tmux.h
index 9d5898ae..7fc2117c 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1098,6 +1098,8 @@ extern struct mode_key_tree mode_key_tree_emacs_copy;
int mode_key_cmp(struct mode_key_binding *, struct mode_key_binding *);
SPLAY_PROTOTYPE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
const char *mode_key_tostring(struct mode_key_cmdstr *r, enum mode_key_cmd);
+enum mode_key_cmd mode_key_fromstring(struct mode_key_cmdstr *, const char *);
+const struct mode_key_table *mode_key_findtable(const char *);
void mode_key_init_trees(void);
void mode_key_free_trees(void);
void mode_key_init(struct mode_key_data *, struct mode_key_tree *);