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));
|
||||
}
|
||||
|
||||
DisplayLine::iterator DisplayLine::erase(iterator beg, iterator end)
|
||||
{
|
||||
iterator res = m_atoms.erase(beg, end);
|
||||
compute_range();
|
||||
return res;
|
||||
}
|
||||
|
||||
void DisplayLine::optimize()
|
||||
{
|
||||
if (m_atoms.empty())
|
||||
|
@ -142,9 +149,11 @@ void DisplayLine::trim(CharCount first_char, CharCount char_count)
|
|||
compute_range();
|
||||
}
|
||||
|
||||
constexpr BufferRange init_range{ {INT_MAX, INT_MAX}, {INT_MIN, INT_MIN} };
|
||||
|
||||
void DisplayLine::compute_range()
|
||||
{
|
||||
m_range = { {INT_MAX, INT_MAX}, {INT_MIN, INT_MIN} };
|
||||
m_range = init_range;
|
||||
for (auto& atom : m_atoms)
|
||||
{
|
||||
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.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()
|
||||
{
|
||||
m_range.first = {INT_MAX,INT_MAX};
|
||||
m_range.second = {0,0};
|
||||
m_range = init_range;
|
||||
for (auto& line : m_lines)
|
||||
{
|
||||
m_range.first = std::min(line.range().first, m_range.first);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,7 @@ class DisplayLine
|
|||
public:
|
||||
using iterator = AtomList::iterator;
|
||||
using const_iterator = AtomList::const_iterator;
|
||||
using value_type = AtomList::value_type;
|
||||
|
||||
DisplayLine() = default;
|
||||
DisplayLine(AtomList atoms);
|
||||
|
@ -143,6 +144,7 @@ public:
|
|||
iterator split(iterator it, BufferCoord pos);
|
||||
|
||||
iterator insert(iterator it, DisplayAtom atom);
|
||||
iterator erase(iterator beg, iterator end);
|
||||
void push_back(DisplayAtom atom);
|
||||
|
||||
// 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;
|
||||
|
||||
class RegexColorizer
|
||||
|
@ -418,29 +501,29 @@ HighlighterAndId reference_factory(HighlighterParameters params)
|
|||
{ DefinedHighlighters::instance().get_group(name, '/')(window, display_buffer); });
|
||||
}
|
||||
|
||||
template<typename HighlightFunc>
|
||||
struct RegionHighlighter
|
||||
{
|
||||
public:
|
||||
RegionHighlighter(String begin, String end, String ignore_prefix,
|
||||
ColorPair colors)
|
||||
HighlightFunc func)
|
||||
: m_begin(std::move(begin)),
|
||||
m_end(std::move(end)),
|
||||
m_ignore_prefix(std::move(ignore_prefix)),
|
||||
m_colors(colors)
|
||||
m_func(std::move(func))
|
||||
{}
|
||||
|
||||
void operator()(const Window& window, DisplayBuffer& display_buffer)
|
||||
{
|
||||
auto& cache = update_cache_ifn(window.buffer());
|
||||
for (auto& pair : cache.regions)
|
||||
highlight_range(display_buffer, pair.first, pair.second, true,
|
||||
[this](DisplayAtom& atom) { atom.colors = m_colors; });
|
||||
m_func(window, display_buffer, pair.first, pair.second);
|
||||
}
|
||||
private:
|
||||
String m_begin;
|
||||
String m_end;
|
||||
String m_ignore_prefix;
|
||||
ColorPair m_colors;
|
||||
HighlightFunc m_func;
|
||||
|
||||
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)
|
||||
{
|
||||
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 ColorPair colors = get_color(params.back());
|
||||
|
||||
return HighlighterAndId("region("+begin+","+end+","+ignore_prefix+")",
|
||||
RegionHighlighter{begin, end, ignore_prefix, colors});
|
||||
auto func = [colors](const Window&, DisplayBuffer& display_buffer,
|
||||
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()
|
||||
{
|
||||
|
@ -509,6 +628,7 @@ void register_highlighters()
|
|||
registry.register_func("flag_lines", flag_lines_factory);
|
||||
registry.register_func("ref", reference_factory);
|
||||
registry.register_func("region", region_factory);
|
||||
registry.register_func("region_ref", region_ref_factory);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user