Add -override support to add-highlighter

This allow replacing a highlighter in place, not loosing its current
position in its parent.

Fixes #3436
This commit is contained in:
Maxime Coste 2020-03-30 21:03:51 +11:00
parent b42885ef71
commit c585107ab5
8 changed files with 34 additions and 18 deletions

View File

@ -252,12 +252,12 @@ of the file onto the filesystem
*colorscheme* <name>:: *colorscheme* <name>::
load named colorscheme load named colorscheme
*add-highlighter* <highlighter_name> <highlighter_parameters> ...:: *add-highlighter* [<switches>] <highlighter_path> <highlighter_parameters> ...::
*alias* addhl + *alias* addhl +
add a highlighter to the current window add a highlighter to the current window
(See <<highlighters#,`:doc highlighters`>>) (See <<highlighters#,`:doc highlighters`>>)
*remove-highlighter* <highlighter_id>:: *remove-highlighter* <highlighter_path>::
*alias* rmhl + *alias* rmhl +
remove the highlighter whose id is *highlighter_id* remove the highlighter whose id is *highlighter_id*
(See <<highlighters#,`:doc highlighters`>>) (See <<highlighters#,`:doc highlighters`>>)

View File

@ -5,9 +5,9 @@
Manipulation of the displayed text is done through highlighters, which can Manipulation of the displayed text is done through highlighters, which can
be added or removed with the following commands: be added or removed with the following commands:
----------------------------------------------------- -----------------------------------------------------------------
add-highlighter <path>/<name> <type> <parameters> ... add-highlighter [-override] <path>/<name> <type> <parameters> ...
----------------------------------------------------- -----------------------------------------------------------------
and and
@ -23,6 +23,9 @@ separated path starting with a scope. Scopes are *global*, *buffer*,
`add-highlighter` (the path ends with a `/`), it will be auto-generated `add-highlighter` (the path ends with a `/`), it will be auto-generated
from the remaining parameters. from the remaining parameters.
if `-override` is specified and the given name already exists, that
highlighter is replaced with the new one.
== Convenient highlighters == Convenient highlighters
*show-matching*:: *show-matching*::

View File

@ -950,7 +950,10 @@ const CommandDesc add_highlighter_cmd = {
"add-highlighter <path>/<name> <type> <type params>...: add an highlighter to the group identified by <path>\n" "add-highlighter <path>/<name> <type> <type params>...: add an highlighter to the group identified by <path>\n"
" <path> is a '/' delimited path or the parent highlighter, starting with either\n" " <path> is a '/' delimited path or the parent highlighter, starting with either\n"
" 'global', 'buffer', 'window' or 'shared', if <name> is empty, it will be autogenerated", " 'global', 'buffer', 'window' or 'shared', if <name> is empty, it will be autogenerated",
ParameterDesc{ {}, ParameterDesc::Flags::SwitchesAsPositional, 2 }, ParameterDesc{
{ { "override", { false, "replace existing highlighter with same path if it exists" } }, },
ParameterDesc::Flags::SwitchesOnlyAtStart, 2
},
CommandFlags::None, CommandFlags::None,
[](const Context& context, CommandParameters params) -> String [](const Context& context, CommandParameters params) -> String
{ {
@ -990,7 +993,7 @@ const CommandDesc add_highlighter_cmd = {
String name{slash.base(), path.end()}; String name{slash.base(), path.end()};
Highlighter& parent = get_highlighter(context, {path.begin(), slash.base() - 1}); Highlighter& parent = get_highlighter(context, {path.begin(), slash.base() - 1});
parent.add_child(name.empty() ? auto_name(parser.positionals_from(1)) : std::move(name), parent.add_child(name.empty() ? auto_name(parser.positionals_from(1)) : std::move(name),
it->value.factory(highlighter_params, &parent)); it->value.factory(highlighter_params, &parent), (bool)parser.get_switch("override"));
redraw_relevant_clients(context, path); redraw_relevant_clients(context, path);
} }

View File

@ -34,7 +34,7 @@ Highlighter& Highlighter::get_child(StringView path)
throw runtime_error("this highlighter does not hold children"); throw runtime_error("this highlighter does not hold children");
} }
void Highlighter::add_child(String name, std::unique_ptr<Highlighter>&& hl) void Highlighter::add_child(String, std::unique_ptr<Highlighter>&&, bool)
{ {
throw runtime_error("this highlighter does not hold children"); throw runtime_error("this highlighter does not hold children");
} }

View File

@ -69,7 +69,7 @@ struct Highlighter
virtual bool has_children() const; virtual bool has_children() const;
virtual Highlighter& get_child(StringView path); virtual Highlighter& get_child(StringView path);
virtual void add_child(String name, std::unique_ptr<Highlighter>&& hl); virtual void add_child(String name, std::unique_ptr<Highlighter>&& hl, bool override = false);
virtual void remove_child(StringView id); virtual void remove_child(StringView id);
virtual Completions complete_child(StringView path, ByteCount cursor_pos, bool group) const; virtual Completions complete_child(StringView path, ByteCount cursor_pos, bool group) const;
virtual void fill_unique_ids(Vector<StringView>& unique_ids) const; virtual void fill_unique_ids(Vector<StringView>& unique_ids) const;

View File

@ -24,13 +24,19 @@ void HighlighterGroup::fill_unique_ids(Vector<StringView>& unique_ids) const
hl.value->fill_unique_ids(unique_ids); hl.value->fill_unique_ids(unique_ids);
} }
void HighlighterGroup::add_child(String name, std::unique_ptr<Highlighter>&& hl) void HighlighterGroup::add_child(String name, std::unique_ptr<Highlighter>&& hl, bool override)
{ {
if ((hl->passes() & passes()) != hl->passes()) if ((hl->passes() & passes()) != hl->passes())
throw runtime_error{"cannot add that highlighter to this group, passes don't match"}; throw runtime_error{"cannot add that highlighter to this group, passes don't match"};
if (m_highlighters.contains(name)) auto it = m_highlighters.find(name);
throw runtime_error(format("duplicate id: '{}'", name)); if (it != m_highlighters.end())
{
if (not override)
throw runtime_error(format("duplicate id: '{}'", name));
it->value = std::move(hl);
return;
}
m_highlighters.insert({std::move(name), std::move(hl)}); m_highlighters.insert({std::move(name), std::move(hl)});
} }

