diff --git a/cmd-set-option.c b/cmd-set-option.c index ef2ce10b..84c12e56 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -160,11 +160,17 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) cmdq_error(item, "not an array: %s", args->argv[0]); return (CMD_RETURN_ERROR); } - } else { - if (*name != '@' && options_array_size(parent, NULL) != -1) { - cmdq_error(item, "is an array: %s", args->argv[0]); - return (CMD_RETURN_ERROR); + } else if (*name != '@' && options_array_size(parent, NULL) != -1) { + if (value == NULL) { + cmdq_error(item, "empty value"); + return (-1); } + if (o == NULL) + o = options_empty(oo, options_table_entry(parent)); + if (!args_has(args, 'a')) + options_array_clear(o); + options_array_assign(o, value); + return (CMD_RETURN_NORMAL); } /* With -o, check this option is not already set. */ @@ -197,7 +203,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) else options_remove(o); } else - options_array_set(o, idx, NULL); + options_array_set(o, idx, NULL, 0); } else if (*name == '@') options_set_string(oo, name, args_has(args, 'a'), "%s", value); else if (idx == -1) { @@ -207,7 +213,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) } else { if (o == NULL) o = options_empty(oo, options_table_entry(parent)); - if (options_array_set(o, idx, value) != 0) { + if (options_array_set(o, idx, value, 1) != 0) { cmdq_error(item, "invalid index: %s", args->argv[0]); return (CMD_RETURN_ERROR); } diff --git a/cmd-show-options.c b/cmd-show-options.c index f7df2b11..b9882243 100644 --- a/cmd-show-options.c +++ b/cmd-show-options.c @@ -92,11 +92,20 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item, const char *name; const char *value; char *tmp, *escaped; + u_int size, i; if (idx != -1) { xasprintf(&tmp, "%s[%d]", options_name(o), idx); name = tmp; } else { + if (options_array_size(o, &size) != -1) { + for (i = 0; i < size; i++) { + if (options_array_get(o, i) == NULL) + continue; + cmd_show_options_print(self, item, o, i); + } + return; + } tmp = NULL; name = options_name(o); } diff --git a/options.c b/options.c index 4f6aa6fe..37263b53 100644 --- a/options.c +++ b/options.c @@ -170,22 +170,11 @@ struct options_entry * options_default(struct options *oo, const struct options_table_entry *oe) { struct options_entry *o; - char *cp, *copy, *next; - u_int idx = 0; o = options_empty(oo, oe); - - if (oe->type == OPTIONS_TABLE_ARRAY) { - copy = cp = xstrdup(oe->default_str); - while ((next = strsep(&cp, ",")) != NULL) { - options_array_set(o, idx, next); - idx++; - } - free(copy); - return (o); - } - - if (oe->type == OPTIONS_TABLE_STRING) + if (oe->type == OPTIONS_TABLE_ARRAY) + options_array_assign(o, oe->default_str); + else if (oe->type == OPTIONS_TABLE_STRING) o->string = xstrdup(oe->default_str); else if (oe->type == OPTIONS_TABLE_STYLE) { memcpy(&o->style, &grid_default_cell, sizeof o->style); @@ -242,6 +231,13 @@ options_table_entry(struct options_entry *o) return (o->tableentry); } +void +options_array_clear(struct options_entry *o) +{ + if (OPTIONS_IS_ARRAY(o)) + o->arraysize = 0; +} + const char * options_array_get(struct options_entry *o, u_int idx) { @@ -253,9 +249,11 @@ options_array_get(struct options_entry *o, u_int idx) } int -options_array_set(struct options_entry *o, u_int idx, const char *value) +options_array_set(struct options_entry *o, u_int idx, const char *value, + int append) { - u_int i; + char *new; + u_int i; if (!OPTIONS_IS_ARRAY(o)) return (-1); @@ -268,12 +266,17 @@ options_array_set(struct options_entry *o, u_int idx, const char *value) o->array[i] = NULL; o->arraysize = idx + 1; } - if (o->array[idx] != NULL) - free((void *)o->array[idx]); - if (value != NULL) - o->array[idx] = xstrdup(value); - else - o->array[idx] = NULL; + + new = NULL; + if (value != NULL) { + if (o->array[idx] != NULL && append) + xasprintf(&new, "%s%s", o->array[idx], value); + else + new = xstrdup(value); + } + + free((void *)o->array[idx]); + o->array[idx] = new; return (0); } @@ -287,6 +290,32 @@ options_array_size(struct options_entry *o, u_int *size) return (0); } +void +options_array_assign(struct options_entry *o, const char *s) +{ + const char *separator; + char *copy, *next, *string; + u_int i; + + separator = o->tableentry->separator; + if (separator == NULL) + separator = " ,"; + + copy = string = xstrdup(s); + while ((next = strsep(&string, separator)) != NULL) { + if (*next == '\0') + continue; + for (i = 0; i < OPTIONS_ARRAY_LIMIT; i++) { + if (i >= o->arraysize || o->array[i] == NULL) + break; + } + if (i == OPTIONS_ARRAY_LIMIT) + break; + options_array_set(o, i, next, 0); + } + free(copy); +} + int options_isstring(struct options_entry *o) { @@ -384,12 +413,6 @@ options_parse_get(struct options *oo, const char *s, int *idx, int only) else o = options_get(oo, name); free(name); - if (o != NULL) { - if (OPTIONS_IS_ARRAY(o) && *idx == -1) - return (NULL); - if (!OPTIONS_IS_ARRAY(o) && *idx != -1) - return (NULL); - } return (o); } @@ -447,12 +470,6 @@ options_match_get(struct options *oo, const char *s, int *idx, int only, else o = options_get(oo, name); free(name); - if (o != NULL) { - if (OPTIONS_IS_ARRAY(o) && *idx == -1) - return (NULL); - if (!OPTIONS_IS_ARRAY(o) && *idx != -1) - return (NULL); - } return (o); } diff --git a/tmux.h b/tmux.h index 2a26f10f..58fe992b 100644 --- a/tmux.h +++ b/tmux.h @@ -1479,6 +1479,7 @@ struct options_table_entry { const char *default_str; long long default_num; + const char *separator; const char *style; }; @@ -1616,17 +1617,20 @@ const struct options_table_entry *options_table_entry(struct options_entry *); struct options_entry *options_get_only(struct options *, const char *); struct options_entry *options_get(struct options *, const char *); void options_remove(struct options_entry *); +void options_array_clear(struct options_entry *); const char *options_array_get(struct options_entry *, u_int); -int options_array_set(struct options_entry *, u_int, const char *); +int options_array_set(struct options_entry *, u_int, const char *, + int); int options_array_size(struct options_entry *, u_int *); +void options_array_assign(struct options_entry *, const char *); int options_isstring(struct options_entry *); const char *options_tostring(struct options_entry *, int); char *options_parse(const char *, int *); struct options_entry *options_parse_get(struct options *, const char *, int *, - int); + int); char *options_match(const char *, int *, int *); struct options_entry *options_match_get(struct options *, const char *, int *, - int, int *); + int, int *); const char *options_get_string(struct options *, const char *); long long options_get_number(struct options *, const char *); const struct grid_cell *options_get_style(struct options *, const char *);