1 /* $OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@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  * 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, NULL },
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, NULL },
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 = { "gpt:w", 0, 1, NULL },
68           .usage = "[-gpw] " CMD_TARGET_PANE_USAGE,
69 
70           .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
71 
72           .flags = CMD_AFTERHOOK,
73           .exec = cmd_show_options_exec
74 };
75 
76 static enum cmd_retval
cmd_show_options_exec(struct cmd * self,struct cmdq_item * item)77 cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
78 {
79           struct args                             *args = cmd_get_args(self);
80           struct cmd_find_state                   *target = cmdq_get_target(item);
81           struct options                          *oo;
82           char                                    *argument, *name = NULL, *cause;
83           int                                      window, idx, ambiguous, parent, scope;
84           struct options_entry                    *o;
85 
86           window = (cmd_get_entry(self) == &cmd_show_window_options_entry);
87 
88           if (args_count(args) == 0) {
89                     scope = options_scope_from_flags(args, window, target, &oo,
90                         &cause);
91                     if (scope == OPTIONS_TABLE_NONE) {
92                               if (args_has(args, 'q'))
93                                         return (CMD_RETURN_NORMAL);
94                               cmdq_error(item, "%s", cause);
95                               free(cause);
96                               return (CMD_RETURN_ERROR);
97                     }
98                     return (cmd_show_options_all(self, item, scope, oo));
99           }
100           argument = format_single_from_target(item, args_string(args, 0));
101 
102           name = options_match(argument, &idx, &ambiguous);
103           if (name == NULL) {
104                     if (args_has(args, 'q'))
105                               goto out;
106                     if (ambiguous)
107                               cmdq_error(item, "ambiguous option: %s", argument);
108                     else
109                               cmdq_error(item, "invalid option: %s", argument);
110                     goto fail;
111           }
112           scope = options_scope_from_name(args, window, name, target, &oo,
113               &cause);
114           if (scope == OPTIONS_TABLE_NONE) {
115                     if (args_has(args, 'q'))
116                               goto out;
117                     cmdq_error(item, "%s", cause);
118                     free(cause);
119                     goto fail;
120           }
121           o = options_get_only(oo, name);
122           if (args_has(args, 'A') && o == NULL) {
123                     o = options_get(oo, name);
124                     parent = 1;
125           } else
126                     parent = 0;
127           if (o != NULL)
128                     cmd_show_options_print(self, item, o, idx, parent);
129           else if (*name == '@') {
130                     if (args_has(args, 'q'))
131                               goto out;
132                     cmdq_error(item, "invalid option: %s", argument);
133                     goto fail;
134           }
135 
136 out:
137           free(name);
138           free(argument);
139           return (CMD_RETURN_NORMAL);
140 
141 fail:
142           free(name);
143           free(argument);
144           return (CMD_RETURN_ERROR);
145 }
146 
147 static void
cmd_show_options_print(struct cmd * self,struct cmdq_item * item,struct options_entry * o,int idx,int parent)148 cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
149     struct options_entry *o, int idx, int parent)
150 {
151           struct args                             *args = cmd_get_args(self);
152           struct options_array_item     *a;
153           const char                              *name = options_name(o);
154           char                                    *value, *tmp = NULL, *escaped;
155 
156           if (idx != -1) {
157                     xasprintf(&tmp, "%s[%d]", name, idx);
158                     name = tmp;
159           } else {
160                     if (options_is_array(o)) {
161                               a = options_array_first(o);
162                               if (a == NULL) {
163                                         if (!args_has(args, 'v'))
164                                                   cmdq_print(item, "%s", name);
165                                         return;
166                               }
167                               while (a != NULL) {
168                                         idx = options_array_item_index(a);
169                                         cmd_show_options_print(self, item, o, idx,
170                                             parent);
171                                         a = options_array_next(a);
172                               }
173                               return;
174                     }
175           }
176 
177           value = options_to_string(o, idx, 0);
178           if (args_has(args, 'v'))
179                     cmdq_print(item, "%s", value);
180           else if (options_is_string(o)) {
181                     escaped = args_escape(value);
182                     if (parent)
183                               cmdq_print(item, "%s* %s", name, escaped);
184                     else
185                               cmdq_print(item, "%s %s", name, escaped);
186                     free(escaped);
187           } else {
188                     if (parent)
189                               cmdq_print(item, "%s* %s", name, value);
190                     else
191                               cmdq_print(item, "%s %s", name, value);
192           }
193           free(value);
194 
195           free(tmp);
196 }
197 
198 static enum cmd_retval
cmd_show_options_all(struct cmd * self,struct cmdq_item * item,int scope,struct options * oo)199 cmd_show_options_all(struct cmd *self, struct cmdq_item *item, int scope,
200     struct options *oo)
201 {
202           struct args                                       *args = cmd_get_args(self);
203           const struct options_table_entry        *oe;
204           struct options_entry                              *o;
205           struct options_array_item               *a;
206           const char                                        *name;
207           u_int                                              idx;
208           int                                                parent;
209 
210           if (cmd_get_entry(self) != &cmd_show_hooks_entry) {
211                     o = options_first(oo);
212                     while (o != NULL) {
213                               if (options_table_entry(o) == NULL)
214                                         cmd_show_options_print(self, item, o, -1, 0);
215                               o = options_next(o);
216                     }
217           }
218           for (oe = options_table; oe->name != NULL; oe++) {
219                     if (~oe->scope & scope)
220                               continue;
221 
222                     if ((cmd_get_entry(self) != &cmd_show_hooks_entry &&
223                         !args_has(args, 'H') &&
224                         (oe->flags & OPTIONS_TABLE_IS_HOOK)) ||
225                         (cmd_get_entry(self) == &cmd_show_hooks_entry &&
226                         (~oe->flags & OPTIONS_TABLE_IS_HOOK)))
227                               continue;
228 
229                     o = options_get_only(oo, oe->name);
230                     if (o == NULL) {
231                               if (!args_has(args, 'A'))
232                                         continue;
233                               o = options_get(oo, oe->name);
234                               if (o == NULL)
235                                         continue;
236                               parent = 1;
237                     } else
238                               parent = 0;
239 
240                     if (!options_is_array(o))
241                               cmd_show_options_print(self, item, o, -1, parent);
242                     else if ((a = options_array_first(o)) == NULL) {
243                               if (!args_has(args, 'v')) {
244                                         name = options_name(o);
245                                         if (parent)
246                                                   cmdq_print(item, "%s*", name);
247                                         else
248                                                   cmdq_print(item, "%s", name);
249                               }
250                     } else {
251                               while (a != NULL) {
252                                         idx = options_array_item_index(a);
253                                         cmd_show_options_print(self, item, o, idx,
254                                             parent);
255                                         a = options_array_next(a);
256                               }
257                     }
258           }
259           return (CMD_RETURN_NORMAL);
260 }
261