degesch: implement -=/+= for multiple values

It didn't make sense to have these unimplemented,
though perhaps += shouldn't enforce a set.

Sadly, autocomplete is fairly difficult for -= of multiple items.
This commit is contained in:
Přemysl Eric Janouch 2021-06-14 08:33:59 +02:00
parent 80c1e8f8eb
commit e3c47c33fa
Signed by: p
GPG Key ID: A0420B94F92B9493
2 changed files with 40 additions and 42 deletions

2
NEWS
View File

@ -11,6 +11,8 @@
* degesch: /deop and /devoice without arguments will use the client's user
* degesch: /set +=/-= now treats its argument as a string array
* censor.lua: now stripping colours from censored messages;
their attributes are also configurable rather than always black on black

View File

@ -11053,45 +11053,38 @@ handle_command_buffer (struct handler_args *a)
return result;
}
static bool
replace_string_array
(struct config_item *item, struct strv *array, struct error **e)
{
char *changed = strv_join (array, ",");
struct str tmp = { .str = changed, .len = strlen (changed) };
bool result = config_item_set_from (item,
config_item_string_array (&tmp), e);
free (changed);
return result;
}
static bool
handle_command_set_add
(struct config_item *item, const char *value, struct error **e)
(struct strv *items, const struct strv *values, struct error **e)
{
struct strv items = strv_make ();
if (item->type != CONFIG_ITEM_NULL)
cstr_split (item->value.string.str, ",", false, &items);
if (items.len == 1 && !*items.vector[0])
strv_reset (&items);
// FIXME: handle multiple items properly
bool result = false;
if (strv_find (&items, value) != -1)
error_set (e, "already present in the array: %s", value);
else
for (size_t i = 0; i < values->len; i++)
{
strv_append (&items, value);
result = replace_string_array (item, &items, e);
const char *value = values->vector[i];
if (strv_find (items, values->vector[i]) != -1)
return error_set (e, "already present in the array: %s", value);
strv_append (items, value);
}
strv_free (&items);
return result;
return true;
}
static bool
handle_command_set_remove
(struct config_item *item, const char *value, struct error **e)
(struct strv *items, const struct strv *values, struct error **e)
{
for (size_t i = 0; i < values->len; i++)
{
const char *value = values->vector[i];
ssize_t i = strv_find (items, value);
if (i == -1)
return error_set (e, "not present in the array: %s", value);
strv_remove (items, i);
}
return true;
}
static bool
handle_command_set_modify
(struct config_item *item, const char *value, bool add, struct error **e)
{
struct strv items = strv_make ();
if (item->type != CONFIG_ITEM_NULL)
@ -11099,18 +11092,23 @@ handle_command_set_remove
if (items.len == 1 && !*items.vector[0])
strv_reset (&items);
// FIXME: handle multiple items properly
bool result = false;
ssize_t i = strv_find (&items, value);
if (i == -1)
error_set (e, "not present in the array: %s", value);
else
struct strv values = strv_make ();
cstr_split (value, ",", false, &values);
bool result = add
? handle_command_set_add (&items, &values, e)
: handle_command_set_remove (&items, &values, e);
if (result)
{
strv_remove (&items, i);
result = replace_string_array (item, &items, e);
char *changed = strv_join (&items, ",");
struct str tmp = { .str = changed, .len = strlen (changed) };
result = config_item_set_from (item,
config_item_string_array (&tmp), e);
free (changed);
}
strv_free (&items);
strv_free (&values);
return result;
}
@ -11129,10 +11127,8 @@ handle_command_set_assign_item (struct app_context *ctx,
config_item_set_from (item, config_item_clone (new_), &e);
else if (item->schema->type != CONFIG_ITEM_STRING_ARRAY)
error_set (&e, "not a string array");
else if (add)
handle_command_set_add (item, new_->value.string.str, &e);
else if (remove)
handle_command_set_remove (item, new_->value.string.str, &e);
else
handle_command_set_modify (item, new_->value.string.str, add, &e);
if (e)
{