Expand format variables in the run-shell and if-shell shell commands,
[tmux-openbsd.git] / cmd-set-option.c
blob55b2c9297703546ac9a84eef2fc71dd5b10411bc
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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.
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.
19 #include <sys/types.h>
21 #include <stdlib.h>
22 #include <string.h>
24 #include "tmux.h"
27 * Set an option.
30 enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmd_ctx *);
32 enum cmd_retval cmd_set_option_user(struct cmd *, struct cmd_ctx *,
33 const char *, const char *);
35 int cmd_set_option_unset(struct cmd *, struct cmd_ctx *,
36 const struct options_table_entry *, struct options *,
37 const char *);
38 int cmd_set_option_set(struct cmd *, struct cmd_ctx *,
39 const struct options_table_entry *, struct options *,
40 const char *);
42 struct options_entry *cmd_set_option_string(struct cmd *, struct cmd_ctx *,
43 const struct options_table_entry *, struct options *,
44 const char *);
45 struct options_entry *cmd_set_option_number(struct cmd *, struct cmd_ctx *,
46 const struct options_table_entry *, struct options *,
47 const char *);
48 struct options_entry *cmd_set_option_key(struct cmd *, struct cmd_ctx *,
49 const struct options_table_entry *, struct options *,
50 const char *);
51 struct options_entry *cmd_set_option_colour(struct cmd *, struct cmd_ctx *,
52 const struct options_table_entry *, struct options *,
53 const char *);
54 struct options_entry *cmd_set_option_attributes(struct cmd *, struct cmd_ctx *,
55 const struct options_table_entry *, struct options *,
56 const char *);
57 struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_ctx *,
58 const struct options_table_entry *, struct options *,
59 const char *);
60 struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_ctx *,
61 const struct options_table_entry *, struct options *,
62 const char *);
64 const struct cmd_entry cmd_set_option_entry = {
65 "set-option", "set",
66 "agqst:uw", 1, 2,
67 "[-agsquw] [-t target-session|target-window] option [value]",
69 NULL,
70 NULL,
71 cmd_set_option_exec
74 const struct cmd_entry cmd_set_window_option_entry = {
75 "set-window-option", "setw",
76 "agqt:u", 1, 2,
77 "[-agqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
79 NULL,
80 NULL,
81 cmd_set_option_exec
84 enum cmd_retval
85 cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
87 struct args *args = self->args;
88 const struct options_table_entry *table, *oe;
89 struct session *s;
90 struct winlink *wl;
91 struct client *c;
92 struct options *oo;
93 struct window *w;
94 const char *optstr, *valstr;
95 u_int i;
97 /* Get the option name and value. */
98 optstr = args->argv[0];
99 if (*optstr == '\0') {
100 ctx->error(ctx, "invalid option");
101 return (CMD_RETURN_ERROR);
103 if (args->argc < 2)
104 valstr = NULL;
105 else
106 valstr = args->argv[1];
108 /* Is this a user option? */
109 if (*optstr == '@')
110 return (cmd_set_option_user(self, ctx, optstr, valstr));
112 /* Find the option entry, try each table. */
113 table = oe = NULL;
114 if (options_table_find(optstr, &table, &oe) != 0) {
115 ctx->error(ctx, "ambiguous option: %s", optstr);
116 return (CMD_RETURN_ERROR);
118 if (oe == NULL) {
119 ctx->error(ctx, "unknown option: %s", optstr);
120 return (CMD_RETURN_ERROR);
123 /* Work out the tree from the table. */
124 if (table == server_options_table)
125 oo = &global_options;
126 else if (table == window_options_table) {
127 if (args_has(self->args, 'g'))
128 oo = &global_w_options;
129 else {
130 wl = cmd_find_window(ctx, args_get(args, 't'), NULL);
131 if (wl == NULL)
132 return (CMD_RETURN_ERROR);
133 oo = &wl->window->options;
135 } else if (table == session_options_table) {
136 if (args_has(self->args, 'g'))
137 oo = &global_s_options;
138 else {
139 s = cmd_find_session(ctx, args_get(args, 't'), 0);
140 if (s == NULL)
141 return (CMD_RETURN_ERROR);
142 oo = &s->options;
144 } else {
145 ctx->error(ctx, "unknown table");
146 return (CMD_RETURN_ERROR);
149 /* Unset or set the option. */
150 if (args_has(args, 'u')) {
151 if (cmd_set_option_unset(self, ctx, oe, oo, valstr) != 0)
152 return (CMD_RETURN_ERROR);
153 } else {
154 if (cmd_set_option_set(self, ctx, oe, oo, valstr) != 0)
155 return (CMD_RETURN_ERROR);
158 /* Start or stop timers when automatic-rename changed. */
159 if (strcmp (oe->name, "automatic-rename") == 0) {
160 for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
161 if ((w = ARRAY_ITEM(&windows, i)) == NULL)
162 continue;
163 if (options_get_number(&w->options, "automatic-rename"))
164 queue_window_name(w);
165 else if (event_initialized(&w->name_timer))
166 evtimer_del(&w->name_timer);
170 /* Update sizes and redraw. May not need it but meh. */
171 recalculate_sizes();
172 for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
173 c = ARRAY_ITEM(&clients, i);
174 if (c != NULL && c->session != NULL)
175 server_redraw_client(c);
178 return (CMD_RETURN_NORMAL);
181 /* Set user option. */
182 enum cmd_retval
183 cmd_set_option_user(struct cmd *self, struct cmd_ctx *ctx, const char* optstr,
184 const char *valstr)
186 struct args *args = self->args;
187 struct session *s;
188 struct winlink *wl;
189 struct options *oo;
191 if (args_has(args, 's'))
192 oo = &global_options;
193 else if (args_has(self->args, 'w') ||
194 self->entry == &cmd_set_window_option_entry) {
195 if (args_has(self->args, 'g'))
196 oo = &global_w_options;
197 else {
198 wl = cmd_find_window(ctx, args_get(args, 't'), NULL);
199 if (wl == NULL)
200 return (CMD_RETURN_ERROR);
201 oo = &wl->window->options;
203 } else {
204 if (args_has(self->args, 'g'))
205 oo = &global_s_options;
206 else {
207 s = cmd_find_session(ctx, args_get(args, 't'), 0);
208 if (s == NULL)
209 return (CMD_RETURN_ERROR);
210 oo = &s->options;
214 if (args_has(args, 'u')) {
215 if (options_find1(oo, optstr) == NULL) {
216 ctx->error(ctx, "unknown option: %s", optstr);
217 return (CMD_RETURN_ERROR);
219 if (valstr != NULL) {
220 ctx->error(ctx, "value passed to unset option: %s",
221 optstr);
222 return (CMD_RETURN_ERROR);
224 options_remove(oo, optstr);
225 } else {
226 if (valstr == NULL) {
227 ctx->error(ctx, "empty value");
228 return (CMD_RETURN_ERROR);
230 options_set_string(oo, optstr, "%s", valstr);
231 if (!args_has(args, 'q'))
232 ctx->info(ctx, "set option: %s -> %s", optstr, valstr);
234 return (CMD_RETURN_NORMAL);
238 /* Unset an option. */
240 cmd_set_option_unset(struct cmd *self, struct cmd_ctx *ctx,
241 const struct options_table_entry *oe, struct options *oo, const char *value)
243 struct args *args = self->args;
245 if (args_has(args, 'g')) {
246 ctx->error(ctx, "can't unset global option: %s", oe->name);
247 return (-1);
249 if (value != NULL) {
250 ctx->error(ctx, "value passed to unset option: %s", oe->name);
251 return (-1);
254 options_remove(oo, oe->name);
255 if (!args_has(args, 'q'))
256 ctx->info(ctx, "unset option: %s", oe->name);
257 return (0);
260 /* Set an option. */
262 cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx,
263 const struct options_table_entry *oe, struct options *oo, const char *value)
265 struct args *args = self->args;
266 struct options_entry *o;
267 const char *s;
269 if (oe->type != OPTIONS_TABLE_FLAG && value == NULL) {
270 ctx->error(ctx, "empty value");
271 return (-1);
274 o = NULL;
275 switch (oe->type) {
276 case OPTIONS_TABLE_STRING:
277 o = cmd_set_option_string(self, ctx, oe, oo, value);
278 break;
279 case OPTIONS_TABLE_NUMBER:
280 o = cmd_set_option_number(self, ctx, oe, oo, value);
281 break;
282 case OPTIONS_TABLE_KEY:
283 o = cmd_set_option_key(self, ctx, oe, oo, value);
284 break;
285 case OPTIONS_TABLE_COLOUR:
286 o = cmd_set_option_colour(self, ctx, oe, oo, value);
287 break;
288 case OPTIONS_TABLE_ATTRIBUTES:
289 o = cmd_set_option_attributes(self, ctx, oe, oo, value);
290 break;
291 case OPTIONS_TABLE_FLAG:
292 o = cmd_set_option_flag(self, ctx, oe, oo, value);
293 break;
294 case OPTIONS_TABLE_CHOICE:
295 o = cmd_set_option_choice(self, ctx, oe, oo, value);
296 break;
298 if (o == NULL)
299 return (-1);
301 s = options_table_print_entry(oe, o, 0);
302 if (!args_has(args, 'q'))
303 ctx->info(ctx, "set option: %s -> %s", oe->name, s);
304 return (0);
307 /* Set a string option. */
308 struct options_entry *
309 cmd_set_option_string(struct cmd *self, unused struct cmd_ctx *ctx,
310 const struct options_table_entry *oe, struct options *oo, const char *value)
312 struct args *args = self->args;
313 struct options_entry *o;
314 char *oldval, *newval;
316 if (args_has(args, 'a')) {
317 oldval = options_get_string(oo, oe->name);
318 xasprintf(&newval, "%s%s", oldval, value);
319 } else
320 newval = xstrdup(value);
322 o = options_set_string(oo, oe->name, "%s", newval);
324 free(newval);
325 return (o);
328 /* Set a number option. */
329 struct options_entry *
330 cmd_set_option_number(unused struct cmd *self, struct cmd_ctx *ctx,
331 const struct options_table_entry *oe, struct options *oo, const char *value)
333 long long ll;
334 const char *errstr;
336 ll = strtonum(value, oe->minimum, oe->maximum, &errstr);
337 if (errstr != NULL) {
338 ctx->error(ctx, "value is %s: %s", errstr, value);
339 return (NULL);
342 return (options_set_number(oo, oe->name, ll));
345 /* Set a key option. */
346 struct options_entry *
347 cmd_set_option_key(unused struct cmd *self, struct cmd_ctx *ctx,
348 const struct options_table_entry *oe, struct options *oo, const char *value)
350 int key;
352 if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
353 ctx->error(ctx, "bad key: %s", value);
354 return (NULL);
357 return (options_set_number(oo, oe->name, key));
360 /* Set a colour option. */
361 struct options_entry *
362 cmd_set_option_colour(unused struct cmd *self, struct cmd_ctx *ctx,
363 const struct options_table_entry *oe, struct options *oo, const char *value)
365 int colour;
367 if ((colour = colour_fromstring(value)) == -1) {
368 ctx->error(ctx, "bad colour: %s", value);
369 return (NULL);
372 return (options_set_number(oo, oe->name, colour));
375 /* Set an attributes option. */
376 struct options_entry *
377 cmd_set_option_attributes(unused struct cmd *self, struct cmd_ctx *ctx,
378 const struct options_table_entry *oe, struct options *oo, const char *value)
380 int attr;
382 if ((attr = attributes_fromstring(value)) == -1) {
383 ctx->error(ctx, "bad attributes: %s", value);
384 return (NULL);
387 return (options_set_number(oo, oe->name, attr));
390 /* Set a flag option. */
391 struct options_entry *
392 cmd_set_option_flag(unused struct cmd *self, struct cmd_ctx *ctx,
393 const struct options_table_entry *oe, struct options *oo, const char *value)
395 int flag;
397 if (value == NULL || *value == '\0')
398 flag = !options_get_number(oo, oe->name);
399 else {
400 if ((value[0] == '1' && value[1] == '\0') ||
401 strcasecmp(value, "on") == 0 ||
402 strcasecmp(value, "yes") == 0)
403 flag = 1;
404 else if ((value[0] == '0' && value[1] == '\0') ||
405 strcasecmp(value, "off") == 0 ||
406 strcasecmp(value, "no") == 0)
407 flag = 0;
408 else {
409 ctx->error(ctx, "bad value: %s", value);
410 return (NULL);
414 return (options_set_number(oo, oe->name, flag));
417 /* Set a choice option. */
418 struct options_entry *
419 cmd_set_option_choice(unused struct cmd *self, struct cmd_ctx *ctx,
420 const struct options_table_entry *oe, struct options *oo, const char *value)
422 const char **choicep;
423 int n, choice = -1;
425 n = 0;
426 for (choicep = oe->choices; *choicep != NULL; choicep++) {
427 n++;
428 if (strncmp(*choicep, value, strlen(value)) != 0)
429 continue;
431 if (choice != -1) {
432 ctx->error(ctx, "ambiguous value: %s", value);
433 return (NULL);
435 choice = n - 1;
437 if (choice == -1) {
438 ctx->error(ctx, "unknown value: %s", value);
439 return (NULL);
442 return (options_set_number(oo, oe->name, choice));