From c585107ab5e7155f7da648c3752cf360f7156177 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 30 Mar 2020 21:03:51 +1100 Subject: [PATCH] Add -override support to add-highlighter This allow replacing a highlighter in place, not loosing its current position in its parent. Fixes #3436 --- doc/pages/commands.asciidoc | 4 ++-- doc/pages/highlighters.asciidoc | 9 ++++++--- src/commands.cc | 7 +++++-- src/highlighter.cc | 2 +- src/highlighter.hh | 2 +- src/highlighter_group.cc | 12 +++++++++--- src/highlighter_group.hh | 2 +- src/highlighters.cc | 14 +++++++++----- 8 files changed, 34 insertions(+), 18 deletions(-) diff --git a/doc/pages/commands.asciidoc b/doc/pages/commands.asciidoc index e83cdf40a..baff045ae 100644 --- a/doc/pages/commands.asciidoc +++ b/doc/pages/commands.asciidoc @@ -252,12 +252,12 @@ of the file onto the filesystem *colorscheme* :: load named colorscheme -*add-highlighter* ...:: +*add-highlighter* [] ...:: *alias* addhl + add a highlighter to the current window (See <>) -*remove-highlighter* :: +*remove-highlighter* :: *alias* rmhl + remove the highlighter whose id is *highlighter_id* (See <>) diff --git a/doc/pages/highlighters.asciidoc b/doc/pages/highlighters.asciidoc index fd95b49f5..25e39846d 100644 --- a/doc/pages/highlighters.asciidoc +++ b/doc/pages/highlighters.asciidoc @@ -5,9 +5,9 @@ Manipulation of the displayed text is done through highlighters, which can be added or removed with the following commands: ------------------------------------------------------ -add-highlighter / ... ------------------------------------------------------ +----------------------------------------------------------------- +add-highlighter [-override] / ... +----------------------------------------------------------------- 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 from the remaining parameters. +if `-override` is specified and the given name already exists, that +highlighter is replaced with the new one. + == Convenient highlighters *show-matching*:: diff --git a/src/commands.cc b/src/commands.cc index 3a14457d5..eff898a25 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -950,7 +950,10 @@ const CommandDesc add_highlighter_cmd = { "add-highlighter / ...: add an highlighter to the group identified by \n" " is a '/' delimited path or the parent highlighter, starting with either\n" " 'global', 'buffer', 'window' or 'shared', if 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, [](const Context& context, CommandParameters params) -> String { @@ -990,7 +993,7 @@ const CommandDesc add_highlighter_cmd = { String name{slash.base(), path.end()}; Highlighter& parent = get_highlighter(context, {path.begin(), slash.base() - 1}); 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); } diff --git a/src/highlighter.cc b/src/highlighter.cc index 20a70fe2c..86da8ac6e 100644 --- a/src/highlighter.cc +++ b/src/highlighter.cc @@ -34,7 +34,7 @@ Highlighter& Highlighter::get_child(StringView path) throw runtime_error("this highlighter does not hold children"); } -void Highlighter::add_child(String name, std::unique_ptr&& hl) +void Highlighter::add_child(String, std::unique_ptr&&, bool) { throw runtime_error("this highlighter does not hold children"); } diff --git a/src/highlighter.hh b/src/highlighter.hh index dd5e22854..17cfac4aa 100644 --- a/src/highlighter.hh +++ b/src/highlighter.hh @@ -69,7 +69,7 @@ struct Highlighter virtual bool has_children() const; virtual Highlighter& get_child(StringView path); - virtual void add_child(String name, std::unique_ptr&& hl); + virtual void add_child(String name, std::unique_ptr&& hl, bool override = false); virtual void remove_child(StringView id); virtual Completions complete_child(StringView path, ByteCount cursor_pos, bool group) const; virtual void fill_unique_ids(Vector& unique_ids) const; diff --git a/src/highlighter_group.cc b/src/highlighter_group.cc index e98ab4aa4..d5d431987 100644 --- a/src/highlighter_group.cc +++ b/src/highlighter_group.cc @@ -24,13 +24,19 @@ void HighlighterGroup::fill_unique_ids(Vector& unique_ids) const hl.value->fill_unique_ids(unique_ids); } -void HighlighterGroup::add_child(String name, std::unique_ptr&& hl) +void HighlighterGroup::add_child(String name, std::unique_ptr&& hl, bool override) { if ((hl->passes() & passes()) != hl->passes()) throw runtime_error{"cannot add that highlighter to this group, passes don't match"}; - if (m_highlighters.contains(name)) - throw runtime_error(format("duplicate id: '{}'", name)); + auto it = m_highlighters.find(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)}); } diff --git a/src/highlighter_group.hh b/src/highlighter_group.hh index 357a0501e..f3727e583 100644 --- a/src/highlighter_group.hh +++ b/src/highlighter_group.hh @@ -21,7 +21,7 @@ public: HighlighterGroup(HighlightPass passes) : Highlighter{passes} {} bool has_children() const override { return true; } - void add_child(String name, std::unique_ptr&& hl) override; + void add_child(String name, std::unique_ptr&& hl, bool override = false) override; void remove_child(StringView id) override; Highlighter& get_child(StringView path) override; diff --git a/src/highlighters.cc b/src/highlighters.cc index 82acdd53a..464f78cd5 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -1873,11 +1873,12 @@ public: return it->value->get_child({sep_it+1, path.end()}); } - void add_child(String name, std::unique_ptr&& hl) override + void add_child(String name, std::unique_ptr&& hl, bool override) override { if (not dynamic_cast(hl.get())) 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)}; std::unique_ptr region_hl{dynamic_cast(hl.release())}; @@ -1888,7 +1889,10 @@ public: 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; } @@ -2132,9 +2136,9 @@ private: return m_delegate->get_child(path); } - void add_child(String name, std::unique_ptr&& hl) override + void add_child(String name, std::unique_ptr&& 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