1 #include "highlighter_group.hh"
2 
3 #include "ranges.hh"
4 #include "string_utils.hh"
5 
6 namespace Kakoune
7 {
8 
do_highlight(HighlightContext context,DisplayBuffer & display_buffer,BufferRange range)9 void HighlighterGroup::do_highlight(HighlightContext context, DisplayBuffer& display_buffer, BufferRange range)
10 {
11     for (auto& hl : m_highlighters)
12         hl.value->highlight(context, display_buffer, range);
13 }
14 
do_compute_display_setup(HighlightContext context,DisplaySetup & setup) const15 void HighlighterGroup::do_compute_display_setup(HighlightContext context, DisplaySetup& setup) const
16 {
17     for (auto& hl : m_highlighters)
18         hl.value->compute_display_setup(context, setup);
19 }
20 
fill_unique_ids(Vector<StringView> & unique_ids) const21 void HighlighterGroup::fill_unique_ids(Vector<StringView>& unique_ids) const
22 {
23     for (auto& hl : m_highlighters)
24         hl.value->fill_unique_ids(unique_ids);
25 }
26 
add_child(String name,std::unique_ptr<Highlighter> && hl,bool override)27 void HighlighterGroup::add_child(String name, std::unique_ptr<Highlighter>&& hl, bool override)
28 {
29     if ((hl->passes() & passes()) != hl->passes())
30         throw runtime_error{"cannot add that highlighter to this group, passes don't match"};
31 
32     auto it = m_highlighters.find(name);
33     if (it != m_highlighters.end())
34     {
35         if (not override)
36             throw runtime_error(format("duplicate id: '{}'", name));
37         it->value = std::move(hl);
38         return;
39     }
40 
41     m_highlighters.insert({std::move(name), std::move(hl)});
42 }
43 
remove_child(StringView id)44 void HighlighterGroup::remove_child(StringView id)
45 {
46     m_highlighters.remove(id);
47 }
48 
get_child(StringView path)49 Highlighter& HighlighterGroup::get_child(StringView path)
50 {
51     auto sep_it = find(path, '/');
52     StringView id(path.begin(), sep_it);
53     auto it = m_highlighters.find(id);
54     if (it == m_highlighters.end())
55         throw child_not_found(format("no such id: '{}'", id));
56     if (sep_it == path.end())
57         return *it->value;
58     else
59         return it->value->get_child({sep_it+1, path.end()});
60 }
61 
complete_child(StringView path,ByteCount cursor_pos,bool group) const62 Completions HighlighterGroup::complete_child(StringView path, ByteCount cursor_pos, bool group) const
63 {
64     auto sep_it = find(path, '/');
65     if (sep_it != path.end())
66     {
67         ByteCount offset = sep_it+1 - path.begin();
68         Highlighter& hl = const_cast<HighlighterGroup*>(this)->get_child({path.begin(), sep_it});
69         return offset_pos(hl.complete_child(path.substr(offset), cursor_pos - offset, group), offset);
70     }
71 
72     auto candidates = complete(
73         path, cursor_pos,
74         m_highlighters | filter([=](auto& hl) { return not group or hl.value->has_children(); })
75                        | transform([](auto& hl) { return hl.value->has_children() ? hl.key + "/" : hl.key; })
76                        | gather<Vector<String>>());
77 
78     return { 0, 0, std::move(candidates) };
79 }
80 
highlight(HighlightContext context,DisplayBuffer & display_buffer,BufferRange range)81 void Highlighters::highlight(HighlightContext context, DisplayBuffer& display_buffer, BufferRange range)
82 {
83     Vector<StringView> disabled_ids(context.disabled_ids.begin(), context.disabled_ids.end());
84     m_group.fill_unique_ids(disabled_ids);
85 
86     if (m_parent)
87         m_parent->highlight({context.context, context.setup, context.pass, disabled_ids}, display_buffer, range);
88     m_group.highlight(context, display_buffer, range);
89 }
90 
compute_display_setup(HighlightContext context,DisplaySetup & setup) const91 void Highlighters::compute_display_setup(HighlightContext context, DisplaySetup& setup) const
92 {
93     Vector<StringView> disabled_ids(context.disabled_ids.begin(), context.disabled_ids.end());
94     m_group.fill_unique_ids(disabled_ids);
95 
96     if (m_parent)
97         m_parent->compute_display_setup({context.context, context.setup, context.pass, disabled_ids}, setup);
98     m_group.compute_display_setup(context, setup);
99 }
100 
101 }
102