diff options
| author | Maxime Coste <mawww@kakoune.org> | 2020-04-06 11:13:24 +1000 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2020-04-06 11:23:47 +1000 |
| commit | f7a2ecfacb566a219d9deef3a5cfaa2d1c5bd404 (patch) | |
| tree | eb044d77d2c31c40b4b99767b22bca9e505f44ba /src | |
| parent | c585107ab5e7155f7da648c3752cf360f7156177 (diff) | |
Support empty ranges in replace-ranges highlighter
Diffstat (limited to 'src')
| -rw-r--r-- | src/changes.hh | 35 | ||||
| -rw-r--r-- | src/highlighters.cc | 48 |
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) |
