Add experimental region_ref highlighter
highlights a region using another highlighter.
This commit is contained in:
parent
39512914ad
commit
277b02eee6
|
@ -61,6 +61,13 @@ void DisplayLine::push_back(DisplayAtom atom)
|
||||||
m_atoms.push_back(std::move(atom));
|
m_atoms.push_back(std::move(atom));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DisplayLine::iterator DisplayLine::erase(iterator beg, iterator end)
|
||||||
|
{
|
||||||
|
iterator res = m_atoms.erase(beg, end);
|
||||||
|
compute_range();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
void DisplayLine::optimize()
|
void DisplayLine::optimize()
|
||||||
{
|
{
|
||||||
if (m_atoms.empty())
|
if (m_atoms.empty())
|
||||||
|
@ -142,9 +149,11 @@ void DisplayLine::trim(CharCount first_char, CharCount char_count)
|
||||||
compute_range();
|
compute_range();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr BufferRange init_range{ {INT_MAX, INT_MAX}, {INT_MIN, INT_MIN} };
|
||||||
|
|
||||||
void DisplayLine::compute_range()
|
void DisplayLine::compute_range()
|
||||||
{
|
{
|
||||||
m_range = { {INT_MAX, INT_MAX}, {INT_MIN, INT_MIN} };
|
m_range = init_range;
|
||||||
for (auto& atom : m_atoms)
|
for (auto& atom : m_atoms)
|
||||||
{
|
{
|
||||||
if (not atom.has_buffer_range())
|
if (not atom.has_buffer_range())
|
||||||
|
@ -152,17 +161,21 @@ void DisplayLine::compute_range()
|
||||||
m_range.first = std::min(m_range.first, atom.begin());
|
m_range.first = std::min(m_range.first, atom.begin());
|
||||||
m_range.second = std::max(m_range.second, atom.end());
|
m_range.second = std::max(m_range.second, atom.end());
|
||||||
}
|
}
|
||||||
|
if (m_range == init_range)
|
||||||
|
m_range = { { 0, 0 }, { 0, 0 } };
|
||||||
|
kak_assert(m_range.first <= m_range.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayBuffer::compute_range()
|
void DisplayBuffer::compute_range()
|
||||||
{
|
{
|
||||||
m_range.first = {INT_MAX,INT_MAX};
|
m_range = init_range;
|
||||||
m_range.second = {0,0};
|
|
||||||
for (auto& line : m_lines)
|
for (auto& line : m_lines)
|
||||||
{
|
{
|
||||||
m_range.first = std::min(line.range().first, m_range.first);
|
m_range.first = std::min(line.range().first, m_range.first);
|
||||||
m_range.second = std::max(line.range().second, m_range.second);
|
m_range.second = std::max(line.range().second, m_range.second);
|
||||||
}
|
}
|
||||||
|
if (m_range == init_range)
|
||||||
|
m_range = { { 0, 0 }, { 0, 0 } };
|
||||||
kak_assert(m_range.first <= m_range.second);
|
kak_assert(m_range.first <= m_range.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,7 @@ class DisplayLine
|
||||||
public:
|
public:
|
||||||
using iterator = AtomList::iterator;
|
using iterator = AtomList::iterator;
|
||||||
using const_iterator = AtomList::const_iterator;
|
using const_iterator = AtomList::const_iterator;
|
||||||
|
using value_type = AtomList::value_type;
|
||||||
|
|
||||||
DisplayLine() = default;
|
DisplayLine() = default;
|
||||||
DisplayLine(AtomList atoms);
|
DisplayLine(AtomList atoms);
|
||||||
|
@ -143,6 +144,7 @@ public:
|
||||||
iterator split(iterator it, BufferCoord pos);
|
iterator split(iterator it, BufferCoord pos);
|
||||||
|
|
||||||
iterator insert(iterator it, DisplayAtom atom);
|
iterator insert(iterator it, DisplayAtom atom);
|
||||||
|
iterator erase(iterator beg, iterator end);
|
||||||
void push_back(DisplayAtom atom);
|
void push_back(DisplayAtom atom);
|
||||||
|
|
||||||
// remove first_char from the begining of the line, and make sure
|
// remove first_char from the begining of the line, and make sure
|
||||||
|
|
|
@ -61,6 +61,89 @@ void highlight_range(DisplayBuffer& display_buffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void apply_highlighter(const Window& window,
|
||||||
|
DisplayBuffer& display_buffer,
|
||||||
|
BufferCoord begin, BufferCoord end,
|
||||||
|
T&& highlighter)
|
||||||
|
{
|
||||||
|
using LineIterator = DisplayBuffer::LineList::iterator;
|
||||||
|
LineIterator first_line;
|
||||||
|
std::vector<DisplayLine::iterator> insert_pos;
|
||||||
|
auto line_end = display_buffer.lines().end();
|
||||||
|
|
||||||
|
DisplayBuffer region_display;
|
||||||
|
auto& region_lines = region_display.lines();
|
||||||
|
for (auto line_it = display_buffer.lines().begin(); line_it != line_end; ++line_it)
|
||||||
|
{
|
||||||
|
auto& line = *line_it;
|
||||||
|
auto& range = line.range();
|
||||||
|
if (range.second <= begin or end < range.first)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (region_lines.empty())
|
||||||
|
first_line = line_it;
|
||||||
|
region_lines.emplace_back();
|
||||||
|
insert_pos.emplace_back();
|
||||||
|
|
||||||
|
if (range.first < begin or range.second > end)
|
||||||
|
{
|
||||||
|
size_t beg_idx = 0;
|
||||||
|
size_t end_idx = line.atoms().size();
|
||||||
|
|
||||||
|
for (auto atom_it = line.begin(); atom_it != line.end(); ++atom_it)
|
||||||
|
{
|
||||||
|
if (not atom_it->has_buffer_range() or end <= atom_it->begin() or begin >= atom_it->end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool is_replaced = atom_it->type() == DisplayAtom::ReplacedBufferRange;
|
||||||
|
if (atom_it->begin() <= begin)
|
||||||
|
{
|
||||||
|
if (is_replaced or atom_it->begin() == begin)
|
||||||
|
beg_idx = atom_it - line.begin();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
atom_it = ++line.split(atom_it, begin);
|
||||||
|
beg_idx = atom_it - line.begin();
|
||||||
|
++end_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atom_it->end() >= end)
|
||||||
|
{
|
||||||
|
if (is_replaced or atom_it->end() == end)
|
||||||
|
beg_idx = atom_it - line.begin();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
atom_it = ++line.split(atom_it, end);
|
||||||
|
end_idx = atom_it - line.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::move(line.begin() + beg_idx, line.begin() + end_idx,
|
||||||
|
std::back_inserter(region_lines.back()));
|
||||||
|
insert_pos.back() = line.erase(line.begin() + beg_idx, line.begin() + end_idx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
region_lines.back() = std::move(line);
|
||||||
|
insert_pos.back() = line.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
region_display.compute_range();
|
||||||
|
highlighter(window, region_display);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < region_lines.size(); ++i)
|
||||||
|
{
|
||||||
|
auto& line = *(first_line + i);
|
||||||
|
auto pos = insert_pos[i];
|
||||||
|
for (auto& atom : region_lines[i])
|
||||||
|
pos = ++line.insert(pos, std::move(atom));
|
||||||
|
}
|
||||||
|
display_buffer.compute_range();
|
||||||
|
}
|
||||||
|
|
||||||
typedef std::unordered_map<size_t, const ColorPair*> ColorSpec;
|
typedef std::unordered_map<size_t, const ColorPair*> ColorSpec;
|
||||||
|
|
||||||
class RegexColorizer
|
class RegexColorizer
|
||||||
|
@ -418,29 +501,29 @@ HighlighterAndId reference_factory(HighlighterParameters params)
|
||||||
{ DefinedHighlighters::instance().get_group(name, '/')(window, display_buffer); });
|
{ DefinedHighlighters::instance().get_group(name, '/')(window, display_buffer); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename HighlightFunc>
|
||||||
struct RegionHighlighter
|
struct RegionHighlighter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RegionHighlighter(String begin, String end, String ignore_prefix,
|
RegionHighlighter(String begin, String end, String ignore_prefix,
|
||||||
ColorPair colors)
|
HighlightFunc func)
|
||||||
: m_begin(std::move(begin)),
|
: m_begin(std::move(begin)),
|
||||||
m_end(std::move(end)),
|
m_end(std::move(end)),
|
||||||
m_ignore_prefix(std::move(ignore_prefix)),
|
m_ignore_prefix(std::move(ignore_prefix)),
|
||||||
m_colors(colors)
|
m_func(std::move(func))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void operator()(const Window& window, DisplayBuffer& display_buffer)
|
void operator()(const Window& window, DisplayBuffer& display_buffer)
|
||||||
{
|
{
|
||||||
auto& cache = update_cache_ifn(window.buffer());
|
auto& cache = update_cache_ifn(window.buffer());
|
||||||
for (auto& pair : cache.regions)
|
for (auto& pair : cache.regions)
|
||||||
highlight_range(display_buffer, pair.first, pair.second, true,
|
m_func(window, display_buffer, pair.first, pair.second);
|
||||||
[this](DisplayAtom& atom) { atom.colors = m_colors; });
|
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
String m_begin;
|
String m_begin;
|
||||||
String m_end;
|
String m_end;
|
||||||
String m_ignore_prefix;
|
String m_ignore_prefix;
|
||||||
ColorPair m_colors;
|
HighlightFunc m_func;
|
||||||
|
|
||||||
struct RegionCache
|
struct RegionCache
|
||||||
{
|
{
|
||||||
|
@ -482,6 +565,15 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename HighlightFunc>
|
||||||
|
RegionHighlighter<HighlightFunc>
|
||||||
|
make_region_highlighter(String begin, String end, String ignore_prefix,
|
||||||
|
HighlightFunc func)
|
||||||
|
{
|
||||||
|
return RegionHighlighter<HighlightFunc>(std::move(begin), std::move(end),
|
||||||
|
std::move(ignore_prefix), std::move(func));
|
||||||
|
}
|
||||||
|
|
||||||
HighlighterAndId region_factory(HighlighterParameters params)
|
HighlighterAndId region_factory(HighlighterParameters params)
|
||||||
{
|
{
|
||||||
if (params.size() != 3 and params.size() != 4)
|
if (params.size() != 3 and params.size() != 4)
|
||||||
|
@ -492,10 +584,37 @@ HighlighterAndId region_factory(HighlighterParameters params)
|
||||||
const String& ignore_prefix = params.size() == 4 ? params[2] : "";
|
const String& ignore_prefix = params.size() == 4 ? params[2] : "";
|
||||||
const ColorPair colors = get_color(params.back());
|
const ColorPair colors = get_color(params.back());
|
||||||
|
|
||||||
return HighlighterAndId("region("+begin+","+end+","+ignore_prefix+")",
|
auto func = [colors](const Window&, DisplayBuffer& display_buffer,
|
||||||
RegionHighlighter{begin, end, ignore_prefix, colors});
|
BufferCoord begin, BufferCoord end)
|
||||||
|
{
|
||||||
|
highlight_range(display_buffer, begin, end, true,
|
||||||
|
[&colors](DisplayAtom& atom) { atom.colors = colors; });
|
||||||
|
};
|
||||||
|
|
||||||
|
return HighlighterAndId("region(" + begin + "," + end + "," + ignore_prefix + ")",
|
||||||
|
make_region_highlighter(begin, end, ignore_prefix, func));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HighlighterAndId region_ref_factory(HighlighterParameters params)
|
||||||
|
{
|
||||||
|
if (params.size() != 3 and params.size() != 4)
|
||||||
|
throw runtime_error("wrong parameter count");
|
||||||
|
|
||||||
|
const String& begin = params[0];
|
||||||
|
const String& end = params[1];
|
||||||
|
const String& ignore_prefix = params.size() == 4 ? params[2] : "";
|
||||||
|
const String& name = params.back();
|
||||||
|
|
||||||
|
auto func = [name](const Window& window, DisplayBuffer& display_buffer,
|
||||||
|
BufferCoord begin, BufferCoord end)
|
||||||
|
{
|
||||||
|
HighlighterGroup& ref = DefinedHighlighters::instance().get_group(name, '/');
|
||||||
|
apply_highlighter(window, display_buffer, begin, end, ref);
|
||||||
|
};
|
||||||
|
|
||||||
|
return HighlighterAndId("regionref(" + begin + "," + end + "," + ignore_prefix + "," + name + ")",
|
||||||
|
make_region_highlighter(begin, end, ignore_prefix, func));
|
||||||
|
}
|
||||||
|
|
||||||
void register_highlighters()
|
void register_highlighters()
|
||||||
{
|
{
|
||||||
|
@ -509,6 +628,7 @@ void register_highlighters()
|
||||||
registry.register_func("flag_lines", flag_lines_factory);
|
registry.register_func("flag_lines", flag_lines_factory);
|
||||||
registry.register_func("ref", reference_factory);
|
registry.register_func("ref", reference_factory);
|
||||||
registry.register_func("region", region_factory);
|
registry.register_func("region", region_factory);
|
||||||
|
registry.register_func("region_ref", region_ref_factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user