Add support for removing from options
`set -remove ...` will remove from the current option value, substracting from int, removing elements from vectors and maps.
This commit is contained in:
parent
6f260c2ab2
commit
ec3d7c3104
|
@ -3,6 +3,10 @@
|
|||
This changelog contains major and/or breaking changes to Kakoune between
|
||||
released versions.
|
||||
|
||||
== Development version
|
||||
|
||||
* `set-option -remove` support for substracting/removing from option values
|
||||
|
||||
== Kakoune 2020.09.01
|
||||
|
||||
* The `repl` and `send-text` aliases have been renamed respectively into
|
||||
|
|
|
@ -10,7 +10,7 @@ scripts.
|
|||
Options can be modified using the `set-option` command:
|
||||
|
||||
--------------------------------------------
|
||||
set-option [-add] <scope> <name> <values>...
|
||||
set-option [-add|-remove] <scope> <name> <values>...
|
||||
--------------------------------------------
|
||||
|
||||
<scope> can be *global*, *buffer*, *window* or *current* (See
|
||||
|
@ -20,8 +20,9 @@ which the option is already set.
|
|||
Multiple <values> can be given as separate arguments when the option is a
|
||||
list or map.
|
||||
|
||||
If `-add` is specified, the new value is *added* to the current one
|
||||
instead of replacing it (the exact outcome depends on the type, see below).
|
||||
If `-add` or `-remove` is specified, the new value is respectively *added*
|
||||
to or *removed* from the current one instead of replacing it (the exact
|
||||
outcome depends on the type, see below).
|
||||
|
||||
[[unset-option]]
|
||||
Options values can be unset in a specific scope with the `unset-option`
|
||||
|
@ -63,7 +64,9 @@ are exclusively available to built-in options.
|
|||
|
||||
*int*::
|
||||
an integer number.
|
||||
`set -add` performs a math addition
|
||||
|
||||
`set -add` performs a math addition. +
|
||||
`set -remove` performs a math substraction. +
|
||||
|
||||
*bool*::
|
||||
a boolean value, yes/true or no/false
|
||||
|
@ -81,7 +84,10 @@ are exclusively available to built-in options.
|
|||
|
||||
*<type>-list*::
|
||||
a list, elements are specified as separate arguments to the command.
|
||||
`set -add` appends the new element to the list
|
||||
|
||||
`set -add` appends the new element to the list. +
|
||||
`set -remove` removes each given element from the list. +
|
||||
|
||||
Only `int-list` and `str-list` options can be created with
|
||||
`declare-option`.
|
||||
|
||||
|
@ -115,7 +121,8 @@ are exclusively available to built-in options.
|
|||
its ranges get updated according to all the buffer modifications
|
||||
that happened since its timestamp.
|
||||
|
||||
`set -add` appends the new pair to the list
|
||||
`set -add` appends the new pairs to the list. +
|
||||
`set -remove` removes the given pairs from the list. +
|
||||
|
||||
See <<highlighters#specs-highlighters,`:doc highlighters specs-highlighters`>>)
|
||||
|
||||
|
@ -126,7 +133,9 @@ are exclusively available to built-in options.
|
|||
type, its lines get updated according to all the buffer modifications
|
||||
that happened since its timestamp.
|
||||
See <<highlighters#specs-highlighters,`:doc highlighters specs-highlighters`>>)
|
||||
`set -add` appends the new spec to the list
|
||||
|
||||
`set -add` appends the new specs to the list. +
|
||||
`set -remove` removes the given specs from the list. +
|
||||
|
||||
*completions*::
|
||||
a list of `<text>|<select cmd>|<menu text>` candidates,
|
||||
|
@ -141,7 +150,8 @@ are exclusively available to built-in options.
|
|||
Markup can be used in the menu text.
|
||||
(see <<faces#markup-strings,`:doc faces markup-strings`>>)
|
||||
|
||||
`set -add` adds a new completion to the list
|
||||
`set -add` adds given completions to the list. +
|
||||
`set -remove` removes given completions from the list. +
|
||||
|
||||
*enum(value1|value2|...)*::
|
||||
an enum, taking one of the given values
|
||||
|
@ -150,13 +160,21 @@ are exclusively available to built-in options.
|
|||
*flags(value1|value2|...)*::
|
||||
a set of flags, taking a combination of the given values joined by a
|
||||
'|' character.
|
||||
`set -add` adds the new flag to the combination
|
||||
|
||||
`set -add` adds the given flags to the combination. +
|
||||
`set -remove` removes the given flags to the combination. +
|
||||
|
||||
Cannot be used with `declare-option`
|
||||
|
||||
*<type>-to-<type>-map*::
|
||||
a list of `key=value` pairs.
|
||||
`set -add` adds the new pair to the hashmap or replace an already
|
||||
existing key.
|
||||
|
||||
`set -add` adds the given pair to the hashmap or replace an already
|
||||
existing key. +
|
||||
`set -remove` removes the given pair from the hashmap, if only the
|
||||
key is provided it removes that entry regardless of the associated
|
||||
value. +
|
||||
|
||||
Only `str-to-str-map` options can be created with `declare-option`.
|
||||
|
||||
== Builtin options
|
||||
|
|
|
@ -1539,7 +1539,8 @@ const CommandDesc set_option_cmd = {
|
|||
"<scope> can be global, buffer, window, or current which refers to the narrowest "
|
||||
"scope the option is set in",
|
||||
ParameterDesc{
|
||||
{ { "add", { false, "add to option rather than replacing it" } } },
|
||||
{ { "add", { false, "add to option rather than replacing it" } },
|
||||
{ "remove", { false, "remove from option rather than replacing it" } } },
|
||||
ParameterDesc::Flags::SwitchesOnlyAtStart, 2, (size_t)-1
|
||||
},
|
||||
CommandFlags::None,
|
||||
|
@ -1571,9 +1572,16 @@ const CommandDesc set_option_cmd = {
|
|||
},
|
||||
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
||||
{
|
||||
bool add = (bool)parser.get_switch("add");
|
||||
bool remove = (bool)parser.get_switch("remove");
|
||||
if (add and remove)
|
||||
throw runtime_error("cannot add and remove at the same time");
|
||||
|
||||
Option& opt = get_options(parser[0], context, parser[1]).get_local_option(parser[1]);
|
||||
if (parser.get_switch("add"))
|
||||
if (add)
|
||||
opt.add_from_strings(parser.positionals_from(2));
|
||||
else if (remove)
|
||||
opt.remove_from_strings(parser.positionals_from(2));
|
||||
else
|
||||
opt.set_from_strings(parser.positionals_from(2));
|
||||
}
|
||||
|
|
|
@ -44,6 +44,9 @@ struct {
|
|||
unsigned int version;
|
||||
StringView notes;
|
||||
} constexpr version_notes[] = { {
|
||||
0,
|
||||
"» {+u}set-option -remove{} support\n"
|
||||
}, {
|
||||
20200901,
|
||||
"» daemon mode does not fork anymore\n"
|
||||
}, {
|
||||
|
|
|
@ -43,6 +43,15 @@ option_add_from_strings(T& opt, ConstArrayView<String> strs)
|
|||
return option_add(opt, strs[0]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
decltype(option_add(std::declval<T>(), std::declval<String>()))
|
||||
option_remove_from_strings(T& opt, ConstArrayView<String> strs)
|
||||
{
|
||||
if (strs.size() != 1)
|
||||
throw runtime_error("expected a single value for option");
|
||||
return option_remove(opt, strs[0]);
|
||||
}
|
||||
|
||||
template<typename P, typename T>
|
||||
struct PrefixedList
|
||||
{
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
virtual String get_desc_string() const = 0;
|
||||
virtual void set_from_strings(ConstArrayView<String> strs) = 0;
|
||||
virtual void add_from_strings(ConstArrayView<String> strs) = 0;
|
||||
virtual void remove_from_strings(ConstArrayView<String> strs) = 0;
|
||||
virtual void update(const Context& context) = 0;
|
||||
|
||||
virtual bool has_same_value(const Option& other) const = 0;
|
||||
|
@ -174,6 +175,12 @@ public:
|
|||
m_manager.on_option_changed(*this);
|
||||
}
|
||||
|
||||
void remove_from_strings(ConstArrayView<String> strs) override
|
||||
{
|
||||
if (option_remove_from_strings(m_value, strs))
|
||||
m_manager.on_option_changed(*this);
|
||||
}
|
||||
|
||||
void update(const Context& context) override
|
||||
{
|
||||
option_update(m_value, context);
|
||||
|
|
|
@ -48,6 +48,12 @@ inline bool option_add(int& opt, StringView str)
|
|||
opt += val;
|
||||
return val != 0;
|
||||
}
|
||||
inline bool option_remove(int& opt, StringView str)
|
||||
{
|
||||
auto val = str_to_int(str);
|
||||
opt -= val;
|
||||
return val != 0;
|
||||
}
|
||||
constexpr StringView option_type_name(Meta::Type<int>) { return "int"; }
|
||||
|
||||
inline String option_to_string(size_t opt) { return to_string(opt); }
|
||||
|
@ -110,6 +116,21 @@ bool option_add_from_strings(Vector<T, domain>& opt, ConstArrayView<String> strs
|
|||
return not vec.empty();
|
||||
}
|
||||
|
||||
template<typename T, MemoryDomain domain>
|
||||
bool option_remove_from_strings(Vector<T, domain>& opt, ConstArrayView<String> strs)
|
||||
{
|
||||
bool did_remove = false;
|
||||
for (auto&& val : strs | transform([](auto&& s) { return option_from_string(Meta::Type<T>{}, s); }))
|
||||
{
|
||||
auto it = find(opt, val);
|
||||
if (it == opt.end())
|
||||
continue;
|
||||
opt.erase(it);
|
||||
did_remove = true;
|
||||
}
|
||||
return did_remove;
|
||||
}
|
||||
|
||||
template<typename T, MemoryDomain D>
|
||||
String option_type_name(Meta::Type<Vector<T, D>>)
|
||||
{
|
||||
|
@ -140,10 +161,11 @@ String option_to_string(const HashMap<Key, Value, domain>& opt, Quoting quoting)
|
|||
template<typename Key, typename Value, MemoryDomain domain>
|
||||
bool option_add_from_strings(HashMap<Key, Value, domain>& opt, ConstArrayView<String> strs)
|
||||
{
|
||||
struct error : runtime_error { error(size_t) : runtime_error{"map option expects key=value"} {} };
|
||||
|
||||
bool changed = false;
|
||||
for (auto&& str : strs)
|
||||
{
|
||||
struct error : runtime_error { error(size_t) : runtime_error{"map option expects key=value"} {} };
|
||||
auto key_value = str | split<StringView>('=', '\\')
|
||||
| transform(unescape<'=', '\\'>)
|
||||
| static_gather<error, 2>();
|
||||
|
@ -154,6 +176,27 @@ bool option_add_from_strings(HashMap<Key, Value, domain>& opt, ConstArrayView<St
|
|||
return changed;
|
||||
}
|
||||
|
||||
template<typename Key, typename Value, MemoryDomain domain>
|
||||
bool option_remove_from_strings(HashMap<Key, Value, domain>& opt, ConstArrayView<String> strs)
|
||||
{
|
||||
struct error : runtime_error { error(size_t) : runtime_error{"map option expects key=value"} {} };
|
||||
|
||||
bool changed = false;
|
||||
for (auto&& str : strs)
|
||||
{
|
||||
auto key_value = str | split<StringView>('=', '\\')
|
||||
| transform(unescape<'=', '\\'>)
|
||||
| static_gather<error, 2>();
|
||||
|
||||
if (auto it = opt.find(key_value[0]); it != opt.end() and (key_value[1].empty() or key_value[1] == it->value))
|
||||
{
|
||||
opt.remove(it->key);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
template<typename Key, typename Value, MemoryDomain domain>
|
||||
HashMap<Key, Value, domain> option_from_strings(Meta::Type<HashMap<Key, Value, domain>>, ConstArrayView<String> str)
|
||||
{
|
||||
|
@ -234,6 +277,11 @@ inline bool option_add(WorstMatch, StringView)
|
|||
throw runtime_error("no add operation supported for this option type");
|
||||
}
|
||||
|
||||
inline bool option_remove(WorstMatch, StringView)
|
||||
{
|
||||
throw runtime_error("no remove operation supported for this option type");
|
||||
}
|
||||
|
||||
class Context;
|
||||
|
||||
inline void option_update(WorstMatch, const Context&)
|
||||
|
@ -312,9 +360,17 @@ EnableIfWithoutBitOps<Enum, Enum> option_from_string(Meta::Type<Enum>, StringVie
|
|||
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
||||
EnableIfWithBitOps<Flags, bool> option_add(Flags& opt, StringView str)
|
||||
{
|
||||
const Flags res = option_from_string(Meta::Type<Flags>{}, str);
|
||||
opt |= res;
|
||||
return res != (Flags)0;
|
||||
const Flags old = opt;
|
||||
opt |= option_from_string(Meta::Type<Flags>{}, str);
|
||||
return opt != old;
|
||||
}
|
||||
|
||||
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
||||
EnableIfWithBitOps<Flags, bool> option_remove(Flags& opt, StringView str)
|
||||
{
|
||||
const Flags old = opt;
|
||||
opt &= ~option_from_string(Meta::Type<Flags>{}, str);
|
||||
return opt != old;
|
||||
}
|
||||
|
||||
template<typename P, typename T>
|
||||
|
@ -348,6 +404,12 @@ inline bool option_add_from_strings(PrefixedList<P, T>& opt, ConstArrayView<Stri
|
|||
return option_add_from_strings(opt.list, str);
|
||||
}
|
||||
|
||||
template<typename P, typename T>
|
||||
inline bool option_remove_from_strings(PrefixedList<P, T>& opt, ConstArrayView<String> str)
|
||||
{
|
||||
return option_remove_from_strings(opt.list, str);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // option_types_hh_INCLUDED
|
||||
|
|
Loading…
Reference in New Issue
Block a user