xref: /openbsd-src/usr.bin/tmux/cmd-list-keys.c (revision 26529d6f1f271c5f6986c5143821a95677eb1285)
1 /* $OpenBSD: cmd-list-keys.c,v 1.25 2014/10/20 23:27:14 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 <string.h>
22 
23 #include "tmux.h"
24 
25 /*
26  * List key bindings.
27  */
28 
29 enum cmd_retval	 cmd_list_keys_exec(struct cmd *, struct cmd_q *);
30 
31 enum cmd_retval	 cmd_list_keys_table(struct cmd *, struct cmd_q *);
32 enum cmd_retval	 cmd_list_keys_commands(struct cmd *, struct cmd_q *);
33 
34 const struct cmd_entry cmd_list_keys_entry = {
35 	"list-keys", "lsk",
36 	"t:", 0, 0,
37 	"[-t key-table]",
38 	0,
39 	cmd_list_keys_exec
40 };
41 
42 const struct cmd_entry cmd_list_commands_entry = {
43 	"list-commands", "lscm",
44 	"", 0, 0,
45 	"",
46 	0,
47 	cmd_list_keys_exec
48 };
49 
50 enum cmd_retval
51 cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
52 {
53 	struct args		*args = self->args;
54 	struct key_binding	*bd;
55 	const char		*key;
56 	char			 tmp[BUFSIZ], flags[8];
57 	size_t			 used;
58 	int			 width, keywidth;
59 
60 	if (self->entry == &cmd_list_commands_entry)
61 		return (cmd_list_keys_commands(self, cmdq));
62 
63 	if (args_has(args, 't'))
64 		return (cmd_list_keys_table(self, cmdq));
65 
66 	width = 0;
67 
68 	RB_FOREACH(bd, key_bindings, &key_bindings) {
69 		key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
70 		if (key == NULL)
71 			continue;
72 
73 		keywidth = strlen(key);
74 		if (!(bd->key & KEYC_PREFIX)) {
75 			if (bd->can_repeat)
76 				keywidth += 4;
77 			else
78 				keywidth += 3;
79 		} else if (bd->can_repeat)
80 			keywidth += 3;
81 		if (keywidth > width)
82 			width = keywidth;
83 	}
84 
85 	RB_FOREACH(bd, key_bindings, &key_bindings) {
86 		key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
87 		if (key == NULL)
88 			continue;
89 
90 		*flags = '\0';
91 		if (!(bd->key & KEYC_PREFIX)) {
92 			if (bd->can_repeat)
93 				xsnprintf(flags, sizeof flags, "-rn ");
94 			else
95 				xsnprintf(flags, sizeof flags, "-n ");
96 		} else if (bd->can_repeat)
97 			xsnprintf(flags, sizeof flags, "-r ");
98 
99 		used = xsnprintf(tmp, sizeof tmp, "%s%*s ",
100 		    flags, (int) (width - strlen(flags)), key);
101 		if (used >= sizeof tmp)
102 			continue;
103 
104 		cmd_list_print(bd->cmdlist, tmp + used, (sizeof tmp) - used);
105 		cmdq_print(cmdq, "bind-key %s", tmp);
106 	}
107 
108 	return (CMD_RETURN_NORMAL);
109 }
110 
111 enum cmd_retval
112 cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
113 {
114 	struct args			*args = self->args;
115 	const char			*tablename;
116 	const struct mode_key_table	*mtab;
117 	struct mode_key_binding		*mbind;
118 	const char			*key, *cmdstr, *mode;
119 	int			 	 width, keywidth, any_mode;
120 
121 	tablename = args_get(args, 't');
122 	if ((mtab = mode_key_findtable(tablename)) == NULL) {
123 		cmdq_error(cmdq, "unknown key table: %s", tablename);
124 		return (CMD_RETURN_ERROR);
125 	}
126 
127 	width = 0;
128 	any_mode = 0;
129 	RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
130 		key = key_string_lookup_key(mbind->key);
131 		if (key == NULL)
132 			continue;
133 
134 		if (mbind->mode != 0)
135 			any_mode = 1;
136 
137 		keywidth = strlen(key);
138 		if (keywidth > width)
139 			width = keywidth;
140 	}
141 
142 	RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
143 		key = key_string_lookup_key(mbind->key);
144 		if (key == NULL)
145 			continue;
146 
147 		mode = "";
148 		if (mbind->mode != 0)
149 			mode = "c";
150 		cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd);
151 		if (cmdstr != NULL) {
152 			cmdq_print(cmdq, "bind-key -%st %s%s %*s %s%s%s%s",
153 			    mode, any_mode && *mode == '\0' ? " " : "",
154 			    mtab->name, (int) width, key, cmdstr,
155 			    mbind->arg != NULL ? " \"" : "",
156 			    mbind->arg != NULL ? mbind->arg : "",
157 			    mbind->arg != NULL ? "\"": "");
158 		}
159 	}
160 
161 	return (CMD_RETURN_NORMAL);
162 }
163 
164 enum cmd_retval
165 cmd_list_keys_commands(unused struct cmd *self, struct cmd_q *cmdq)
166 {
167 	const struct cmd_entry	**entryp;
168 	const struct cmd_entry	 *entry;
169 
170 	for (entryp = cmd_table; *entryp != NULL; entryp++) {
171 		entry = *entryp;
172 		if (entry->alias == NULL) {
173 			cmdq_print(cmdq, "%s %s", entry->name, entry->usage);
174 			continue;
175 		}
176 		cmdq_print(cmdq, "%s (%s) %s", entry->name, entry->alias,
177 		    entry->usage);
178 	}
179 
180 	return (CMD_RETURN_NORMAL);
181 }
182