From 45d5dbcc8566d54251302842d13d49cfd8f81780 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 3 Dec 2013 22:03:10 +0000 Subject: [PATCH] Add support for defining and referencing highlighters * defhl defines a shared highlighter * addhl -def-group adds highlighters to the defined highlighter * addhl ref add the defined highlighter to the window's ones --- src/commands.cc | 45 ++++++++++++++++++++++++++----------------- src/function_group.hh | 9 +++++++-- src/highlighter.hh | 5 +++++ src/highlighters.cc | 16 +++++++++++++++ src/main.cc | 1 + 5 files changed, 56 insertions(+), 20 deletions(-) diff --git a/src/commands.cc b/src/commands.cc index 6dbe59f2..ca96e6df 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -240,20 +240,18 @@ void set_buffer_name(CommandParameters params, Context& context) throw runtime_error("unable to change buffer name to " + parser[0]); } -template -Group& get_group(Group& root, const String& group_path) +void define_highlighter(CommandParameters params, Context& context) { - auto it = find(group_path, '/'); - Group& group = root.get_group(String(group_path.begin(), it)); - if (it != group_path.end()) - return get_group(group, String(it+1, group_path.end())); - else - return group; + if (params.size() != 1) + throw wrong_argument_count(); + + const String& name = params[0]; + DefinedHighlighters::instance().append({name, HighlighterGroup{}}); } void add_highlighter(CommandParameters params, Context& context) { - ParametersParser parser(params, { { "group", true } }, ParametersParser::Flags::None, 1); + ParametersParser parser(params, { { "group", true }, { "def-group", true } }, ParametersParser::Flags::None, 1); HighlighterRegistry& registry = HighlighterRegistry::instance(); auto begin = parser.begin(); @@ -262,22 +260,32 @@ void add_highlighter(CommandParameters params, Context& context) for (++begin; begin != parser.end(); ++begin) highlighter_params.push_back(*begin); - Window& window = context.window(); - HighlighterGroup& group = parser.has_option("group") ? - get_group(window.highlighters(), parser.option_value("group")) - : window.highlighters(); + if (parser.has_option("group") and parser.has_option("def-group")) + throw runtime_error("-group and -def-group cannot be specified together"); - group.append(registry[name](highlighter_params)); + HighlighterGroup* group = nullptr; + + if (parser.has_option("def-group")) + group = &DefinedHighlighters::instance().get_group(parser.option_value("def-group"), '/'); + else + { + HighlighterGroup& window_hl = context.window().highlighters(); + group = parser.has_option("group") ? + &window_hl.get_group(parser.option_value("group"), '/') + : &window_hl; + } + + group->append(registry[name](highlighter_params)); } void rm_highlighter(CommandParameters params, Context& context) { ParametersParser parser(params, { { "group", true } }, ParametersParser::Flags::None, 1, 1); - Window& window = context.window(); + HighlighterGroup& window_hl = context.window().highlighters(); HighlighterGroup& group = parser.has_option("group") ? - get_group(window.highlighters(), parser.option_value("group")) - : window.highlighters(); + window_hl.get_group(parser.option_value("group"), '/') + : window_hl; group.remove(parser[0]); } @@ -732,7 +740,7 @@ CommandCompleter group_rm_completer(GetRootGroup get_root_group) if (token_to_complete == 1 and params[0] == "-group") return root_group.complete_group_id(arg, pos_in_token); else if (token_to_complete == 2 and params[0] == "-group") - return get_group(root_group, params[1]).complete_id(arg, pos_in_token); + return root_group.get_group(params[1], '/').complete_id(arg, pos_in_token); return root_group.complete_id(arg, pos_in_token); }; } @@ -816,6 +824,7 @@ void register_commands() auto get_highlighters = [](const Context& c) -> HighlighterGroup& { return c.window().highlighters(); }; cm.register_commands({ "ah", "addhl" }, add_highlighter, CommandFlags::None, group_add_completer(get_highlighters)); cm.register_commands({ "rh", "rmhl" }, rm_highlighter, CommandFlags::None, group_rm_completer(get_highlighters)); + cm.register_commands({ "dh", "defhl" }, define_highlighter); cm.register_command("hook", add_hook); cm.register_command("rmhooks", rm_hooks); diff --git a/src/function_group.hh b/src/function_group.hh index 491debf9..7e598a94 100644 --- a/src/function_group.hh +++ b/src/function_group.hh @@ -33,15 +33,20 @@ public: m_functions.remove(id); } - FunctionGroup& get_group(const String& id) + FunctionGroup& get_group(const String& path, Codepoint path_separator = 0) { + auto sep_it = std::find(path.begin(), path.end(), path_separator); + String id(path.begin(), sep_it); auto it = m_functions.find(id); if (it == m_functions.end()) throw runtime_error("no such id: " + id); FunctionGroup* group = it->second.template target(); if (not group) throw runtime_error("not a group: " + id); - return *group; + if (sep_it != path.end()) + return group->get_group(String(sep_it+1, path.end()), path_separator); + else + return *group; } CandidateList complete_id(const String& prefix, ByteCount cursor_pos) const diff --git a/src/highlighter.hh b/src/highlighter.hh index a81d9817..bed5d235 100644 --- a/src/highlighter.hh +++ b/src/highlighter.hh @@ -32,6 +32,11 @@ struct HighlighterRegistry : FunctionRegistry, Singleton {}; +struct DefinedHighlighters : public HighlighterGroup, + public Singleton +{ +}; + } #endif // highlighter_hh_INCLUDED diff --git a/src/highlighters.cc b/src/highlighters.cc index db4a2b27..99fd38b2 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -403,6 +403,21 @@ HighlighterAndId highlighter_group_factory(HighlighterParameters params) return HighlighterAndId(params[0], HighlighterGroup()); } +HighlighterAndId reference_factory(HighlighterParameters params) +{ + if (params.size() != 1) + throw runtime_error("wrong parameter count"); + + const String& name = params[0]; + + // throw if not found + DefinedHighlighters::instance().get_group(name, '/'); + + return HighlighterAndId(name, + [name](const Window& window, DisplayBuffer& display_buffer) + { DefinedHighlighters::instance().get_group(name, '/')(window, display_buffer); }); +} + void register_highlighters() { HighlighterRegistry& registry = HighlighterRegistry::instance(); @@ -413,6 +428,7 @@ void register_highlighters() registry.register_func("search", highlight_search_factory); registry.register_func("group", highlighter_group_factory); registry.register_func("flag_lines", flag_lines_factory); + registry.register_func("ref", reference_factory); } } diff --git a/src/main.cc b/src/main.cc index 390c3f8f..e035971a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -270,6 +270,7 @@ int kakoune(memoryview params) BufferManager buffer_manager; RegisterManager register_manager; HighlighterRegistry highlighter_registry; + DefinedHighlighters defined_highlighters; ColorRegistry color_registry; ClientManager client_manager;