summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2020-04-06 11:13:24 +1000
committerMaxime Coste <mawww@kakoune.org>2020-04-06 11:23:47 +1000
commitf7a2ecfacb566a219d9deef3a5cfaa2d1c5bd404 (patch)
treeeb044d77d2c31c40b4b99767b22bca9e505f44ba /src
parentc585107ab5e7155f7da648c3752cf360f7156177 (diff)
Support empty ranges in replace-ranges highlighter
Diffstat (limited to 'src')
-rw-r--r--src/changes.hh35
-rw-r--r--src/highlighters.cc48
2 files changed, 47 insertions, 36 deletions
diff --git a/src/changes.hh b/src/changes.hh
index 5b64cbec..5ebb3ded 100644
--- a/src/changes.hh
+++ b/src/changes.hh
@@ -28,6 +28,21 @@ struct ForwardChangesTracker
const Buffer::Change* forward_sorted_until(const Buffer::Change* first, const Buffer::Change* last);
const Buffer::Change* backward_sorted_until(const Buffer::Change* first, const Buffer::Change* last);
+template<typename Range, typename AdvanceFunc>
+auto update_range(ForwardChangesTracker& changes_tracker, Range& range, AdvanceFunc&& advance_while_relevant)
+{
+ auto& first = get_first(range);
+ auto& last = get_last(range);
+ advance_while_relevant(first);
+ first = changes_tracker.get_new_coord_tolerant(first);
+
+ if (last < BufferCoord{0,0})
+ return;
+
+ advance_while_relevant(last);
+ last = changes_tracker.get_new_coord_tolerant(last);
+}
+
template<typename RangeContainer>
void update_forward(ConstArrayView<Buffer::Change> changes, RangeContainer& ranges)
{
@@ -39,15 +54,7 @@ void update_forward(ConstArrayView<Buffer::Change> changes, RangeContainer& rang
};
for (auto& range : ranges)
- {
- auto& first = get_first(range);
- auto& last = get_last(range);
- advance_while_relevant(first);
- first = changes_tracker.get_new_coord_tolerant(first);
-
- advance_while_relevant(last);
- last = changes_tracker.get_new_coord_tolerant(last);
- }
+ update_range(changes_tracker, range, advance_while_relevant);
}
template<typename RangeContainer>
@@ -69,15 +76,7 @@ void update_backward(ConstArrayView<Buffer::Change> changes, RangeContainer& ran
};
for (auto& range : ranges)
- {
- auto& first = get_first(range);
- auto& last = get_last(range);
- advance_while_relevant(first);
- first = changes_tracker.get_new_coord_tolerant(first);
-
- advance_while_relevant(last);
- last = changes_tracker.get_new_coord_tolerant(last);
- }
+ update_range(changes_tracker, range, advance_while_relevant);
}
template<typename RangeContainer>
diff --git a/src/highlighters.cc b/src/highlighters.cc
index 464f78cd..d3fe1164 100644
--- a/src/highlighters.cc
+++ b/src/highlighters.cc
@@ -89,8 +89,8 @@ void replace_range(DisplayBuffer& display_buffer,
BufferCoord begin, BufferCoord end, T func)
{
// tolerate begin > end as that can be triggered by wrong encodings
- if (begin >= end or end <= display_buffer.range().begin
- or begin >= display_buffer.range().end)
+ if (begin > end or end <= display_buffer.range().begin
+ or begin >= display_buffer.range().end)
return;
for (auto& line : display_buffer.lines())
@@ -112,7 +112,9 @@ void replace_range(DisplayBuffer& display_buffer,
atom_it = ++line.split(atom_it, begin);
beg_idx = atom_it - line.begin();
}
- if (end <= atom_it->end())
+ if (end == atom_it->begin())
+ end_idx = atom_it - line.begin();
+ else if (end <= atom_it->end())
{
if (end < atom_it->end())
atom_it = line.split(atom_it, end);
@@ -1448,8 +1450,15 @@ private:
String m_default_face;
};
+bool is_empty(const InclusiveBufferRange& range)
+{
+ return range.last < BufferCoord{0,0};
+}
+
String option_to_string(InclusiveBufferRange range)
{
+ if (is_empty(range))
+ return format("{}.{}+0", range.first.line+1, range.first.column+1);
return format("{}.{},{}.{}",
range.first.line+1, range.first.column+1,
range.last.line+1, range.last.column+1);
@@ -1468,12 +1477,17 @@ InclusiveBufferRange option_from_string(Meta::Type<InclusiveBufferRange>, String
const BufferCoord first{str_to_int({str.begin(), dot_beg}) - 1,
str_to_int({dot_beg+1, sep}) - 1};
- const bool len = (*sep == '+');
- const BufferCoord last{len ? first.line : str_to_int({sep+1, dot_end}) - 1,
- len ? first.column + str_to_int({sep+1, str.end()}) - 1
- : str_to_int({dot_end+1, str.end()}) - 1 };
+ if (first.line < 0 or first.column < 0)
+ throw runtime_error("coordinates elements should be >= 1");
+
+ if (*sep == '+')
+ {
+ auto len = str_to_int({sep+1, str.end()});
+ return {first, len == 0 ? BufferCoord{-1,-1} : BufferCoord{first.line, first.column + len}};
+ }
- if (first.line < 0 or first.column < 0 or last.line < 0 or last.column < 0)
+ const BufferCoord last{str_to_int({sep+1, dot_end}) - 1, str_to_int({dot_end+1, str.end()}) - 1};
+ if (last.line < 0 or last.column < 0)
throw runtime_error("coordinates elements should be >= 1");
return { std::min(first, last), std::max(first, last) };
@@ -1522,14 +1536,13 @@ private:
auto& range_and_faces = context.context.options()[m_option_name].get_mutable<RangeAndStringList>();
update_ranges(buffer, range_and_faces.prefix, range_and_faces.list);
- for (auto& range : range_and_faces.list)
+ for (auto& [range, face] : range_and_faces.list)
{
try
{
- auto& r = std::get<0>(range);
- if (buffer.is_valid(r.first) and (buffer.is_valid(r.last) and not buffer.is_end(r.last)))
- highlight_range(display_buffer, r.first, buffer.char_next(r.last), false,
- apply_face(context.context.faces()[std::get<1>(range)]));
+ if (buffer.is_valid(range.first) and (buffer.is_valid(range.last) and not buffer.is_end(range.last)))
+ highlight_range(display_buffer, range.first, buffer.char_next(range.last), false,
+ apply_face(context.context.faces()[face]));
}
catch (runtime_error&)
{}
@@ -1564,15 +1577,14 @@ private:
auto& range_and_faces = context.context.options()[m_option_name].get_mutable<RangeAndStringList>();
update_ranges(buffer, range_and_faces.prefix, range_and_faces.list);
- for (auto& range : range_and_faces.list)
+ for (auto& [range, spec] : range_and_faces.list)
{
try
{
- auto& r = std::get<0>(range);
- if (buffer.is_valid(r.first) and buffer.is_valid(r.last))
+ if (buffer.is_valid(range.first) and (buffer.is_valid(range.last) or is_empty(range)))
{
- auto replacement = parse_display_line(std::get<1>(range), context.context.faces());
- replace_range(display_buffer, r.first, buffer.char_next(r.last),
+ auto replacement = parse_display_line(spec, context.context.faces());
+ replace_range(display_buffer, range.first, is_empty(range) ? range.first : buffer.char_next(range.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)