Annotation of src/usr.bin/tmux/cmd-bind-key.c, Revision 1.7
1.7 ! nicm 1: /* $OpenBSD: cmd-bind-key.c,v 1.6 2009/11/13 19:53:28 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':
82: data->tablename = xstrdup(optarg);
83: break;
1.1 nicm 84: default:
85: goto usage;
86: }
87: }
88: argc -= optind;
89: argv += optind;
90: if (argc < 1)
91: goto usage;
92:
93: if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) {
94: xasprintf(cause, "unknown key: %s", argv[0]);
95: goto error;
96: }
1.3 nicm 97: if (!no_prefix)
98: data->key |= KEYC_PREFIX;
1.1 nicm 99:
100: argc--;
101: argv++;
1.5 nicm 102: if (data->tablename != NULL) {
103: if (argc != 1)
104: goto usage;
105: data->modecmd = xstrdup(argv[0]);
106: } else {
107: if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL)
108: goto error;
109: }
1.1 nicm 110:
111: return (0);
112:
113: usage:
114: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
115:
116: error:
117: self->entry->free(self);
118: return (-1);
119: }
120:
121: int
122: cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
123: {
124: struct cmd_bind_key_data *data = self->data;
125:
126: if (data == NULL)
127: return (0);
1.5 nicm 128: if (data->tablename != NULL)
129: return (cmd_bind_key_table(self, ctx));
1.1 nicm 130:
131: key_bindings_add(data->key, data->can_repeat, data->cmdlist);
132: data->cmdlist = NULL; /* avoid free */
133:
134: return (0);
135: }
136:
1.5 nicm 137: int
138: cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx)
139: {
140: struct cmd_bind_key_data *data = self->data;
141: const struct mode_key_table *mtab;
142: struct mode_key_binding *mbind, mtmp;
143: enum mode_key_cmd cmd;
144:
145: if ((mtab = mode_key_findtable(data->tablename)) == NULL) {
146: ctx->error(ctx, "unknown key table: %s", data->tablename);
147: return (-1);
148: }
149:
150: cmd = mode_key_fromstring(mtab->cmdstr, data->modecmd);
151: if (cmd == MODEKEY_NONE) {
152: ctx->error(ctx, "unknown command: %s", data->modecmd);
153: return (-1);
154: }
1.7 ! nicm 155:
1.5 nicm 156: mtmp.key = data->key & ~KEYC_PREFIX;
157: mtmp.mode = data->command_key ? 1 : 0;
158: if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
159: mbind->cmd = cmd;
160: return (0);
161: }
162: mbind = xmalloc(sizeof *mbind);
163: mbind->key = mtmp.key;
164: mbind->mode = mtmp.mode;
165: mbind->cmd = cmd;
166: SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
167: return (0);
168: }
169:
1.1 nicm 170: void
171: cmd_bind_key_free(struct cmd *self)
172: {
173: struct cmd_bind_key_data *data = self->data;
174:
175: if (data->cmdlist != NULL)
176: cmd_list_free(data->cmdlist);
1.5 nicm 177: if (data->tablename != NULL)
178: xfree(data->tablename);
179: if (data->modecmd != NULL)
180: xfree(data->modecmd);
1.1 nicm 181: xfree(data);
182: }
183:
184: size_t
185: cmd_bind_key_print(struct cmd *self, char *buf, size_t len)
186: {
187: struct cmd_bind_key_data *data = self->data;
188: size_t off = 0;
189: const char *skey;
190:
191: off += xsnprintf(buf, len, "%s", self->entry->name);
192: if (data == NULL)
193: return (off);
194: if (off < len) {
195: skey = key_string_lookup_key(data->key);
196: off += xsnprintf(buf + off, len - off, " %s ", skey);
197: }
198: if (off < len)
199: off += cmd_list_print(data->cmdlist, buf + off, len - off);
200: return (off);
201: }