Annotation of src/usr.bin/tmux/cmd-set-option.c, Revision 1.140
1.140 ! nicm 1: /* $OpenBSD: cmd-set-option.c,v 1.139 2021/08/20 19:50:17 nicm Exp $ */
1.1 nicm 2:
3: /*
1.93 nicm 4: * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1 nicm 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: * Set an option.
28: */
29:
1.101 nicm 30: static enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmdq_item *);
1.59 nicm 31:
1.1 nicm 32: const struct cmd_entry cmd_set_option_entry = {
1.91 nicm 33: .name = "set-option",
34: .alias = "set",
35:
1.140 ! nicm 36: .args = { "aFgopqst:uUw", 1, 2, NULL },
1.138 nicm 37: .usage = "[-aFgopqsuUw] " CMD_TARGET_PANE_USAGE " option [value]",
1.91 nicm 38:
1.127 nicm 39: .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
1.92 nicm 40:
1.100 nicm 41: .flags = CMD_AFTERHOOK,
1.91 nicm 42: .exec = cmd_set_option_exec
1.1 nicm 43: };
44:
1.46 nicm 45: const struct cmd_entry cmd_set_window_option_entry = {
1.91 nicm 46: .name = "set-window-option",
47: .alias = "setw",
48:
1.140 ! nicm 49: .args = { "aFgoqt:u", 1, 2, NULL },
1.115 nicm 50: .usage = "[-aFgoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
1.91 nicm 51:
1.114 nicm 52: .target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
1.92 nicm 53:
1.100 nicm 54: .flags = CMD_AFTERHOOK,
1.91 nicm 55: .exec = cmd_set_option_exec
1.46 nicm 56: };
57:
1.125 nicm 58: const struct cmd_entry cmd_set_hook_entry = {
59: .name = "set-hook",
60: .alias = NULL,
61:
1.140 ! nicm 62: .args = { "agpRt:uw", 1, 2, NULL },
1.129 nicm 63: .usage = "[-agpRuw] " CMD_TARGET_PANE_USAGE " hook [command]",
1.125 nicm 64:
1.129 nicm 65: .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
1.125 nicm 66:
67: .flags = CMD_AFTERHOOK,
68: .exec = cmd_set_option_exec
69: };
70:
1.99 nicm 71: static enum cmd_retval
1.101 nicm 72: cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
1.1 nicm 73: {
1.130 nicm 74: struct args *args = cmd_get_args(self);
1.109 nicm 75: int append = args_has(args, 'a');
1.131 nicm 76: struct cmd_find_state *target = cmdq_get_target(item);
1.138 nicm 77: struct window_pane *loop;
1.105 nicm 78: struct options *oo;
1.138 nicm 79: struct options_entry *parent, *o, *po;
1.139 nicm 80: char *name, *argument, *expanded = NULL;
81: char *cause;
82: const char *value;
1.105 nicm 83: int window, idx, already, error, ambiguous;
1.127 nicm 84: int scope;
1.115 nicm 85:
1.130 nicm 86: window = (cmd_get_entry(self) == &cmd_set_window_option_entry);
1.126 nicm 87:
1.115 nicm 88: /* Expand argument. */
1.139 nicm 89: argument = format_single_from_target(item, args_string(args, 0));
1.105 nicm 90:
1.126 nicm 91: /* If set-hook -R, fire the hook straight away. */
1.130 nicm 92: if (cmd_get_entry(self) == &cmd_set_hook_entry && args_has(args, 'R')) {
1.125 nicm 93: notify_hook(item, argument);
1.126 nicm 94: free(argument);
1.125 nicm 95: return (CMD_RETURN_NORMAL);
96: }
97:
1.105 nicm 98: /* Parse option name and index. */
1.115 nicm 99: name = options_match(argument, &idx, &ambiguous);
1.105 nicm 100: if (name == NULL) {
1.106 nicm 101: if (args_has(args, 'q'))
1.115 nicm 102: goto out;
1.105 nicm 103: if (ambiguous)
1.115 nicm 104: cmdq_error(item, "ambiguous option: %s", argument);
1.105 nicm 105: else
1.115 nicm 106: cmdq_error(item, "invalid option: %s", argument);
107: goto fail;
1.50 nicm 108: }
1.139 nicm 109: if (args_count(args) < 2)
1.105 nicm 110: value = NULL;
1.50 nicm 111: else
1.139 nicm 112: value = args_string(args, 1);
113: if (value != NULL && args_has(args, 'F')) {
114: expanded = format_single_from_target(item, value);
115: value = expanded;
116: }
1.50 nicm 117:
1.126 nicm 118: /* Get the scope and table for the option .*/
1.131 nicm 119: scope = options_scope_from_name(args, window, name, target, &oo,
120: &cause);
1.105 nicm 121: if (scope == OPTIONS_TABLE_NONE) {
1.106 nicm 122: if (args_has(args, 'q'))
1.115 nicm 123: goto out;
1.105 nicm 124: cmdq_error(item, "%s", cause);
125: free(cause);
1.113 nicm 126: goto fail;
1.105 nicm 127: }
128: o = options_get_only(oo, name);
129: parent = options_get(oo, name);
130:
131: /* Check that array options and indexes match up. */
1.135 nicm 132: if (idx != -1 && (*name == '@' || !options_is_array(parent))) {
1.122 nicm 133: cmdq_error(item, "not an array: %s", argument);
134: goto fail;
1.105 nicm 135: }
136:
137: /* With -o, check this option is not already set. */
138: if (!args_has(args, 'u') && args_has(args, 'o')) {
139: if (idx == -1)
140: already = (o != NULL);
141: else {
142: if (o == NULL)
143: already = 0;
144: else
145: already = (options_array_get(o, idx) != NULL);
146: }
147: if (already) {
148: if (args_has(args, 'q'))
1.115 nicm 149: goto out;
150: cmdq_error(item, "already set: %s", argument);
1.113 nicm 151: goto fail;
1.105 nicm 152: }
1.1 nicm 153: }
154:
1.105 nicm 155: /* Change the option. */
1.138 nicm 156: if (args_has(args, 'U') && scope == OPTIONS_TABLE_WINDOW) {
157: TAILQ_FOREACH(loop, &target->w->panes, entry) {
158: po = options_get_only(loop->options, name);
159: if (po == NULL)
160: continue;
161: if (options_remove_or_default(po, idx, &cause) != 0) {
162: cmdq_error(item, "%s", cause);
163: free(cause);
164: goto fail;
165: }
166: }
167: }
168: if (args_has(args, 'u') || args_has(args, 'U')) {
1.105 nicm 169: if (o == NULL)
1.118 nicm 170: goto out;
1.137 nicm 171: if (options_remove_or_default(o, idx, &cause) != 0) {
1.125 nicm 172: cmdq_error(item, "%s", cause);
173: free(cause);
174: goto fail;
175: }
1.109 nicm 176: } else if (*name == '@') {
177: if (value == NULL) {
178: cmdq_error(item, "empty value");
1.113 nicm 179: goto fail;
1.109 nicm 180: }
181: options_set_string(oo, name, append, "%s", value);
1.135 nicm 182: } else if (idx == -1 && !options_is_array(parent)) {
183: error = options_from_string(oo, options_table_entry(parent),
184: options_table_entry(parent)->name, value,
185: args_has(args, 'a'), &cause);
186: if (error != 0) {
187: cmdq_error(item, "%s", cause);
188: free(cause);
1.113 nicm 189: goto fail;
1.135 nicm 190: }
1.43 nicm 191: } else {
1.109 nicm 192: if (value == NULL) {
193: cmdq_error(item, "empty value");
1.113 nicm 194: goto fail;
1.109 nicm 195: }
1.105 nicm 196: if (o == NULL)
197: o = options_empty(oo, options_table_entry(parent));
1.110 nicm 198: if (idx == -1) {
199: if (!append)
200: options_array_clear(o);
1.125 nicm 201: if (options_array_assign(o, value, &cause) != 0) {
202: cmdq_error(item, "%s", cause);
203: free(cause);
204: goto fail;
205: }
206: } else if (options_array_set(o, idx, value, append,
207: &cause) != 0) {
208: cmdq_error(item, "%s", cause);
209: free(cause);
1.113 nicm 210: goto fail;
1.61 nicm 211: }
1.55 nicm 212: }
213:
1.135 nicm 214: options_push_changes(name);
1.1 nicm 215:
1.115 nicm 216: out:
217: free(argument);
1.139 nicm 218: free(expanded);
1.113 nicm 219: free(name);
1.57 nicm 220: return (CMD_RETURN_NORMAL);
1.113 nicm 221:
222: fail:
1.115 nicm 223: free(argument);
1.139 nicm 224: free(expanded);
1.113 nicm 225: free(name);
226: return (CMD_RETURN_ERROR);
1.1 nicm 227: }