cmd-list-keys.c revision 1.1.1.10 1 /* $OpenBSD$ */
2
3 /*
4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott (at) gmail.com>
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 <stdlib.h>
22 #include <string.h>
23
24 #include "tmux.h"
25
26 /*
27 * List key bindings.
28 */
29
30 static enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmdq_item *);
31
32 static enum cmd_retval cmd_list_keys_commands(struct cmd *,
33 struct cmdq_item *);
34
35 const struct cmd_entry cmd_list_keys_entry = {
36 .name = "list-keys",
37 .alias = "lsk",
38
39 .args = { "T:", 0, 0 },
40 .usage = "[-T key-table]",
41
42 .flags = CMD_STARTSERVER|CMD_AFTERHOOK,
43 .exec = cmd_list_keys_exec
44 };
45
46 const struct cmd_entry cmd_list_commands_entry = {
47 .name = "list-commands",
48 .alias = "lscm",
49
50 .args = { "F:", 0, 0 },
51 .usage = "[-F format]",
52
53 .flags = CMD_STARTSERVER|CMD_AFTERHOOK,
54 .exec = cmd_list_keys_exec
55 };
56
57 static enum cmd_retval
58 cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
59 {
60 struct args *args = self->args;
61 struct key_table *table;
62 struct key_binding *bd;
63 const char *tablename, *r;
64 char *key, *cp, *tmp;
65 int repeat, width, tablewidth, keywidth;
66 size_t tmpsize, tmpused, cplen;
67
68 if (self->entry == &cmd_list_commands_entry)
69 return (cmd_list_keys_commands(self, item));
70
71 tablename = args_get(args, 'T');
72 if (tablename != NULL && key_bindings_get_table(tablename, 0) == NULL) {
73 cmdq_error(item, "table %s doesn't exist", tablename);
74 return (CMD_RETURN_ERROR);
75 }
76
77 repeat = 0;
78 tablewidth = keywidth = 0;
79 table = key_bindings_first_table ();
80 while (table != NULL) {
81 if (tablename != NULL && strcmp(table->name, tablename) != 0) {
82 table = key_bindings_next_table(table);
83 continue;
84 }
85 bd = key_bindings_first(table);
86 while (bd != NULL) {
87 key = args_escape(key_string_lookup_key(bd->key));
88
89 if (bd->flags & KEY_BINDING_REPEAT)
90 repeat = 1;
91
92 width = utf8_cstrwidth(table->name);
93 if (width > tablewidth)
94 tablewidth = width;
95 width = utf8_cstrwidth(key);
96 if (width > keywidth)
97 keywidth = width;
98
99 free(key);
100 bd = key_bindings_next(table, bd);
101 }
102 table = key_bindings_next_table(table);
103 }
104
105 tmpsize = 256;
106 tmp = xmalloc(tmpsize);
107
108 table = key_bindings_first_table ();
109 while (table != NULL) {
110 if (tablename != NULL && strcmp(table->name, tablename) != 0) {
111 table = key_bindings_next_table(table);
112 continue;
113 }
114 bd = key_bindings_first(table);
115 while (bd != NULL) {
116 key = args_escape(key_string_lookup_key(bd->key));
117
118 if (!repeat)
119 r = "";
120 else if (bd->flags & KEY_BINDING_REPEAT)
121 r = "-r ";
122 else
123 r = " ";
124 tmpused = xsnprintf(tmp, tmpsize, "%s-T ", r);
125
126 cp = utf8_padcstr(table->name, tablewidth);
127 cplen = strlen(cp) + 1;
128 while (tmpused + cplen + 1 >= tmpsize) {
129 tmpsize *= 2;
130 tmp = xrealloc(tmp, tmpsize);
131 }
132 tmpused = strlcat(tmp, cp, tmpsize);
133 tmpused = strlcat(tmp, " ", tmpsize);
134 free(cp);
135
136 cp = utf8_padcstr(key, keywidth);
137 cplen = strlen(cp) + 1;
138 while (tmpused + cplen + 1 >= tmpsize) {
139 tmpsize *= 2;
140 tmp = xrealloc(tmp, tmpsize);
141 }
142 tmpused = strlcat(tmp, cp, tmpsize);
143 tmpused = strlcat(tmp, " ", tmpsize);
144 free(cp);
145
146 cp = cmd_list_print(bd->cmdlist, 1);
147 cplen = strlen(cp);
148 while (tmpused + cplen + 1 >= tmpsize) {
149 tmpsize *= 2;
150 tmp = xrealloc(tmp, tmpsize);
151 }
152 strlcat(tmp, cp, tmpsize);
153 free(cp);
154
155 cmdq_print(item, "bind-key %s", tmp);
156
157 free(key);
158 bd = key_bindings_next(table, bd);
159 }
160 table = key_bindings_next_table(table);
161 }
162
163 free(tmp);
164
165 return (CMD_RETURN_NORMAL);
166 }
167
168 static enum cmd_retval
169 cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
170 {
171 struct args *args = self->args;
172 const struct cmd_entry **entryp;
173 const struct cmd_entry *entry;
174 struct format_tree *ft;
175 const char *template, *s;
176 char *line;
177
178 if ((template = args_get(args, 'F')) == NULL) {
179 template = "#{command_list_name}"
180 "#{?command_list_alias, (#{command_list_alias}),} "
181 "#{command_list_usage}";
182 }
183
184 ft = format_create(item->client, item, FORMAT_NONE, 0);
185 format_defaults(ft, NULL, NULL, NULL, NULL);
186
187 for (entryp = cmd_table; *entryp != NULL; entryp++) {
188 entry = *entryp;
189
190 format_add(ft, "command_list_name", "%s", entry->name);
191 if (entry->alias != NULL)
192 s = entry->alias;
193 else
194 s = "";
195 format_add(ft, "command_list_alias", "%s", s);
196 if (entry->usage != NULL)
197 s = entry->usage;
198 else
199 s = "";
200 format_add(ft, "command_list_usage", "%s", s);
201
202 line = format_expand(ft, template);
203 if (*line != '\0')
204 cmdq_print(item, "%s", line);
205 free(line);
206 }
207
208 format_free(ft);
209 return (CMD_RETURN_NORMAL);
210 }
211