mirror of
https://github.com/tmux/tmux.git
synced 2026-10-10 20:24:21 +00:00
Add a key to change an array key in customize mode.
This commit is contained in:
@@ -178,10 +178,10 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct window_pane *loop;
|
struct window_pane *loop;
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
struct options_entry *parent, *o, *po;
|
struct options_entry *parent, *o, *po;
|
||||||
char *name, *argument, *expanded = NULL;
|
char *name, *argument, *cause;
|
||||||
char *cause;
|
char *expanded = NULL, *array_key = NULL;
|
||||||
const char *value;
|
const char *value;
|
||||||
int window, idx, already, error, ambiguous;
|
int window, already, error, ambiguous;
|
||||||
int scope;
|
int scope;
|
||||||
|
|
||||||
window = (cmd_get_entry(self) == &cmd_set_window_option_entry);
|
window = (cmd_get_entry(self) == &cmd_set_window_option_entry);
|
||||||
@@ -202,8 +202,8 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse option name and index. */
|
/* Parse option name and array key. */
|
||||||
name = options_match(argument, &idx, &ambiguous);
|
name = options_match(argument, &array_key, &ambiguous);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
if (args_has(args, 'q'))
|
if (args_has(args, 'q'))
|
||||||
goto out;
|
goto out;
|
||||||
@@ -235,21 +235,23 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
o = options_get_only(oo, name);
|
o = options_get_only(oo, name);
|
||||||
parent = options_get(oo, name);
|
parent = options_get(oo, name);
|
||||||
|
|
||||||
/* Check that array options and indexes match up. */
|
/* Check that array options and keys match up. */
|
||||||
if (idx != -1 && (*name == '@' || !options_is_array(parent))) {
|
if (array_key != NULL && (*name == '@' || !options_is_array(parent))) {
|
||||||
cmdq_error(item, "not an array: %s", argument);
|
cmdq_error(item, "not an array: %s", argument);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* With -o, check this option is not already set. */
|
/* With -o, check this option is not already set. */
|
||||||
if (!args_has(args, 'u') && args_has(args, 'o')) {
|
if (!args_has(args, 'u') && args_has(args, 'o')) {
|
||||||
if (idx == -1)
|
if (array_key == NULL)
|
||||||
already = (o != NULL);
|
already = (o != NULL);
|
||||||
else {
|
else {
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
already = 0;
|
already = 0;
|
||||||
|
else if (options_array_get(o, array_key) != NULL)
|
||||||
|
already = 1;
|
||||||
else
|
else
|
||||||
already = (options_array_get(o, idx) != NULL);
|
already = 0;
|
||||||
}
|
}
|
||||||
if (already) {
|
if (already) {
|
||||||
if (args_has(args, 'q'))
|
if (args_has(args, 'q'))
|
||||||
@@ -265,7 +267,8 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
po = options_get_only(loop->options, name);
|
po = options_get_only(loop->options, name);
|
||||||
if (po == NULL)
|
if (po == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (options_remove_or_default(po, idx, &cause) != 0) {
|
if (options_remove_or_default(po, array_key,
|
||||||
|
&cause) != 0) {
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -275,7 +278,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'u') || args_has(args, 'U')) {
|
if (args_has(args, 'u') || args_has(args, 'U')) {
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
if (options_remove_or_default(o, idx, &cause) != 0) {
|
if (options_remove_or_default(o, array_key, &cause) != 0) {
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -286,7 +289,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
options_set_string(oo, name, append, "%s", value);
|
options_set_string(oo, name, append, "%s", value);
|
||||||
} else if (idx == -1 && !options_is_array(parent)) {
|
} else if (array_key == NULL && !options_is_array(parent)) {
|
||||||
error = options_from_string(oo, options_table_entry(parent),
|
error = options_from_string(oo, options_table_entry(parent),
|
||||||
options_table_entry(parent)->name, value,
|
options_table_entry(parent)->name, value,
|
||||||
args_has(args, 'a'), &cause);
|
args_has(args, 'a'), &cause);
|
||||||
@@ -302,7 +305,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
o = options_empty(oo, options_table_entry(parent));
|
o = options_empty(oo, options_table_entry(parent));
|
||||||
if (idx == -1) {
|
if (array_key == NULL) {
|
||||||
if (!append)
|
if (!append)
|
||||||
options_array_clear(o);
|
options_array_clear(o);
|
||||||
if (options_array_assign(o, value, &cause) != 0) {
|
if (options_array_assign(o, value, &cause) != 0) {
|
||||||
@@ -310,7 +313,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
free(cause);
|
free(cause);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
} else if (options_array_set(o, idx, value, append,
|
} else if (options_array_set(o, array_key, value, append,
|
||||||
&cause) != 0) {
|
&cause) != 0) {
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
@@ -324,11 +327,13 @@ out:
|
|||||||
free(argument);
|
free(argument);
|
||||||
free(expanded);
|
free(expanded);
|
||||||
free(name);
|
free(name);
|
||||||
|
free(array_key);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
free(argument);
|
free(argument);
|
||||||
free(expanded);
|
free(expanded);
|
||||||
free(name);
|
free(name);
|
||||||
|
free(array_key);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
33
format.c
33
format.c
@@ -4213,25 +4213,26 @@ format_find(struct format_tree *ft, const char *key, uint64_t modifiers,
|
|||||||
struct format_entry *fe, fe_find;
|
struct format_entry *fe, fe_find;
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
int idx;
|
|
||||||
char *found = NULL, *saved, s[512];
|
char *found = NULL, *saved, s[512];
|
||||||
|
char *array_key = NULL;
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
time_t t = 0;
|
time_t t = 0;
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
|
|
||||||
o = options_parse_get(global_options, key, &idx, 0);
|
o = options_parse_get(global_options, key, &array_key, 0);
|
||||||
if (o == NULL && ft->wp != NULL)
|
if (o == NULL && ft->wp != NULL)
|
||||||
o = options_parse_get(ft->wp->options, key, &idx, 0);
|
o = options_parse_get(ft->wp->options, key, &array_key, 0);
|
||||||
if (o == NULL && ft->w != NULL)
|
if (o == NULL && ft->w != NULL)
|
||||||
o = options_parse_get(ft->w->options, key, &idx, 0);
|
o = options_parse_get(ft->w->options, key, &array_key, 0);
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
o = options_parse_get(global_w_options, key, &idx, 0);
|
o = options_parse_get(global_w_options, key, &array_key, 0);
|
||||||
if (o == NULL && ft->s != NULL)
|
if (o == NULL && ft->s != NULL)
|
||||||
o = options_parse_get(ft->s->options, key, &idx, 0);
|
o = options_parse_get(ft->s->options, key, &array_key, 0);
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
o = options_parse_get(global_s_options, key, &idx, 0);
|
o = options_parse_get(global_s_options, key, &array_key, 0);
|
||||||
if (o != NULL) {
|
if (o != NULL) {
|
||||||
found = options_to_string(o, idx, 1);
|
found = options_to_string(o, array_key, 1);
|
||||||
|
free(array_key);
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4925,7 +4926,7 @@ format_add_window_neighbour(struct format_tree *nft, struct winlink *wl,
|
|||||||
oname = options_name(o);
|
oname = options_name(o);
|
||||||
if (*oname == '@') {
|
if (*oname == '@') {
|
||||||
xasprintf(&prefixed, "%s_%s", prefix, oname);
|
xasprintf(&prefixed, "%s_%s", prefix, oname);
|
||||||
oval = options_to_string(o, -1, 1);
|
oval = options_to_string(o, NULL, 1);
|
||||||
format_add(nft, prefixed, "%s", oval);
|
format_add(nft, prefixed, "%s", oval);
|
||||||
free(oval);
|
free(oval);
|
||||||
free(prefixed);
|
free(prefixed);
|
||||||
@@ -5097,11 +5098,12 @@ format_loop_add_option(struct format_expand_state *es, const char *fmt,
|
|||||||
nft = format_create(ft->client, ft->item, FORMAT_NONE, ft->flags);
|
nft = format_create(ft->client, ft->item, FORMAT_NONE, ft->flags);
|
||||||
|
|
||||||
format_add(nft, "option_name", "%s", name);
|
format_add(nft, "option_name", "%s", name);
|
||||||
s = options_to_string(o, -1, 0);
|
s = options_to_string(o, NULL, 0);
|
||||||
format_add(nft, "option_value", "%s", s);
|
format_add(nft, "option_value", "%s", s);
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
format_add(nft, "option_is_array", "%d", is_array);
|
format_add(nft, "option_is_array", "%d", is_array);
|
||||||
|
format_add(nft, "option_array_key", "%s", "");
|
||||||
format_add(nft, "option_array_index", "%s", "");
|
format_add(nft, "option_array_index", "%s", "");
|
||||||
format_add(nft, "option_array_first", "%d", is_array);
|
format_add(nft, "option_array_first", "%d", is_array);
|
||||||
format_add(nft, "option_array_last", "%d", is_array);
|
format_add(nft, "option_array_last", "%d", is_array);
|
||||||
@@ -5139,20 +5141,21 @@ format_loop_add_array_item(struct format_expand_state *es, const char *fmt,
|
|||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
const struct options_table_entry *oe = options_table_entry(o);
|
const struct options_table_entry *oe = options_table_entry(o);
|
||||||
const char *name = options_name(o);
|
const char *name = options_name(o);
|
||||||
|
const char *array_key;
|
||||||
char *expanded, *s;
|
char *expanded, *s;
|
||||||
u_int idx;
|
|
||||||
|
|
||||||
idx = options_array_item_index(a);
|
array_key = options_array_item_key(a);
|
||||||
format_log(es, "option loop: %s[%u]", name, idx);
|
format_log(es, "option loop: %s[%s]", name, array_key);
|
||||||
nft = format_create(ft->client, ft->item, FORMAT_NONE, ft->flags);
|
nft = format_create(ft->client, ft->item, FORMAT_NONE, ft->flags);
|
||||||
|
|
||||||
format_add(nft, "option_name", "%s", name);
|
format_add(nft, "option_name", "%s", name);
|
||||||
s = options_to_string(o, idx, 0);
|
s = options_to_string(o, array_key, 0);
|
||||||
format_add(nft, "option_value", "%s", s);
|
format_add(nft, "option_value", "%s", s);
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
format_add(nft, "option_is_array", "1");
|
format_add(nft, "option_is_array", "1");
|
||||||
format_add(nft, "option_array_index", "%u", idx);
|
format_add(nft, "option_array_key", "%s", array_key);
|
||||||
|
format_add(nft, "option_array_index", "%s", array_key);
|
||||||
if (a == options_array_first(o))
|
if (a == options_array_first(o))
|
||||||
format_add(nft, "option_array_first", "1");
|
format_add(nft, "option_array_first", "1");
|
||||||
else
|
else
|
||||||
|
|||||||
205
options.c
205
options.c
@@ -32,18 +32,69 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct options_array_item {
|
struct options_array_item {
|
||||||
u_int index;
|
char *key;
|
||||||
union options_value value;
|
union options_value value;
|
||||||
RB_ENTRY(options_array_item) entry;
|
RB_ENTRY(options_array_item) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
options_array_key_to_number(const char *key, u_int *idx)
|
||||||
|
{
|
||||||
|
const char *errstr;
|
||||||
|
long long n;
|
||||||
|
|
||||||
|
if (*key == '\0')
|
||||||
|
return (-1);
|
||||||
|
for (const char *cp = key; *cp != '\0'; cp++) {
|
||||||
|
if (!isdigit((u_char)*cp))
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
n = strtonum(key, 0, UINT_MAX, &errstr);
|
||||||
|
if (errstr != NULL)
|
||||||
|
return (-1);
|
||||||
|
if (idx != NULL)
|
||||||
|
*idx = n;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
options_array_correct_key(const char *key)
|
||||||
|
{
|
||||||
|
u_int idx;
|
||||||
|
int numeric;
|
||||||
|
char *out;
|
||||||
|
|
||||||
|
numeric = options_array_key_to_number(key, &idx);
|
||||||
|
if (numeric == -1)
|
||||||
|
return (NULL);
|
||||||
|
if (numeric == 1) {
|
||||||
|
xasprintf(&out, "%u", idx);
|
||||||
|
return (out);
|
||||||
|
}
|
||||||
|
return (xstrdup(key));
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
options_array_cmp(struct options_array_item *a1, struct options_array_item *a2)
|
options_array_cmp(struct options_array_item *a1, struct options_array_item *a2)
|
||||||
{
|
{
|
||||||
if (a1->index < a2->index)
|
u_int i1, i2;
|
||||||
|
int n1, n2;
|
||||||
|
|
||||||
|
n1 = options_array_key_to_number(a1->key, &i1);
|
||||||
|
n2 = options_array_key_to_number(a2->key, &i2);
|
||||||
|
if (n1 && n2) {
|
||||||
|
if (i1 < i2)
|
||||||
|
return (-1);
|
||||||
|
if (i1 > i2)
|
||||||
|
return (1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (n1)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (a1->index > a2->index)
|
if (n2)
|
||||||
return (1);
|
return (1);
|
||||||
return (0);
|
return (strcmp(a1->key, a2->key));
|
||||||
}
|
}
|
||||||
RB_GENERATE_STATIC(options_array, options_array_item, entry, options_array_cmp);
|
RB_GENERATE_STATIC(options_array, options_array_item, entry, options_array_cmp);
|
||||||
|
|
||||||
@@ -260,6 +311,7 @@ options_default(struct options *oo, const struct options_table_entry *oe)
|
|||||||
{
|
{
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
union options_value *ov;
|
union options_value *ov;
|
||||||
|
char key[32];
|
||||||
u_int i;
|
u_int i;
|
||||||
struct cmd_parse_result *pr;
|
struct cmd_parse_result *pr;
|
||||||
|
|
||||||
@@ -271,8 +323,10 @@ options_default(struct options *oo, const struct options_table_entry *oe)
|
|||||||
options_array_assign(o, oe->default_str, NULL);
|
options_array_assign(o, oe->default_str, NULL);
|
||||||
return (o);
|
return (o);
|
||||||
}
|
}
|
||||||
for (i = 0; oe->default_arr[i] != NULL; i++)
|
for (i = 0; oe->default_arr[i] != NULL; i++) {
|
||||||
options_array_set(o, i, oe->default_arr[i], 0, NULL);
|
xsnprintf(key, sizeof key, "%u", i);
|
||||||
|
options_array_set(o, key, oe->default_arr[i], 0, NULL);
|
||||||
|
}
|
||||||
return (o);
|
return (o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,21 +447,21 @@ options_table_entry(struct options_entry *o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct options_array_item *
|
static struct options_array_item *
|
||||||
options_array_item(struct options_entry *o, u_int idx)
|
options_array_item(struct options_entry *o, const char *key)
|
||||||
{
|
{
|
||||||
struct options_array_item a;
|
struct options_array_item a;
|
||||||
|
|
||||||
a.index = idx;
|
a.key = (char *)key;
|
||||||
return (RB_FIND(options_array, &o->value.array, &a));
|
return (RB_FIND(options_array, &o->value.array, &a));
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct options_array_item *
|
static struct options_array_item *
|
||||||
options_array_new(struct options_entry *o, u_int idx)
|
options_array_new(struct options_entry *o, const char *key)
|
||||||
{
|
{
|
||||||
struct options_array_item *a;
|
struct options_array_item *a;
|
||||||
|
|
||||||
a = xcalloc(1, sizeof *a);
|
a = xcalloc(1, sizeof *a);
|
||||||
a->index = idx;
|
a->key = xstrdup(key);
|
||||||
RB_INSERT(options_array, &o->value.array, a);
|
RB_INSERT(options_array, &o->value.array, a);
|
||||||
return (a);
|
return (a);
|
||||||
}
|
}
|
||||||
@@ -417,6 +471,7 @@ options_array_free(struct options_entry *o, struct options_array_item *a)
|
|||||||
{
|
{
|
||||||
options_value_free(o, &a->value);
|
options_value_free(o, &a->value);
|
||||||
RB_REMOVE(options_array, &o->value.array, a);
|
RB_REMOVE(options_array, &o->value.array, a);
|
||||||
|
free(a->key);
|
||||||
free(a);
|
free(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,24 +488,45 @@ options_array_clear(struct options_entry *o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
union options_value *
|
union options_value *
|
||||||
options_array_get(struct options_entry *o, u_int idx)
|
options_array_get(struct options_entry *o, const char *key)
|
||||||
{
|
{
|
||||||
struct options_array_item *a;
|
struct options_array_item *a;
|
||||||
|
char *new_key;
|
||||||
|
|
||||||
if (!OPTIONS_IS_ARRAY(o))
|
if (!OPTIONS_IS_ARRAY(o))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
a = options_array_item(o, idx);
|
new_key = options_array_correct_key(key);
|
||||||
|
if (new_key == NULL)
|
||||||
|
return (NULL);
|
||||||
|
a = options_array_item(o, new_key);
|
||||||
|
free(new_key);
|
||||||
if (a == NULL)
|
if (a == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
return (&a->value);
|
return (&a->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
union options_value *
|
||||||
|
options_array_getv(struct options_entry *o, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
union options_value *ov;
|
||||||
|
va_list ap;
|
||||||
|
char *key;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
xvasprintf(&key, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
ov = options_array_get(o, key);
|
||||||
|
free(key);
|
||||||
|
return (ov);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
options_array_set(struct options_entry *o, u_int idx, const char *value,
|
options_array_set(struct options_entry *o, const char *key, const char *value,
|
||||||
int append, char **cause)
|
int append, char **cause)
|
||||||
{
|
{
|
||||||
struct options_array_item *a;
|
struct options_array_item *a;
|
||||||
char *new;
|
char *new, *new_key;
|
||||||
struct cmd_parse_result *pr;
|
struct cmd_parse_result *pr;
|
||||||
long long number;
|
long long number;
|
||||||
|
|
||||||
@@ -460,10 +536,18 @@ options_array_set(struct options_entry *o, u_int idx, const char *value,
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_key = options_array_correct_key(key);
|
||||||
|
if (new_key == NULL) {
|
||||||
|
if (cause != NULL)
|
||||||
|
xasprintf(cause, "bad array key: %s", key);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
a = options_array_item(o, idx);
|
a = options_array_item(o, new_key);
|
||||||
if (a != NULL)
|
if (a != NULL)
|
||||||
options_array_free(o, a);
|
options_array_free(o, a);
|
||||||
|
free(new_key);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,50 +559,56 @@ options_array_set(struct options_entry *o, u_int idx, const char *value,
|
|||||||
*cause = pr->error;
|
*cause = pr->error;
|
||||||
else
|
else
|
||||||
free(pr->error);
|
free(pr->error);
|
||||||
|
free(new_key);
|
||||||
return (-1);
|
return (-1);
|
||||||
case CMD_PARSE_SUCCESS:
|
case CMD_PARSE_SUCCESS:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = options_array_item(o, idx);
|
a = options_array_item(o, new_key);
|
||||||
if (a == NULL)
|
if (a == NULL)
|
||||||
a = options_array_new(o, idx);
|
a = options_array_new(o, new_key);
|
||||||
else
|
else
|
||||||
options_value_free(o, &a->value);
|
options_value_free(o, &a->value);
|
||||||
a->value.cmdlist = pr->cmdlist;
|
a->value.cmdlist = pr->cmdlist;
|
||||||
|
free(new_key);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OPTIONS_IS_STRING(o)) {
|
if (OPTIONS_IS_STRING(o)) {
|
||||||
a = options_array_item(o, idx);
|
a = options_array_item(o, new_key);
|
||||||
if (a != NULL && append)
|
if (a != NULL && append)
|
||||||
xasprintf(&new, "%s%s", a->value.string, value);
|
xasprintf(&new, "%s%s", a->value.string, value);
|
||||||
else
|
else
|
||||||
new = xstrdup(value);
|
new = xstrdup(value);
|
||||||
if (a == NULL)
|
if (a == NULL)
|
||||||
a = options_array_new(o, idx);
|
a = options_array_new(o, new_key);
|
||||||
else
|
else
|
||||||
options_value_free(o, &a->value);
|
options_value_free(o, &a->value);
|
||||||
a->value.string = new;
|
a->value.string = new;
|
||||||
|
free(new_key);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o->tableentry->type == OPTIONS_TABLE_COLOUR) {
|
if (o->tableentry->type == OPTIONS_TABLE_COLOUR) {
|
||||||
if ((number = colour_fromstring(value)) == -1) {
|
if ((number = colour_fromstring(value)) == -1) {
|
||||||
xasprintf(cause, "bad colour: %s", value);
|
xasprintf(cause, "bad colour: %s", value);
|
||||||
|
free(new_key);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
a = options_array_item(o, idx);
|
a = options_array_item(o, new_key);
|
||||||
if (a == NULL)
|
if (a == NULL)
|
||||||
a = options_array_new(o, idx);
|
a = options_array_new(o, new_key);
|
||||||
else
|
else
|
||||||
options_value_free(o, &a->value);
|
options_value_free(o, &a->value);
|
||||||
a->value.number = number;
|
a->value.number = number;
|
||||||
|
free(new_key);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cause != NULL)
|
if (cause != NULL)
|
||||||
*cause = xstrdup("wrong array type");
|
*cause = xstrdup("wrong array type");
|
||||||
|
free(new_key);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,6 +617,7 @@ options_array_assign(struct options_entry *o, const char *s, char **cause)
|
|||||||
{
|
{
|
||||||
const char *separator;
|
const char *separator;
|
||||||
char *copy, *next, *string;
|
char *copy, *next, *string;
|
||||||
|
char key[32];
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
separator = o->tableentry->separator;
|
separator = o->tableentry->separator;
|
||||||
@@ -536,10 +627,11 @@ options_array_assign(struct options_entry *o, const char *s, char **cause)
|
|||||||
if (*s == '\0')
|
if (*s == '\0')
|
||||||
return (0);
|
return (0);
|
||||||
for (i = 0; i < UINT_MAX; i++) {
|
for (i = 0; i < UINT_MAX; i++) {
|
||||||
if (options_array_item(o, i) == NULL)
|
if (options_array_getv(o, "%u", i) == NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (options_array_set(o, i, s, 0, cause));
|
xsnprintf(key, sizeof key, "%u", i);
|
||||||
|
return (options_array_set(o, key, s, 0, cause));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*s == '\0')
|
if (*s == '\0')
|
||||||
@@ -549,12 +641,13 @@ options_array_assign(struct options_entry *o, const char *s, char **cause)
|
|||||||
if (*next == '\0')
|
if (*next == '\0')
|
||||||
continue;
|
continue;
|
||||||
for (i = 0; i < UINT_MAX; i++) {
|
for (i = 0; i < UINT_MAX; i++) {
|
||||||
if (options_array_item(o, i) == NULL)
|
if (options_array_getv(o, "%u", i) == NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == UINT_MAX)
|
if (i == UINT_MAX)
|
||||||
break;
|
break;
|
||||||
if (options_array_set(o, i, next, 0, cause) != 0) {
|
xsnprintf(key, sizeof key, "%u", i);
|
||||||
|
if (options_array_set(o, key, next, 0, cause) != 0) {
|
||||||
free(copy);
|
free(copy);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@@ -577,10 +670,10 @@ options_array_next(struct options_array_item *a)
|
|||||||
return (RB_NEXT(options_array, &o->value.array, a));
|
return (RB_NEXT(options_array, &o->value.array, a));
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int
|
const char *
|
||||||
options_array_item_index(struct options_array_item *a)
|
options_array_item_key(struct options_array_item *a)
|
||||||
{
|
{
|
||||||
return (a->index);
|
return (a->key);
|
||||||
}
|
}
|
||||||
|
|
||||||
union options_value *
|
union options_value *
|
||||||
@@ -602,15 +695,16 @@ options_is_string(struct options_entry *o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
options_to_string(struct options_entry *o, int idx, int numeric)
|
options_to_string(struct options_entry *o, const char *key, int numeric)
|
||||||
{
|
{
|
||||||
struct options_array_item *a;
|
struct options_array_item *a;
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
char *last = NULL;
|
char *last = NULL;
|
||||||
char *next;
|
char *next;
|
||||||
|
char *new_key;
|
||||||
|
|
||||||
if (OPTIONS_IS_ARRAY(o)) {
|
if (OPTIONS_IS_ARRAY(o)) {
|
||||||
if (idx == -1) {
|
if (key == NULL) {
|
||||||
RB_FOREACH(a, options_array, &o->value.array) {
|
RB_FOREACH(a, options_array, &o->value.array) {
|
||||||
next = options_value_to_string(o, &a->value,
|
next = options_value_to_string(o, &a->value,
|
||||||
numeric);
|
numeric);
|
||||||
@@ -627,7 +721,11 @@ options_to_string(struct options_entry *o, int idx, int numeric)
|
|||||||
return (xstrdup(""));
|
return (xstrdup(""));
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
a = options_array_item(o, idx);
|
new_key = options_array_correct_key(key);
|
||||||
|
if (new_key == NULL)
|
||||||
|
return (xstrdup(""));
|
||||||
|
a = options_array_item(o, new_key);
|
||||||
|
free(new_key);
|
||||||
if (a == NULL)
|
if (a == NULL)
|
||||||
return (xstrdup(""));
|
return (xstrdup(""));
|
||||||
return (options_value_to_string(o, &a->value, numeric));
|
return (options_value_to_string(o, &a->value, numeric));
|
||||||
@@ -636,37 +734,41 @@ options_to_string(struct options_entry *o, int idx, int numeric)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
options_parse(const char *name, int *idx)
|
options_parse(const char *name, char **key)
|
||||||
{
|
{
|
||||||
char *copy, *cp, *end;
|
char *copy, *cp, *end, *raw, *new_key;
|
||||||
|
|
||||||
if (*name == '\0')
|
if (*name == '\0')
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
*key = NULL;
|
||||||
copy = xstrdup(name);
|
copy = xstrdup(name);
|
||||||
if ((cp = strchr(copy, '[')) == NULL) {
|
if ((cp = strchr(copy, '[')) == NULL) {
|
||||||
*idx = -1;
|
|
||||||
return (copy);
|
return (copy);
|
||||||
}
|
}
|
||||||
end = strchr(cp + 1, ']');
|
end = strchr(cp + 1, ']');
|
||||||
if (end == NULL || end[1] != '\0' || !isdigit((u_char)end[-1])) {
|
if (end == NULL || end[1] != '\0' || end == cp + 1) {
|
||||||
free(copy);
|
free(copy);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
if (sscanf(cp, "[%d]", idx) != 1 || *idx < 0) {
|
raw = xstrndup(cp + 1, end - (cp + 1));
|
||||||
|
new_key = options_array_correct_key(raw);
|
||||||
|
free(raw);
|
||||||
|
if (new_key == NULL) {
|
||||||
free(copy);
|
free(copy);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
*key = new_key;
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
return (copy);
|
return (copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct options_entry *
|
struct options_entry *
|
||||||
options_parse_get(struct options *oo, const char *s, int *idx, int only)
|
options_parse_get(struct options *oo, const char *s, char **key, int only)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
name = options_parse(s, idx);
|
name = options_parse(s, key);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
if (only)
|
if (only)
|
||||||
@@ -674,6 +776,10 @@ options_parse_get(struct options *oo, const char *s, int *idx, int only)
|
|||||||
else
|
else
|
||||||
o = options_get(oo, name);
|
o = options_get(oo, name);
|
||||||
free(name);
|
free(name);
|
||||||
|
if (o == NULL) {
|
||||||
|
free(*key);
|
||||||
|
*key = NULL;
|
||||||
|
}
|
||||||
return (o);
|
return (o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,14 +796,14 @@ options_search(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
options_match(const char *s, int *idx, int *ambiguous)
|
options_match(const char *s, char **key, int *ambiguous)
|
||||||
{
|
{
|
||||||
const struct options_table_entry *oe, *found;
|
const struct options_table_entry *oe, *found;
|
||||||
char *parsed;
|
char *parsed;
|
||||||
const char *name;
|
const char *name;
|
||||||
size_t namelen;
|
size_t namelen;
|
||||||
|
|
||||||
parsed = options_parse(s, idx);
|
parsed = options_parse(s, key);
|
||||||
if (parsed == NULL)
|
if (parsed == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
if (*parsed == '@') {
|
if (*parsed == '@') {
|
||||||
@@ -718,6 +824,8 @@ options_match(const char *s, int *idx, int *ambiguous)
|
|||||||
if (found != NULL) {
|
if (found != NULL) {
|
||||||
*ambiguous = 1;
|
*ambiguous = 1;
|
||||||
free(parsed);
|
free(parsed);
|
||||||
|
free(*key);
|
||||||
|
*key = NULL;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
found = oe;
|
found = oe;
|
||||||
@@ -726,19 +834,21 @@ options_match(const char *s, int *idx, int *ambiguous)
|
|||||||
free(parsed);
|
free(parsed);
|
||||||
if (found == NULL) {
|
if (found == NULL) {
|
||||||
*ambiguous = 0;
|
*ambiguous = 0;
|
||||||
|
free(*key);
|
||||||
|
*key = NULL;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
return (xstrdup(found->name));
|
return (xstrdup(found->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct options_entry *
|
struct options_entry *
|
||||||
options_match_get(struct options *oo, const char *s, int *idx, int only,
|
options_match_get(struct options *oo, const char *s, char **key, int only,
|
||||||
int *ambiguous)
|
int *ambiguous)
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
|
|
||||||
name = options_match(s, idx, ambiguous);
|
name = options_match(s, key, ambiguous);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
*ambiguous = 0;
|
*ambiguous = 0;
|
||||||
@@ -747,6 +857,10 @@ options_match_get(struct options *oo, const char *s, int *idx, int only,
|
|||||||
else
|
else
|
||||||
o = options_get(oo, name);
|
o = options_get(oo, name);
|
||||||
free(name);
|
free(name);
|
||||||
|
if (o == NULL) {
|
||||||
|
free(*key);
|
||||||
|
*key = NULL;
|
||||||
|
}
|
||||||
return (o);
|
return (o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1340,11 +1454,12 @@ options_push_changes(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
options_remove_or_default(struct options_entry *o, int idx, char **cause)
|
options_remove_or_default(struct options_entry *o, const char *key,
|
||||||
|
char **cause)
|
||||||
{
|
{
|
||||||
struct options *oo = o->owner;
|
struct options *oo = o->owner;
|
||||||
|
|
||||||
if (idx == -1) {
|
if (key == NULL) {
|
||||||
if (o->tableentry != NULL &&
|
if (o->tableentry != NULL &&
|
||||||
(oo == global_options ||
|
(oo == global_options ||
|
||||||
oo == global_s_options ||
|
oo == global_s_options ||
|
||||||
@@ -1352,7 +1467,7 @@ options_remove_or_default(struct options_entry *o, int idx, char **cause)
|
|||||||
options_default(oo, o->tableentry);
|
options_default(oo, o->tableentry);
|
||||||
else
|
else
|
||||||
options_remove(o);
|
options_remove(o);
|
||||||
} else if (options_array_set(o, idx, NULL, 0, cause) != 0)
|
} else if (options_array_set(o, key, NULL, 0, cause) != 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,15 +82,15 @@ enum window_customize_change {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct window_customize_itemdata {
|
struct window_customize_itemdata {
|
||||||
struct window_customize_modedata *data;
|
struct window_customize_modedata *data;
|
||||||
enum window_customize_scope scope;
|
enum window_customize_scope scope;
|
||||||
|
|
||||||
char *table;
|
char *table;
|
||||||
key_code key;
|
key_code key;
|
||||||
|
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
char *name;
|
char *name;
|
||||||
int idx;
|
char *array_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct window_customize_modedata {
|
struct window_customize_modedata {
|
||||||
@@ -111,15 +111,17 @@ struct window_customize_modedata {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
window_customize_get_tag(struct options_entry *o, int idx,
|
window_customize_get_tag(struct options_entry *o, struct options_array_item *a,
|
||||||
const struct options_table_entry *oe)
|
const struct options_table_entry *oe)
|
||||||
{
|
{
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
|
|
||||||
|
if (a != NULL)
|
||||||
|
return ((uint64_t)(uintptr_t)a);
|
||||||
if (oe == NULL)
|
if (oe == NULL)
|
||||||
return ((uint64_t)o);
|
return ((uint64_t)o);
|
||||||
offset = ((char *)oe - (char *)options_table) / sizeof *options_table;
|
offset = ((char *)oe - (char *)options_table) / sizeof *options_table;
|
||||||
return ((2ULL << 62)|(offset << 32)|((idx + 1) << 1)|1);
|
return ((2ULL << 62)|(offset << 32)|1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct options *
|
static struct options *
|
||||||
@@ -224,6 +226,7 @@ window_customize_free_item(struct window_customize_itemdata *item)
|
|||||||
{
|
{
|
||||||
free(item->table);
|
free(item->table);
|
||||||
free(item->name);
|
free(item->name);
|
||||||
|
free(item->array_key);
|
||||||
free(item);
|
free(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,26 +240,26 @@ window_customize_build_array(struct window_customize_modedata *data,
|
|||||||
struct window_customize_itemdata *item;
|
struct window_customize_itemdata *item;
|
||||||
struct options_array_item *ai;
|
struct options_array_item *ai;
|
||||||
char *name, *value, *text;
|
char *name, *value, *text;
|
||||||
u_int idx;
|
|
||||||
uint64_t tag;
|
uint64_t tag;
|
||||||
|
const char *array_key;
|
||||||
|
|
||||||
ai = options_array_first(o);
|
ai = options_array_first(o);
|
||||||
while (ai != NULL) {
|
while (ai != NULL) {
|
||||||
idx = options_array_item_index(ai);
|
array_key = options_array_item_key(ai);
|
||||||
|
|
||||||
xasprintf(&name, "%s[%u]", options_name(o), idx);
|
xasprintf(&name, "%s[%s]", options_name(o), array_key);
|
||||||
format_add(ft, "option_name", "%s", name);
|
format_add(ft, "option_name", "%s", name);
|
||||||
value = options_to_string(o, idx, 0);
|
value = options_to_string(o, array_key, 0);
|
||||||
format_add(ft, "option_value", "%s", value);
|
format_add(ft, "option_value", "%s", value);
|
||||||
|
|
||||||
item = window_customize_add_item(data);
|
item = window_customize_add_item(data);
|
||||||
item->scope = scope;
|
item->scope = scope;
|
||||||
item->oo = oo;
|
item->oo = oo;
|
||||||
item->name = xstrdup(options_name(o));
|
item->name = xstrdup(options_name(o));
|
||||||
item->idx = idx;
|
item->array_key = xstrdup(array_key);
|
||||||
|
|
||||||
text = format_expand(ft, data->format);
|
text = format_expand(ft, data->format);
|
||||||
tag = window_customize_get_tag(o, idx, oe);
|
tag = window_customize_get_tag(o, ai, oe);
|
||||||
mode_tree_add(data->data, top, item, tag, name, text, -1);
|
mode_tree_add(data->data, top, item, tag, name, text, -1);
|
||||||
free(text);
|
free(text);
|
||||||
|
|
||||||
@@ -307,7 +310,7 @@ window_customize_build_option(struct window_customize_modedata *data,
|
|||||||
format_add(ft, "option_unit", "%s", "");
|
format_add(ft, "option_unit", "%s", "");
|
||||||
|
|
||||||
if (!array) {
|
if (!array) {
|
||||||
value = options_to_string(o, -1, 0);
|
value = options_to_string(o, NULL, 0);
|
||||||
format_add(ft, "option_value", "%s", value);
|
format_add(ft, "option_value", "%s", value);
|
||||||
free(value);
|
free(value);
|
||||||
}
|
}
|
||||||
@@ -324,13 +327,12 @@ window_customize_build_option(struct window_customize_modedata *data,
|
|||||||
item->oo = oo;
|
item->oo = oo;
|
||||||
item->scope = scope;
|
item->scope = scope;
|
||||||
item->name = xstrdup(name);
|
item->name = xstrdup(name);
|
||||||
item->idx = -1;
|
|
||||||
|
|
||||||
if (array)
|
if (array)
|
||||||
text = NULL;
|
text = NULL;
|
||||||
else
|
else
|
||||||
text = format_expand(ft, data->format);
|
text = format_expand(ft, data->format);
|
||||||
tag = window_customize_get_tag(o, -1, oe);
|
tag = window_customize_get_tag(o, NULL, oe);
|
||||||
top = mode_tree_add(data->data, top, item, tag, name, text, 0);
|
top = mode_tree_add(data->data, top, item, tag, name, text, 0);
|
||||||
free(text);
|
free(text);
|
||||||
|
|
||||||
@@ -483,7 +485,6 @@ window_customize_build_keys(struct window_customize_modedata *data,
|
|||||||
item->table = xstrdup(kt->name);
|
item->table = xstrdup(kt->name);
|
||||||
item->key = bd->key;
|
item->key = bd->key;
|
||||||
item->name = xstrdup(key_string_lookup_key(item->key, 0));
|
item->name = xstrdup(key_string_lookup_key(item->key, 0));
|
||||||
item->idx = -1;
|
|
||||||
|
|
||||||
expanded = format_expand(ft, data->format);
|
expanded = format_expand(ft, data->format);
|
||||||
child = mode_tree_add(data->data, top, item, (uint64_t)bd,
|
child = mode_tree_add(data->data, top, item, (uint64_t)bd,
|
||||||
@@ -653,12 +654,12 @@ window_customize_draw_option(struct window_customize_modedata *data,
|
|||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
u_int cx = s->cx, cy = s->cy;
|
u_int cx = s->cx, cy = s->cy;
|
||||||
int idx;
|
|
||||||
struct options_entry *o, *parent;
|
struct options_entry *o, *parent;
|
||||||
struct options *go, *wo;
|
struct options *go, *wo;
|
||||||
const struct options_table_entry *oe;
|
const struct options_table_entry *oe;
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
const char **choice, *text, *name;
|
const char **choice, *text, *name;
|
||||||
|
const char *array_key;
|
||||||
const char *space = "", *unit = "";
|
const char *space = "", *unit = "";
|
||||||
char *value = NULL, *expanded;
|
char *value = NULL, *expanded;
|
||||||
char *default_value = NULL;
|
char *default_value = NULL;
|
||||||
@@ -669,7 +670,7 @@ window_customize_draw_option(struct window_customize_modedata *data,
|
|||||||
if (!window_customize_check_item(data, item, &fs))
|
if (!window_customize_check_item(data, item, &fs))
|
||||||
return;
|
return;
|
||||||
name = item->name;
|
name = item->name;
|
||||||
idx = item->idx;
|
array_key = item->array_key;
|
||||||
|
|
||||||
o = options_get(item->oo, name);
|
o = options_get(item->oo, name);
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
@@ -708,25 +709,25 @@ window_customize_draw_option(struct window_customize_modedata *data,
|
|||||||
&grid_default_cell, "This is a %s option.", text))
|
&grid_default_cell, "This is a %s option.", text))
|
||||||
goto out;
|
goto out;
|
||||||
if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
|
if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
|
||||||
if (idx != -1) {
|
if (array_key != NULL) {
|
||||||
if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
|
if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
|
||||||
0, &grid_default_cell,
|
0, &grid_default_cell,
|
||||||
"This is an array option, index %u.", idx))
|
"This is an array option, key %s.", array_key))
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
|
if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
|
||||||
0, &grid_default_cell, "This is an array option."))
|
0, &grid_default_cell, "This is an array option."))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (idx == -1)
|
if (array_key == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
|
screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
|
||||||
if (s->cy >= cy + sy - 1)
|
if (s->cy >= cy + sy - 1)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
value = options_to_string(o, idx, 0);
|
value = options_to_string(o, array_key, 0);
|
||||||
if (oe != NULL && idx == -1) {
|
if (oe != NULL && array_key == NULL) {
|
||||||
default_value = options_default_to_string(oe);
|
default_value = options_default_to_string(oe);
|
||||||
if (strcmp(default_value, value) == 0) {
|
if (strcmp(default_value, value) == 0) {
|
||||||
free(default_value);
|
free(default_value);
|
||||||
@@ -820,7 +821,7 @@ window_customize_draw_option(struct window_customize_modedata *data,
|
|||||||
if (wo != NULL && options_owner(o) != wo) {
|
if (wo != NULL && options_owner(o) != wo) {
|
||||||
parent = options_get_only(wo, name);
|
parent = options_get_only(wo, name);
|
||||||
if (parent != NULL) {
|
if (parent != NULL) {
|
||||||
value = options_to_string(parent, -1 , 0);
|
value = options_to_string(parent, NULL, 0);
|
||||||
if (!screen_write_text(ctx, s->cx, sx,
|
if (!screen_write_text(ctx, s->cx, sx,
|
||||||
sy - (s->cy - cy), 0, &grid_default_cell,
|
sy - (s->cy - cy), 0, &grid_default_cell,
|
||||||
"Window value (from window %u): %s%s%s", fs.wl->idx,
|
"Window value (from window %u): %s%s%s", fs.wl->idx,
|
||||||
@@ -831,7 +832,7 @@ window_customize_draw_option(struct window_customize_modedata *data,
|
|||||||
if (go != NULL && options_owner(o) != go) {
|
if (go != NULL && options_owner(o) != go) {
|
||||||
parent = options_get_only(go, name);
|
parent = options_get_only(go, name);
|
||||||
if (parent != NULL) {
|
if (parent != NULL) {
|
||||||
value = options_to_string(parent, -1 , 0);
|
value = options_to_string(parent, NULL, 0);
|
||||||
if (!screen_write_text(ctx, s->cx, sx,
|
if (!screen_write_text(ctx, s->cx, sx,
|
||||||
sy - (s->cy - cy), 0, &grid_default_cell,
|
sy - (s->cy - cy), 0, &grid_default_cell,
|
||||||
"Global value: %s%s%s", value, space, unit))
|
"Global value: %s%s%s", value, space, unit))
|
||||||
@@ -896,6 +897,8 @@ static const char* window_customize_help_lines[] = {
|
|||||||
"#[fg=themelightgrey]"
|
"#[fg=themelightgrey]"
|
||||||
" U #[#{E:tree-mode-border-style},acs]x#[default] Unset tagged %1s",
|
" U #[#{E:tree-mode-border-style},acs]x#[default] Unset tagged %1s",
|
||||||
"#[fg=themelightgrey]"
|
"#[fg=themelightgrey]"
|
||||||
|
" a #[#{E:tree-mode-border-style},acs]x#[default] Change array key",
|
||||||
|
"#[fg=themelightgrey]"
|
||||||
" f #[#{E:tree-mode-border-style},acs]x#[default] Enter a filter",
|
" f #[#{E:tree-mode-border-style},acs]x#[default] Enter a filter",
|
||||||
"#[fg=themelightgrey]"
|
"#[fg=themelightgrey]"
|
||||||
" v #[#{E:tree-mode-border-style},acs]x#[default] Toggle information",
|
" v #[#{E:tree-mode-border-style},acs]x#[default] Toggle information",
|
||||||
@@ -1007,8 +1010,10 @@ window_customize_set_option_callback(struct client *c, void *itemdata,
|
|||||||
const struct options_table_entry *oe;
|
const struct options_table_entry *oe;
|
||||||
struct options *oo = item->oo;
|
struct options *oo = item->oo;
|
||||||
const char *name = item->name;
|
const char *name = item->name;
|
||||||
|
const char *array_key = item->array_key;
|
||||||
char *cause;
|
char *cause;
|
||||||
int idx = item->idx;
|
u_int idx;
|
||||||
|
char keybuf[32];
|
||||||
|
|
||||||
if (s == NULL || *s == '\0' || data->dead)
|
if (s == NULL || *s == '\0' || data->dead)
|
||||||
return (PROMPT_CLOSE);
|
return (PROMPT_CLOSE);
|
||||||
@@ -1020,13 +1025,15 @@ window_customize_set_option_callback(struct client *c, void *itemdata,
|
|||||||
oe = options_table_entry(o);
|
oe = options_table_entry(o);
|
||||||
|
|
||||||
if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
|
if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
|
||||||
if (idx == -1) {
|
if (array_key == NULL) {
|
||||||
for (idx = 0; idx < INT_MAX; idx++) {
|
for (idx = 0; idx < INT_MAX; idx++) {
|
||||||
if (options_array_get(o, idx) == NULL)
|
if (options_array_getv(o, "%u", idx) == NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
xsnprintf(keybuf, sizeof keybuf, "%u", idx);
|
||||||
|
array_key = keybuf;
|
||||||
}
|
}
|
||||||
if (options_array_set(o, idx, s, 0, &cause) != 0)
|
if (options_array_set(o, array_key, s, 0, &cause) != 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
} else {
|
} else {
|
||||||
if (options_from_string(oo, oe, name, s, 0, &cause) != 0)
|
if (options_from_string(oo, oe, name, s, 0, &cause) != 0)
|
||||||
@@ -1056,10 +1063,11 @@ window_customize_set_option(struct client *c,
|
|||||||
const struct options_table_entry *oe;
|
const struct options_table_entry *oe;
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
struct window_customize_itemdata *new_item;
|
struct window_customize_itemdata *new_item;
|
||||||
int flag, idx = item->idx;
|
int flag;
|
||||||
enum window_customize_scope scope = WINDOW_CUSTOMIZE_NONE;
|
enum window_customize_scope scope = WINDOW_CUSTOMIZE_NONE;
|
||||||
u_int choice;
|
u_int choice;
|
||||||
const char *name = item->name, *space = "";
|
const char *name = item->name, *space = "";
|
||||||
|
const char *array_key = item->array_key;
|
||||||
char *prompt, *value, *text;
|
char *prompt, *value, *text;
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
|
|
||||||
@@ -1142,25 +1150,26 @@ window_customize_set_option(struct client *c,
|
|||||||
else if (scope != WINDOW_CUSTOMIZE_SERVER)
|
else if (scope != WINDOW_CUSTOMIZE_SERVER)
|
||||||
space = ", global";
|
space = ", global";
|
||||||
if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
|
if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
|
||||||
if (idx == -1) {
|
if (array_key == NULL) {
|
||||||
xasprintf(&prompt, "(%s[+]%s%s) ", name, space,
|
xasprintf(&prompt, "(%s[+]%s%s) ", name, space,
|
||||||
text);
|
text);
|
||||||
} else {
|
} else {
|
||||||
xasprintf(&prompt, "(%s[%d]%s%s) ", name, idx,
|
xasprintf(&prompt, "(%s[%s]%s%s) ", name,
|
||||||
space, text);
|
array_key, space, text);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
xasprintf(&prompt, "(%s%s%s) ", name, space, text);
|
xasprintf(&prompt, "(%s%s%s) ", name, space, text);
|
||||||
free(text);
|
free(text);
|
||||||
|
|
||||||
value = options_to_string(o, idx, 0);
|
value = options_to_string(o, array_key, 0);
|
||||||
|
|
||||||
new_item = xcalloc(1, sizeof *new_item);
|
new_item = xcalloc(1, sizeof *new_item);
|
||||||
new_item->data = data;
|
new_item->data = data;
|
||||||
new_item->scope = scope;
|
new_item->scope = scope;
|
||||||
new_item->oo = oo;
|
new_item->oo = oo;
|
||||||
new_item->name = xstrdup(name);
|
new_item->name = xstrdup(name);
|
||||||
new_item->idx = idx;
|
if (array_key != NULL)
|
||||||
|
new_item->array_key = xstrdup(array_key);
|
||||||
|
|
||||||
data->references++;
|
data->references++;
|
||||||
mode_tree_set_prompt(data->data, c, prompt, value,
|
mode_tree_set_prompt(data->data, c, prompt, value,
|
||||||
@@ -1173,6 +1182,84 @@ window_customize_set_option(struct client *c,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum prompt_result
|
||||||
|
window_customize_set_array_key_callback(struct client *c, void *itemdata,
|
||||||
|
const char *s, __unused enum prompt_key_result key)
|
||||||
|
{
|
||||||
|
struct window_customize_itemdata *item = itemdata;
|
||||||
|
struct window_customize_modedata *data;
|
||||||
|
struct options_entry *o;
|
||||||
|
const char *name, *array_key;
|
||||||
|
char *value, *cause;
|
||||||
|
|
||||||
|
if (item == NULL)
|
||||||
|
return (PROMPT_CLOSE);
|
||||||
|
data = item->data;
|
||||||
|
if (s == NULL || *s == '\0' || data->dead)
|
||||||
|
return (PROMPT_CLOSE);
|
||||||
|
name = item->name;
|
||||||
|
array_key = item->array_key;
|
||||||
|
if (array_key == NULL || !window_customize_check_item(data, item, NULL))
|
||||||
|
return (PROMPT_CLOSE);
|
||||||
|
|
||||||
|
o = options_get(item->oo, name);
|
||||||
|
if (o == NULL)
|
||||||
|
return (PROMPT_CLOSE);
|
||||||
|
if (options_array_get(o, s) != NULL)
|
||||||
|
return (PROMPT_CLOSE);
|
||||||
|
|
||||||
|
value = options_to_string(o, array_key, 0);
|
||||||
|
if (options_array_set(o, s, value, 0, &cause) != 0)
|
||||||
|
goto fail;
|
||||||
|
free(value);
|
||||||
|
|
||||||
|
options_array_set(o, array_key, NULL, 0, NULL);
|
||||||
|
options_push_changes(item->name);
|
||||||
|
mode_tree_build(data->data);
|
||||||
|
mode_tree_draw(data->data);
|
||||||
|
data->wp->flags |= PANE_REDRAW;
|
||||||
|
|
||||||
|
return (PROMPT_CLOSE);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(value);
|
||||||
|
*cause = toupper((u_char)*cause);
|
||||||
|
status_message_set(c, -1, 1, 0, 0, "%s", cause);
|
||||||
|
free(cause);
|
||||||
|
return (PROMPT_CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_customize_set_array_key(struct client *c,
|
||||||
|
struct window_customize_modedata *data,
|
||||||
|
struct window_customize_itemdata *item)
|
||||||
|
{
|
||||||
|
struct window_customize_itemdata *new_item;
|
||||||
|
char *prompt;
|
||||||
|
|
||||||
|
if (item == NULL ||
|
||||||
|
item->array_key == NULL ||
|
||||||
|
!window_customize_check_item(data, item, NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
xasprintf(&prompt, "(%s[%s]) ", item->name, item->array_key);
|
||||||
|
|
||||||
|
new_item = xcalloc(1, sizeof *new_item);
|
||||||
|
new_item->data = data;
|
||||||
|
new_item->scope = item->scope;
|
||||||
|
new_item->oo = item->oo;
|
||||||
|
new_item->name = xstrdup(item->name);
|
||||||
|
new_item->array_key = xstrdup(item->array_key);
|
||||||
|
|
||||||
|
data->references++;
|
||||||
|
mode_tree_set_prompt(data->data, c, prompt, item->array_key,
|
||||||
|
PROMPT_TYPE_COMMAND, PROMPT_NOFORMAT,
|
||||||
|
window_customize_set_array_key_callback,
|
||||||
|
window_customize_free_item_callback, new_item);
|
||||||
|
|
||||||
|
free(prompt);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_customize_unset_option(struct window_customize_modedata *data,
|
window_customize_unset_option(struct window_customize_modedata *data,
|
||||||
struct window_customize_itemdata *item)
|
struct window_customize_itemdata *item)
|
||||||
@@ -1185,9 +1272,10 @@ window_customize_unset_option(struct window_customize_modedata *data,
|
|||||||
o = options_get(item->oo, item->name);
|
o = options_get(item->oo, item->name);
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
return;
|
return;
|
||||||
if (item->idx != -1 && item == mode_tree_get_current(data->data))
|
if (item->array_key != NULL &&
|
||||||
|
item == mode_tree_get_current(data->data))
|
||||||
mode_tree_up(data->data, 0);
|
mode_tree_up(data->data, 0);
|
||||||
options_remove_or_default(o, item->idx, NULL);
|
options_remove_or_default(o, item->array_key, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1199,14 +1287,14 @@ window_customize_reset_option(struct window_customize_modedata *data,
|
|||||||
|
|
||||||
if (item == NULL || !window_customize_check_item(data, item, NULL))
|
if (item == NULL || !window_customize_check_item(data, item, NULL))
|
||||||
return;
|
return;
|
||||||
if (item->idx != -1)
|
if (item->array_key != NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
oo = item->oo;
|
oo = item->oo;
|
||||||
while (oo != NULL) {
|
while (oo != NULL) {
|
||||||
o = options_get_only(item->oo, item->name);
|
o = options_get_only(item->oo, item->name);
|
||||||
if (o != NULL)
|
if (o != NULL)
|
||||||
options_remove_or_default(o, -1, NULL);
|
options_remove_or_default(o, NULL, NULL);
|
||||||
oo = options_get_parent(oo);
|
oo = options_get_parent(oo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1452,7 +1540,7 @@ window_customize_key(struct window_mode_entry *wme, struct client *c,
|
|||||||
struct window_pane *wp = wme->wp;
|
struct window_pane *wp = wme->wp;
|
||||||
struct window_customize_modedata *data = wme->data;
|
struct window_customize_modedata *data = wme->data;
|
||||||
struct window_customize_itemdata *item, *new_item;
|
struct window_customize_itemdata *item, *new_item;
|
||||||
int finished, idx;
|
int finished;
|
||||||
char *prompt;
|
char *prompt;
|
||||||
u_int tagged;
|
u_int tagged;
|
||||||
|
|
||||||
@@ -1462,6 +1550,11 @@ window_customize_key(struct window_mode_entry *wme, struct client *c,
|
|||||||
item = new_item;
|
item = new_item;
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
case 'a':
|
||||||
|
if (item == NULL || item->scope == WINDOW_CUSTOMIZE_KEY)
|
||||||
|
break;
|
||||||
|
window_customize_set_array_key(c, data, item);
|
||||||
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
case 's':
|
case 's':
|
||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
@@ -1490,7 +1583,7 @@ window_customize_key(struct window_mode_entry *wme, struct client *c,
|
|||||||
mode_tree_build(data->data);
|
mode_tree_build(data->data);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
if (item == NULL || item->idx != -1)
|
if (item == NULL || item->array_key != NULL)
|
||||||
break;
|
break;
|
||||||
xasprintf(&prompt, "Reset %s to default? ", item->name);
|
xasprintf(&prompt, "Reset %s to default? ", item->name);
|
||||||
data->references++;
|
data->references++;
|
||||||
@@ -1519,10 +1612,10 @@ window_customize_key(struct window_mode_entry *wme, struct client *c,
|
|||||||
case 'u':
|
case 'u':
|
||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
break;
|
break;
|
||||||
idx = item->idx;
|
if (item->array_key != NULL) {
|
||||||
if (idx != -1)
|
xasprintf(&prompt, "Unset %s[%s]? ", item->name,
|
||||||
xasprintf(&prompt, "Unset %s[%d]? ", item->name, idx);
|
item->array_key);
|
||||||
else
|
} else
|
||||||
xasprintf(&prompt, "Unset %s? ", item->name);
|
xasprintf(&prompt, "Unset %s? ", item->name);
|
||||||
data->references++;
|
data->references++;
|
||||||
data->change = WINDOW_CUSTOMIZE_UNSET;
|
data->change = WINDOW_CUSTOMIZE_UNSET;
|
||||||
|
|||||||
Reference in New Issue
Block a user