View File

@ -21,7 +21,7 @@ public:
HighlighterGroup(HighlightPass passes) : Highlighter{passes} {} HighlighterGroup(HighlightPass passes) : Highlighter{passes} {}
bool has_children() const override { return true; } bool has_children() const override { return true; }
void add_child(String name, std::unique_ptr<Highlighter>&& hl) override; void add_child(String name, std::unique_ptr<Highlighter>&& hl, bool override = false) override;
void remove_child(StringView id) override; void remove_child(StringView id) override;
Highlighter& get_child(StringView path) override; Highlighter& get_child(StringView path) override;

View File

@ -1873,11 +1873,12 @@ public:
return it->value->get_child({sep_it+1, path.end()}); return it->value->get_child({sep_it+1, path.end()});
} }
void add_child(String name, std::unique_ptr<Highlighter>&& hl) override void add_child(String name, std::unique_ptr<Highlighter>&& hl, bool override) override
{ {
if (not dynamic_cast<RegionHighlighter*>(hl.get())) if (not dynamic_cast<RegionHighlighter*>(hl.get()))
throw runtime_error{"only region highlighter can be added as child of a regions highlighter"}; throw runtime_error{"only region highlighter can be added as child of a regions highlighter"};
if (m_regions.contains(name)) auto it = m_regions.find(name);
if (not override and it != m_regions.end())
throw runtime_error{format("duplicate id: '{}'", name)}; throw runtime_error{format("duplicate id: '{}'", name)};
std::unique_ptr<RegionHighlighter> region_hl{dynamic_cast<RegionHighlighter*>(hl.release())}; std::unique_ptr<RegionHighlighter> region_hl{dynamic_cast<RegionHighlighter*>(hl.release())};
@ -1888,7 +1889,10 @@ public:
m_default_region = name; m_default_region = name;
} }
m_regions.insert({std::move(name), std::move(region_hl)}); if (it != m_regions.end())
it->value = std::move(region_hl);
else
m_regions.insert({std::move(name), std::move(region_hl)});
++m_regions_timestamp; ++m_regions_timestamp;
} }
@ -2132,9 +2136,9 @@ private:
return m_delegate->get_child(path); return m_delegate->get_child(path);
} }
void add_child(String name, std::unique_ptr<Highlighter>&& hl) override void add_child(String name, std::unique_ptr<Highlighter>&& hl, bool override) override
{ {
return m_delegate->add_child(name, std::move(hl)); return m_delegate->add_child(name, std::move(hl), override);
} }
void remove_child(StringView id) override void remove_child(StringView id) override