cmd-bind-key.c revision 1.4
1/* $OpenBSD: cmd-bind-key.c,v 1.4 2009/07/26 12:58:44 nicm Exp $ */
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
21#include "tmux.h"
22
23/*
24 * Bind a key to a command, this recurses through cmd_*.
25 */
26
27int	cmd_bind_key_parse(struct cmd *, int, char **, char **);
28int	cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
29void	cmd_bind_key_free(struct cmd *);
30size_t	cmd_bind_key_print(struct cmd *, char *, size_t);
31
32struct cmd_bind_key_data {
33	int		 key;
34	int		 can_repeat;
35	struct cmd_list	*cmdlist;
36};
37
38const struct cmd_entry cmd_bind_key_entry = {
39	"bind-key", "bind",
40	"[-nr] key command [arguments]",
41	0, 0,
42	NULL,
43	cmd_bind_key_parse,
44	cmd_bind_key_exec,
45	cmd_bind_key_free,
46	cmd_bind_key_print
47};
48
49int
50cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
51{
52	struct cmd_bind_key_data	*data;
53	int				 opt, no_prefix = 0;
54
55	self->data = data = xmalloc(sizeof *data);
56	data->can_repeat = 0;
57	data->cmdlist = NULL;
58
59	while ((opt = getopt(argc, argv, "nr")) != -1) {
60		switch (opt) {
61		case 'n':
62			no_prefix = 1;
63			break;
64		case 'r':
65			data->can_repeat = 1;
66			break;
67		default:
68			goto usage;
69		}
70	}
71	argc -= optind;
72	argv += optind;
73	if (argc < 1)
74		goto usage;
75
76	if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) {
77		xasprintf(cause, "unknown key: %s", argv[0]);
78		goto error;
79	}
80	if (!no_prefix)
81		data->key |= KEYC_PREFIX;
82
83	argc--;
84	argv++;
85	if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL)
86		goto error;
87
88	return (0);
89
90usage:
91	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
92
93error:
94	self->entry->free(self);
95	return (-1);
96}
97
98int
99cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
100{
101	struct cmd_bind_key_data	*data = self->data;
102
103	if (data == NULL)
104		return (0);
105
106	key_bindings_add(data->key, data->can_repeat, data->cmdlist);
107	data->cmdlist = NULL;	/* avoid free */
108
109	return (0);
110}
111
112void
113cmd_bind_key_free(struct cmd *self)
114{
115	struct cmd_bind_key_data	*data = self->data;
116
117	if (data->cmdlist != NULL)
118		cmd_list_free(data->cmdlist);
119	xfree(data);
120}
121
122size_t
123cmd_bind_key_print(struct cmd *self, char *buf, size_t len)
124{
125	struct cmd_bind_key_data	*data = self->data;
126	size_t				 off = 0;
127	const char			*skey;
128
129	off += xsnprintf(buf, len, "%s", self->entry->name);
130	if (data == NULL)
131		return (off);
132	if (off < len) {
133		skey = key_string_lookup_key(data->key);
134		off += xsnprintf(buf + off, len - off, " %s ", skey);
135	}
136	if (off < len)
137		off += cmd_list_print(data->cmdlist, buf + off, len - off);
138	return (off);
139}
140