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 | |
30 | static enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmdq_item *); |
31 | |
32 | static void cmd_show_options_print(struct cmd *, struct cmdq_item *, |
33 | struct options_entry *, int, int); |
34 | static enum cmd_retval cmd_show_options_all(struct cmd *, struct cmdq_item *, |
35 | int, struct options *); |
36 | |
37 | const 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 | |
50 | const 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 | |
63 | const 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 | |
76 | static enum cmd_retval |
77 | cmd_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 | |
135 | fail: |
136 | free(name); |
137 | free(argument); |
138 | return (CMD_RETURN_ERROR); |
139 | } |
140 | |
141 | static void |
142 | cmd_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 | |
191 | static enum cmd_retval |
192 | cmd_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 | |