1/* $OpenBSD$ */
2
3/*
4 * Copyright (c) 2007 Nicholas Marriott <[email protected]>
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 * Show options.
28 */
29
30static enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmdq_item *);
31
32static void cmd_show_options_print(struct cmd *, struct cmdq_item *,
33 struct options_entry *, int, int);
34static enum cmd_retval cmd_show_options_all(struct cmd *, struct cmdq_item *,
35 int, struct options *);
36
37const struct cmd_entry cmd_show_options_entry = {
38 .name = "show-options",
39 .alias = "show",
40
41 .args = { "AgHpqst:vw", 0, 1 },
42 .usage = "[-AgHpqsvw] " CMD_TARGET_PANE_USAGE " [option]",
43
44 .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
45
46 .flags = CMD_AFTERHOOK,
47 .exec = cmd_show_options_exec
48};
49
50const struct cmd_entry cmd_show_window_options_entry = {
51 .name = "show-window-options",
52 .alias = "showw",
53
54 .args = { "gvt:", 0, 1 },
55 .usage = "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
56
57 .target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
58
59 .flags = CMD_AFTERHOOK,
60 .exec = cmd_show_options_exec
61};
62
63const struct cmd_entry cmd_show_hooks_entry = {
64 .name = "show-hooks",
65 .alias = NULL,
66
67 .args = { "gt:", 0, 1 },
68 .usage = "[-g] " CMD_TARGET_SESSION_USAGE,
69
70 .target = { 't', CMD_FIND_SESSION, 0 },
71
72 .flags = CMD_AFTERHOOK,
73 .exec = cmd_show_options_exec
74};
75
76static enum cmd_retval
77cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
78{
79 struct args *args = self->args;
80 struct cmd_find_state *fs = &item->target;
81 struct client *c = cmd_find_client(item, NULL, 1);
82 struct session *s = item->target.s;
83 struct winlink *wl = item->target.wl;
84 struct options *oo;
85 char *argument, *name = NULL, *cause;
86 int window, idx, ambiguous, parent, scope;
87 struct options_entry *o;
88
89 window = (self->entry == &cmd_show_window_options_entry);
90
91 if (args->argc == 0) {
92 scope = options_scope_from_flags(args, window, fs, &oo, &cause);
93 if (scope == OPTIONS_TABLE_NONE) {
94 if (args_has(args, 'q'))
95 return (CMD_RETURN_NORMAL);
96 cmdq_error(item, "%s", cause);
97 free(cause);
98 return (CMD_RETURN_ERROR);
99 }
100 return (cmd_show_options_all(self, item, scope, oo));
101 }
102 argument = format_single(item, args->argv[0], c, s, wl, NULL);
103
104 name = options_match(argument, &idx, &ambiguous);
105 if (name == NULL) {
106 if (args_has(args, 'q'))
107 goto fail;
108 if (ambiguous)
109 cmdq_error(item, "ambiguous option: %s", argument);
110 else
111 cmdq_error(item, "invalid option: %s", argument);
112 goto fail;
113 }
114 scope = options_scope_from_name(args, window, name, fs, &oo, &cause);
115 if (scope == OPTIONS_TABLE_NONE) {
116 if (args_has(args, 'q'))
117 goto fail;
118 cmdq_error(item, "%s", cause);
119 free(cause);
120 goto fail;
121 }
122 o = options_get_only(oo, name);
123 if (args_has(args, 'A') && o == NULL) {
124 o = options_get(oo, name);
125 parent = 1;
126 } else
127 parent = 0;
128 if (o != NULL)
129 cmd_show_options_print(self, item, o, idx, parent);
130
131 free(name);
132 free(argument);
133 return (CMD_RETURN_NORMAL);
134
135fail:
136 free(name);
137 free(argument);
138 return (CMD_RETURN_ERROR);
139}
140
141static void
142cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
143 struct options_entry *o, int idx, int parent)
144{
145 struct options_array_item *a;
146 const char *name = options_name(o);
147 char *value, *tmp = NULL, *escaped;
148
149 if (idx != -1) {
150 xasprintf(&tmp, "%s[%d]", name, idx);
151 name = tmp;
152 } else {
153 if (options_isarray(o)) {
154 a = options_array_first(o);
155 if (a == NULL) {
156 if (!args_has(self->args, 'v'))
157 cmdq_print(item, "%s", name);
158 return;
159 }
160 while (a != NULL) {
161 idx = options_array_item_index(a);
162 cmd_show_options_print(self, item, o, idx,
163 parent);
164 a = options_array_next(a);
165 }
166 return;
167 }
168 }
169
170 value = options_tostring(o, idx, 0);
171 if (args_has(self->args, 'v'))
172 cmdq_print(item, "%s", value);
173 else if (options_isstring(o)) {
174 escaped = args_escape(value);
175 if (parent)
176 cmdq_print(item, "%s* %s", name, escaped);
177 else
178 cmdq_print(item, "%s %s", name, escaped);
179 free(escaped);
180 } else {
181 if (parent)
182 cmdq_print(item, "%s* %s", name, value);
183 else
184 cmdq_print(item, "%s %s", name, value);
185 }
186 free(value);
187
188 free(tmp);
189}
190
191static enum cmd_retval
192cmd_show_options_all(struct cmd *self, struct cmdq_item *item, int scope,
193 struct options *oo)
194{
195 const struct options_table_entry *oe;
196 struct options_entry *o;
197 struct options_array_item *a;
198 const char *name;
199 u_int idx;
200 int parent;
201
202 o = options_first(oo);
203 while (o != NULL) {
204 if (options_table_entry(o) == NULL)
205 cmd_show_options_print(self, item, o, -1, 0);
206 o = options_next(o);
207 }
208 for (oe = options_table; oe->name != NULL; oe++) {
209 if (~oe->scope & scope)
210 continue;
211
212 if ((self->entry != &cmd_show_hooks_entry &&
213 !args_has(self->args, 'H') &&
214 oe != NULL &&
215 (oe->flags & OPTIONS_TABLE_IS_HOOK)) ||
216 (self->entry == &cmd_show_hooks_entry &&
217 (oe == NULL ||
218 (~oe->flags & OPTIONS_TABLE_IS_HOOK))))
219 continue;
220
221 o = options_get_only(oo, oe->name);
222 if (o == NULL) {
223 if (!args_has(self->args, 'A'))
224 continue;
225 o = options_get(oo, oe->name);
226 if (o == NULL)
227 continue;
228 parent = 1;
229 } else
230 parent = 0;
231
232 if (!options_isarray(o))
233 cmd_show_options_print(self, item, o, -1, parent);
234 else if ((a = options_array_first(o)) == NULL) {
235 if (!args_has(self->args, 'v')) {
236 name = options_name(o);
237 if (parent)
238 cmdq_print(item, "%s*", name);
239 else
240 cmdq_print(item, "%s", name);
241 }
242 } else {
243 while (a != NULL) {
244 idx = options_array_item_index(a);
245 cmd_show_options_print(self, item, o, idx,
246 parent);
247 a = options_array_next(a);
248 }
249 }
250 }
251 return (CMD_RETURN_NORMAL);
252}
253