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