Annotation of src/usr.bin/tmux/cmd-bind-key.c, Revision 1.5
1.5 ! nicm 1: /* $OpenBSD: cmd-bind-key.c,v 1.4 2009/07/26 12:58:44 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.2 nicm 49: 0, 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: }
! 155:
! 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: }