cmd-list-keys.c revision 1.1.1.6 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 enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmd_q *);
31
32 enum cmd_retval cmd_list_keys_table(struct cmd *, struct cmd_q *);
33 enum cmd_retval cmd_list_keys_commands(struct cmd_q *);
34
35 const struct cmd_entry cmd_list_keys_entry = {
36 .name = "list-keys",
37 .alias = "lsk",
38
39 .args = { "t:T:", 0, 0 },
40 .usage = "[-t mode-table] [-T key-table]",
41
42 .flags = CMD_STARTSERVER,
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 = { "", 0, 0 },
51 .usage = "",
52
53 .flags = CMD_STARTSERVER,
54 .exec = cmd_list_keys_exec
55 };
56
57 enum cmd_retval
58 cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
59 {
60 struct args *args = self->args;
61 struct key_table *table;
62 struct key_binding *bd;
63 const char *key, *tablename, *r;
64 char *cp, tmp[BUFSIZ];
65 int repeat, width, tablewidth, keywidth;
66
67 if (self->entry == &cmd_list_commands_entry)
68 return (cmd_list_keys_commands(cmdq));
69
70 if (args_has(args, 't'))
71 return (cmd_list_keys_table(self, cmdq));
72
73 tablename = args_get(args, 'T');
74 if (tablename != NULL && key_bindings_get_table(tablename, 0) == NULL) {
75 cmdq_error(cmdq, "table %s doesn't exist", tablename);
76 return (CMD_RETURN_ERROR);
77 }
78
79 repeat = 0;
80 tablewidth = keywidth = 0;
81 RB_FOREACH(table, key_tables, &key_tables) {
82 if (tablename != NULL && strcmp(table->name, tablename) != 0)
83 continue;
84 RB_FOREACH(bd, key_bindings, &table->key_bindings) {
85 key = key_string_lookup_key(bd->key);
86
87 if (bd->can_repeat)
88 repeat = 1;
89
90 width = utf8_cstrwidth(table->name);
91 if (width > tablewidth)
92 tablewidth = width;
93 width = utf8_cstrwidth(key);
94 if (width > keywidth)
95 keywidth = width;
96 }
97 }
98
99 RB_FOREACH(table, key_tables, &key_tables) {
100 if (tablename != NULL && strcmp(table->name, tablename) != 0)
101 continue;
102 RB_FOREACH(bd, key_bindings, &table->key_bindings) {
103 key = key_string_lookup_key(bd->key);
104
105 if (!repeat)
106 r = "";
107 else if (bd->can_repeat)
108 r = "-r ";
109 else
110 r = " ";
111 xsnprintf(tmp, sizeof tmp, "%s-T ", r);
112
113 cp = utf8_padcstr(table->name, tablewidth);
114 strlcat(tmp, cp, sizeof tmp);
115 strlcat(tmp, " ", sizeof tmp);
116 free(cp);
117
118 cp = utf8_padcstr(key, keywidth);
119 strlcat(tmp, cp, sizeof tmp);
120 strlcat(tmp, " ", sizeof tmp);
121 free(cp);
122
123 cp = cmd_list_print(bd->cmdlist);
124 strlcat(tmp, cp, sizeof tmp);
125 free(cp);
126
127 cmdq_print(cmdq, "bind-key %s", tmp);
128 }
129 }
130
131 return (CMD_RETURN_NORMAL);
132 }
133
134 enum cmd_retval
135 cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
136 {
137 struct args *args = self->args;
138 const char *tablename;
139 const struct mode_key_table *mtab;
140 struct mode_key_binding *mbind;
141 const char *key, *cmdstr, *mode;
142 int width, keywidth, any_mode;
143
144 tablename = args_get(args, 't');
145 if ((mtab = mode_key_findtable(tablename)) == NULL) {
146 cmdq_error(cmdq, "unknown key table: %s", tablename);
147 return (CMD_RETURN_ERROR);
148 }
149
150 width = 0;
151 any_mode = 0;
152 RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
153 key = key_string_lookup_key(mbind->key);
154
155 if (mbind->mode != 0)
156 any_mode = 1;
157
158 keywidth = strlen(key);
159 if (keywidth > width)
160 width = keywidth;
161 }
162
163 RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
164 key = key_string_lookup_key(mbind->key);
165
166 mode = "";
167 if (mbind->mode != 0)
168 mode = "c";
169 cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd);
170 if (cmdstr != NULL) {
171 cmdq_print(cmdq, "bind-key -%st %s%s %*s %s%s%s%s",
172 mode, any_mode && *mode == '\0' ? " " : "",
173 mtab->name, (int) width, key, cmdstr,
174 mbind->arg != NULL ? " \"" : "",
175 mbind->arg != NULL ? mbind->arg : "",
176 mbind->arg != NULL ? "\"": "");
177 }
178 }
179
180 return (CMD_RETURN_NORMAL);
181 }
182
183 enum cmd_retval
184 cmd_list_keys_commands(struct cmd_q *cmdq)
185 {
186 const struct cmd_entry **entryp;
187 const struct cmd_entry *entry;
188
189 for (entryp = cmd_table; *entryp != NULL; entryp++) {
190 entry = *entryp;
191 if (entry->alias == NULL) {
192 cmdq_print(cmdq, "%s %s", entry->name, entry->usage);
193 continue;
194 }
195 cmdq_print(cmdq, "%s (%s) %s", entry->name, entry->alias,
196 entry->usage);
197 }
198
199 return (CMD_RETURN_NORMAL);
200 }
201