Annotation of src/usr.bin/tmux/cmd-bind-key.c, Revision 1.8
1.8 ! nicm 1: /* $OpenBSD: cmd-bind-key.c,v 1.7 2009/12/03 22:50:10 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/types.h>
20:
1.5 nicm 21: #include <string.h>
22:
1.1 nicm 23: #include "tmux.h"
24:
25: /*
26: * Bind a key to a command, this recurses through cmd_*.
27: */
28:
29: int cmd_bind_key_parse(struct cmd *, int, char **, char **);
30: int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
31: void cmd_bind_key_free(struct cmd *);
32: size_t cmd_bind_key_print(struct cmd *, char *, size_t);
33:
1.5 nicm 34: int cmd_bind_key_table(struct cmd *, struct cmd_ctx *);
35:
1.1 nicm 36: struct cmd_bind_key_data {
37: int key;
38: int can_repeat;
39: struct cmd_list *cmdlist;
1.5 nicm 40:
41: int command_key;
42: char *tablename;
43: char *modecmd;
1.1 nicm 44: };
45:
46: const struct cmd_entry cmd_bind_key_entry = {
47: "bind-key", "bind",
1.5 nicm 48: "[-cnr] [-t key-table] key command [arguments]",
1.6 nicm 49: 0, "",
1.1 nicm 50: NULL,
51: cmd_bind_key_parse,
52: cmd_bind_key_exec,
53: cmd_bind_key_free,
54: cmd_bind_key_print
55: };
56:
57: int
58: cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
59: {
60: struct cmd_bind_key_data *data;
1.3 nicm 61: int opt, no_prefix = 0;
1.1 nicm 62:
63: self->data = data = xmalloc(sizeof *data);
64: data->can_repeat = 0;
65: data->cmdlist = NULL;
1.5 nicm 66: data->command_key = 0;
67: data->tablename = NULL;
68: data->modecmd = NULL;
1.1 nicm 69:
1.5 nicm 70: while ((opt = getopt(argc, argv, "cnrt:")) != -1) {
1.1 nicm 71: switch (opt) {
1.5 nicm 72: case 'c':
73: data->command_key = 1;
74: break;
1.3 nicm 75: case 'n':
76: no_prefix = 1;
77: break;
1.1 nicm 78: case 'r':
79: data->can_repeat = 1;
80: break;
1.5 nicm 81: case 't':
1.8 ! nicm 82: if (data->tablename == NULL)
! 83: data->tablename = xstrdup(optarg);
1.5 nicm 84: break;
1.1 nicm 85: default:
86: goto usage;
87: }
88: }
89: argc -= optind;
90: argv += optind;
91: if (argc < 1)
92: goto usage;
93:
94: if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) {
95: xasprintf(cause, "unknown key: %s", argv[0]);
96: goto error;
97: }
1.3 nicm 98: if (!no_prefix)
99: data->key |= KEYC_PREFIX;
1.1 nicm 100:
101: argc--;
102: argv++;
1.5 nicm 103: if (data->tablename != NULL) {
104: if (argc != 1)
105: goto usage;
106: data->modecmd = xstrdup(argv[0]);
107: } else {
108: if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL)
109: goto error;
110: }
1.1 nicm 111:
112: return (0);
113:
114: usage:
115: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
116:
117: error:
118: self->entry->free(self);
119: return (-1);
120: }
121:
122: int
123: cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
124: {
125: struct cmd_bind_key_data *data = self->data;
126:
127: if (data == NULL)
128: return (0);
1.5 nicm 129: if (data->tablename != NULL)
130: return (cmd_bind_key_table(self, ctx));
1.1 nicm 131:
132: key_bindings_add(data->key, data->can_repeat, data->cmdlist);
133: data->cmdlist = NULL; /* avoid free */
134:
135: return (0);
136: }
137:
1.5 nicm 138: int
139: cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx)
140: {
141: struct cmd_bind_key_data *data = self->data;
142: const struct mode_key_table *mtab;
143: struct mode_key_binding *mbind, mtmp;
144: enum mode_key_cmd cmd;
145:
146: if ((mtab = mode_key_findtable(data->tablename)) == NULL) {
147: ctx->error(ctx, "unknown key table: %s", data->tablename);
148: return (-1);
149: }
150:
151: cmd = mode_key_fromstring(mtab->cmdstr, data->modecmd);
152: if (cmd == MODEKEY_NONE) {
153: ctx->error(ctx, "unknown command: %s", data->modecmd);
154: return (-1);
155: }
1.7 nicm 156:
1.5 nicm 157: mtmp.key = data->key & ~KEYC_PREFIX;
158: mtmp.mode = data->command_key ? 1 : 0;
159: if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
160: mbind->cmd = cmd;
161: return (0);
162: }
163: mbind = xmalloc(sizeof *mbind);
164: mbind->key = mtmp.key;
165: mbind->mode = mtmp.mode;
166: mbind->cmd = cmd;
167: SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
168: return (0);
169: }
170:
1.1 nicm 171: void
172: cmd_bind_key_free(struct cmd *self)
173: {
174: struct cmd_bind_key_data *data = self->data;
175:
176: if (data->cmdlist != NULL)
177: cmd_list_free(data->cmdlist);
1.5 nicm 178: if (data->tablename != NULL)
179: xfree(data->tablename);
180: if (data->modecmd != NULL)
181: xfree(data->modecmd);
1.1 nicm 182: xfree(data);
183: }
184:
185: size_t
186: cmd_bind_key_print(struct cmd *self, char *buf, size_t len)
187: {
188: struct cmd_bind_key_data *data = self->data;
189: size_t off = 0;
190: const char *skey;
191:
192: off += xsnprintf(buf, len, "%s", self->entry->name);
193: if (data == NULL)
194: return (off);
195: if (off < len) {
196: skey = key_string_lookup_key(data->key);
197: off += xsnprintf(buf + off, len - off, " %s ", skey);
198: }
199: if (off < len)
200: off += cmd_list_print(data->cmdlist, buf + off, len - off);
201: return (off);
202: }