Add a basic replace-ranges highlighter
replace-ranges is takes a range-faces option, but treats the face string as a display line to be parsed, and replaces the range display with this display line.
This commit is contained in:
parent
468bd63569
commit
44d2db2706
|
@ -64,10 +64,8 @@ void highlight_range(DisplayBuffer& display_buffer,
|
||||||
bool is_replaced = atom_it->type() == DisplayAtom::ReplacedRange;
|
bool is_replaced = atom_it->type() == DisplayAtom::ReplacedRange;
|
||||||
|
|
||||||
if (not atom_it->has_buffer_range() or
|
if (not atom_it->has_buffer_range() or
|
||||||
(skip_replaced and is_replaced))
|
(skip_replaced and is_replaced) or
|
||||||
continue;
|
end <= atom_it->begin() or begin >= atom_it->end())
|
||||||
|
|
||||||
if (end <= atom_it->begin() or begin >= atom_it->end())
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (not is_replaced and begin > atom_it->begin())
|
if (not is_replaced and begin > atom_it->begin())
|
||||||
|
@ -85,6 +83,47 @@ void highlight_range(DisplayBuffer& display_buffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void replace_range(DisplayBuffer& display_buffer,
|
||||||
|
BufferCoord begin, BufferCoord end, T func)
|
||||||
|
{
|
||||||
|
// tolerate begin > end as that can be triggered by wrong encodngs
|
||||||
|
if (begin >= end or end <= display_buffer.range().begin
|
||||||
|
or begin >= display_buffer.range().end)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto& line : display_buffer.lines())
|
||||||
|
{
|
||||||
|
auto& range = line.range();
|
||||||
|
if (range.end <= begin or end < range.begin)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int beg_idx = -1, end_idx = -1;
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (begin >= atom_it->begin())
|
||||||
|
{
|
||||||
|
if (begin > atom_it->begin())
|
||||||
|
atom_it = ++line.split(atom_it, begin);
|
||||||
|
beg_idx = atom_it - line.begin();
|
||||||
|
}
|
||||||
|
if (end <= atom_it->end())
|
||||||
|
{
|
||||||
|
if (end < atom_it->end())
|
||||||
|
atom_it = line.split(atom_it, end);
|
||||||
|
end_idx = (atom_it - line.begin()) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (beg_idx != -1 and end_idx != -1)
|
||||||
|
func(line, beg_idx, end_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void apply_highlighter(const Context& context,
|
void apply_highlighter(const Context& context,
|
||||||
DisplayBuffer& display_buffer,
|
DisplayBuffer& display_buffer,
|
||||||
HighlightPass pass,
|
HighlightPass pass,
|
||||||
|
@ -1309,6 +1348,31 @@ void option_from_string(StringView str, InclusiveBufferRange& opt)
|
||||||
BufferCoord& get_first(RangeAndFace& r) { return std::get<0>(r).first; }
|
BufferCoord& get_first(RangeAndFace& r) { return std::get<0>(r).first; }
|
||||||
BufferCoord& get_last(RangeAndFace& r) { return std::get<0>(r).last; }
|
BufferCoord& get_last(RangeAndFace& r) { return std::get<0>(r).last; }
|
||||||
|
|
||||||
|
static void update_ranges_ifn(const Buffer& buffer, TimestampedList<RangeAndFace>& range_and_faces)
|
||||||
|
{
|
||||||
|
if (range_and_faces.prefix == buffer.timestamp())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto changes = buffer.changes_since(range_and_faces.prefix);
|
||||||
|
for (auto change_it = changes.begin(); change_it != changes.end(); )
|
||||||
|
{
|
||||||
|
auto forward_end = forward_sorted_until(change_it, changes.end());
|
||||||
|
auto backward_end = backward_sorted_until(change_it, changes.end());
|
||||||
|
|
||||||
|
if (forward_end >= backward_end)
|
||||||
|
{
|
||||||
|
update_forward({ change_it, forward_end }, range_and_faces.list);
|
||||||
|
change_it = forward_end;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
update_backward({ change_it, backward_end }, range_and_faces.list);
|
||||||
|
change_it = backward_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
range_and_faces.prefix = buffer.timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
struct RangesHighlighter : Highlighter
|
struct RangesHighlighter : Highlighter
|
||||||
{
|
{
|
||||||
RangesHighlighter(String option_name)
|
RangesHighlighter(String option_name)
|
||||||
|
@ -1348,29 +1412,53 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_ranges_ifn(const Buffer& buffer, TimestampedList<RangeAndFace>& range_and_faces)
|
const String m_option_name;
|
||||||
{
|
};
|
||||||
if (range_and_faces.prefix == buffer.timestamp())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto changes = buffer.changes_since(range_and_faces.prefix);
|
struct ReplaceRangesHighlighter : Highlighter
|
||||||
for (auto change_it = changes.begin(); change_it != changes.end(); )
|
{
|
||||||
{
|
ReplaceRangesHighlighter(String option_name)
|
||||||
auto forward_end = forward_sorted_until(change_it, changes.end());
|
: Highlighter{HighlightPass::Colorize}
|
||||||
auto backward_end = backward_sorted_until(change_it, changes.end());
|
, m_option_name{std::move(option_name)} {}
|
||||||
|
|
||||||
if (forward_end >= backward_end)
|
static HighlighterAndId create(HighlighterParameters params)
|
||||||
{
|
{
|
||||||
update_forward({ change_it, forward_end }, range_and_faces.list);
|
if (params.size() != 1)
|
||||||
change_it = forward_end;
|
throw runtime_error("wrong parameter count");
|
||||||
|
|
||||||
|
const String& option_name = params[0];
|
||||||
|
// throw if wrong option type
|
||||||
|
GlobalScope::instance().options()[option_name].get<TimestampedList<RangeAndFace>>();
|
||||||
|
|
||||||
|
return {"replace_ranges_" + params[0], make_unique<ReplaceRangesHighlighter>(option_name)};
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
private:
|
||||||
|
void do_highlight(const Context& context, HighlightPass, DisplayBuffer& display_buffer, BufferRange) override
|
||||||
{
|
{
|
||||||
update_backward({ change_it, backward_end }, range_and_faces.list);
|
auto& buffer = context.buffer();
|
||||||
change_it = backward_end;
|
auto& range_and_faces = context.options()[m_option_name].get_mutable<TimestampedList<RangeAndFace>>();
|
||||||
|
update_ranges_ifn(buffer, range_and_faces);
|
||||||
|
|
||||||
|
for (auto& range : range_and_faces.list)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto& r = std::get<0>(range);
|
||||||
|
if (buffer.is_valid(r.first) and buffer.is_valid(r.last))
|
||||||
|
{
|
||||||
|
auto replacement = parse_display_line(std::get<1>(range));
|
||||||
|
replace_range(display_buffer, r.first, buffer.char_next(r.last),
|
||||||
|
[&](DisplayLine& line, int beg_idx, int end_idx){
|
||||||
|
auto it = line.erase(line.begin() + beg_idx, line.begin() + end_idx);
|
||||||
|
for (auto& atom : replacement)
|
||||||
|
it = ++line.insert(it, std::move(atom));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
range_and_faces.prefix = buffer.timestamp();
|
catch (runtime_error&)
|
||||||
|
{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const String m_option_name;
|
const String m_option_name;
|
||||||
|
@ -1886,6 +1974,11 @@ void register_highlighters()
|
||||||
{ RangesHighlighter::create,
|
{ RangesHighlighter::create,
|
||||||
"Parameters: <option name>\n"
|
"Parameters: <option name>\n"
|
||||||
"Use the range-faces option given as parameter to highlight buffer\n" } });
|
"Use the range-faces option given as parameter to highlight buffer\n" } });
|
||||||
|
registry.insert({
|
||||||
|
"replace-ranges",
|
||||||
|
{ ReplaceRangesHighlighter::create,
|
||||||
|
"Parameters: <option name>\n"
|
||||||
|
"Use the range-faces option given as parameter to highlight buffer\n" } });
|
||||||
registry.insert({
|
registry.insert({
|
||||||
"line",
|
"line",
|
||||||
{ create_line_highlighter,
|
{ create_line_highlighter,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user