summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2017-01-13 13:45:46 +0000
committerMaxime Coste <mawww@kakoune.org>2017-01-13 13:52:55 +0000
commite7e72747edfcba76f7fc36e2e345577ffeb47eab (patch)
treec3fff0f3d12dd95ca1a5e34406c5b9924493714f /src
parent5ad44995036274989f82f62b9ff2135687b00394 (diff)
Update ranges highlighter options according to buffer changes
Diffstat (limited to 'src')
-rw-r--r--src/changes.cc97
-rw-r--r--src/changes.hh89
-rw-r--r--src/highlighters.cc25
-rw-r--r--src/selection.cc165
4 files changed, 215 insertions, 161 deletions
diff --git a/src/changes.cc b/src/changes.cc
new file mode 100644
index 00000000..7feb82ec
--- /dev/null
+++ b/src/changes.cc
@@ -0,0 +1,97 @@
+#include "changes.hh"
+
+namespace Kakoune
+{
+void ForwardChangesTracker::update(const Buffer::Change& change)
+{
+ kak_assert(change.begin >= cur_pos);
+
+ if (change.type == Buffer::Change::Insert)
+ {
+ old_pos = get_old_coord(change.begin);
+ cur_pos = change.end;
+ }
+ else if (change.type == Buffer::Change::Erase)
+ {
+ old_pos = get_old_coord(change.end);
+ cur_pos = change.begin;
+ }
+}
+
+void ForwardChangesTracker::update(const Buffer& buffer, size_t& timestamp)
+{
+ for (auto& change : buffer.changes_since(timestamp))
+ update(change);
+ timestamp = buffer.timestamp();
+}
+
+BufferCoord ForwardChangesTracker::get_old_coord(BufferCoord coord) const
+{
+ kak_assert(cur_pos <= coord);
+ auto pos_change = cur_pos - old_pos;
+ if (cur_pos.line == coord.line)
+ {
+ kak_assert(pos_change.column <= coord.column);
+ coord.column -= pos_change.column;
+ }
+ coord.line -= pos_change.line;
+ kak_assert(old_pos <= coord);
+ return coord;
+}
+
+BufferCoord ForwardChangesTracker::get_new_coord(BufferCoord coord) const
+{
+ kak_assert(old_pos <= coord);
+ auto pos_change = cur_pos - old_pos;
+ if (old_pos.line == coord.line)
+ {
+ kak_assert(-pos_change.column <= coord.column);
+ coord.column += pos_change.column;
+ }
+ coord.line += pos_change.line;
+ kak_assert(cur_pos <= coord);
+ return coord;
+}
+
+BufferCoord ForwardChangesTracker::get_new_coord_tolerant(BufferCoord coord) const
+{
+ if (coord < old_pos)
+ return cur_pos;
+ return get_new_coord(coord);
+}
+
+bool ForwardChangesTracker::relevant(const Buffer::Change& change, BufferCoord old_coord) const
+{
+ auto new_coord = get_new_coord_tolerant(old_coord);
+ return change.type == Buffer::Change::Insert ? change.begin <= new_coord
+ : change.begin < new_coord;
+}
+
+const Buffer::Change* forward_sorted_until(const Buffer::Change* first, const Buffer::Change* last)
+{
+ if (first != last) {
+ const Buffer::Change* next = first;
+ while (++next != last) {
+ const auto& ref = first->type == Buffer::Change::Insert ? first->end : first->begin;
+ if (next->begin <= ref)
+ return next;
+ first = next;
+ }
+ }
+ return last;
+}
+
+const Buffer::Change* backward_sorted_until(const Buffer::Change* first, const Buffer::Change* last)
+{
+ if (first != last) {
+ const Buffer::Change* next = first;
+ while (++next != last) {
+ if (first->begin <= next->end)
+ return next;
+ first = next;
+ }
+ }
+ return last;
+}
+
+}
diff --git a/src/changes.hh b/src/changes.hh
new file mode 100644
index 00000000..963ca786
--- /dev/null
+++ b/src/changes.hh
@@ -0,0 +1,89 @@
+#ifndef changes_hh_INCLUDED
+#define changes_hh_INCLUDED
+
+#include "buffer.hh"
+#include "coord.hh"
+
+namespace Kakoune
+{
+
+// This tracks position changes for changes that are done
+// in a forward way (each change takes place at a position)
+// *after* the previous one.
+struct ForwardChangesTracker
+{
+ BufferCoord cur_pos; // last change position at current modification
+ BufferCoord old_pos; // last change position at start
+
+ void update(const Buffer::Change& change);
+ void update(const Buffer& buffer, size_t& timestamp);
+
+ BufferCoord get_old_coord(BufferCoord coord) const;
+ BufferCoord get_new_coord(BufferCoord coord) const;
+ BufferCoord get_new_coord_tolerant(BufferCoord coord) const;
+
+ bool relevant(const Buffer::Change& change, BufferCoord old_coord) const;
+};
+
+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 RangeContainer>
+void update_forward(ConstArrayView<Buffer::Change> changes, RangeContainer& ranges)
+{
+ ForwardChangesTracker changes_tracker;
+
+ auto change_it = changes.begin();
+ auto advance_while_relevant = [&](const BufferCoord& pos) mutable {
+ while (change_it != changes.end() and changes_tracker.relevant(*change_it, pos))
+ changes_tracker.update(*change_it++);
+ };
+
+ 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);
+ }
+}
+
+template<typename RangeContainer>
+void update_backward(ConstArrayView<Buffer::Change> changes, RangeContainer& ranges)
+{
+ ForwardChangesTracker changes_tracker;
+
+ using ReverseIt = std::reverse_iterator<const Buffer::Change*>;
+ auto change_it = ReverseIt(changes.end());
+ auto change_end = ReverseIt(changes.begin());
+ auto advance_while_relevant = [&](const BufferCoord& pos) mutable {
+ while (change_it != change_end)
+ {
+ auto change = *change_it;
+ change.begin = changes_tracker.get_new_coord(change.begin);
+ change.end = changes_tracker.get_new_coord(change.end);
+ if (not changes_tracker.relevant(change, pos))
+ break;
+ changes_tracker.update(change);
+ ++change_it;
+ }
+ };
+
+ 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);
+ }
+}
+
+}
+
+#endif // changes_hh_INCLUDED
diff --git a/src/highlighters.cc b/src/highlighters.cc
index fdb85c69..00f47297 100644
--- a/src/highlighters.cc
+++ b/src/highlighters.cc
@@ -2,6 +2,7 @@
#include "assert.hh"
#include "buffer_utils.hh"
+#include "changes.hh"
#include "context.hh"
#include "containers.hh"
#include "command_manager.hh"
@@ -992,6 +993,9 @@ HighlighterAndId create_flag_lines_highlighter(HighlighterParameters params)
return {"hlflags_" + params[1], make_simple_highlighter(func) };
}
+BufferCoord& get_first(RangeAndFace& r) { return std::get<0>(r).begin; }
+BufferCoord& get_last(RangeAndFace& r) { return std::get<0>(r).end; }
+
HighlighterAndId create_ranges_highlighter(HighlighterParameters params)
{
if (params.size() != 1)
@@ -1011,8 +1015,25 @@ HighlighterAndId create_ranges_highlighter(HighlighterParameters params)
auto& buffer = context.buffer();
if (range_and_faces.prefix != buffer.timestamp())
{
- // TODO: update ranges to current timestamp
- return;
+ auto changes = buffer.changes_since(range_and_faces.prefix);
+ auto change_it = changes.begin();
+ while (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 }, ranges);
+ change_it = forward_end;
+ }
+ else
+ {
+ update_backward({ change_it, backward_end }, ranges);
+ change_it = backward_end;
+ }
+ }
+ range_and_faces.prefix = buffer.timestamp();
}
for (auto& range : ranges)
diff --git a/src/selection.cc b/src/selection.cc
index 5501bbd0..b0474e67 100644
--- a/src/selection.cc
+++ b/src/selection.cc
@@ -1,7 +1,8 @@
#include "selection.hh"
-#include "utf8.hh"
#include "buffer_utils.hh"
+#include "changes.hh"
+#include "utf8.hh"
namespace Kakoune
{
@@ -96,164 +97,10 @@ Iterator merge_overlapping(Iterator begin, Iterator end, size_t& main, OverlapsF
return begin + i + 1;
}
-// This tracks position changes for changes that are done
-// in a forward way (each change takes place at a position)
-// *after* the previous one.
-struct ForwardChangesTracker
-{
- BufferCoord cur_pos; // last change position at current modification
- BufferCoord old_pos; // last change position at start
-
- void update(const Buffer::Change& change)
- {
- kak_assert(change.begin >= cur_pos);
-
- if (change.type == Buffer::Change::Insert)
- {
- old_pos = get_old_coord(change.begin);
- cur_pos = change.end;
- }
- else if (change.type == Buffer::Change::Erase)
- {
- old_pos = get_old_coord(change.end);
- cur_pos = change.begin;
- }
- }
-
- void update(const Buffer& buffer, size_t& timestamp)
- {
- for (auto& change : buffer.changes_since(timestamp))
- update(change);
- timestamp = buffer.timestamp();
- }
-
- BufferCoord get_old_coord(BufferCoord coord) const
- {
- kak_assert(cur_pos <= coord);
- auto pos_change = cur_pos - old_pos;
- if (cur_pos.line == coord.line)
- {
- kak_assert(pos_change.column <= coord.column);
- coord.column -= pos_change.column;
- }
- coord.line -= pos_change.line;
- kak_assert(old_pos <= coord);
- return coord;
- }
-
- BufferCoord get_new_coord(BufferCoord coord) const
- {
- kak_assert(old_pos <= coord);
- auto pos_change = cur_pos - old_pos;
- if (old_pos.line == coord.line)
- {
- kak_assert(-pos_change.column <= coord.column);
- coord.column += pos_change.column;
- }
- coord.line += pos_change.line;
- kak_assert(cur_pos <= coord);
- return coord;
- }
-
- BufferCoord get_new_coord_tolerant(BufferCoord coord) const
- {
- if (coord < old_pos)
- return cur_pos;
- return get_new_coord(coord);
- }
-
- bool relevant(const Buffer::Change& change, BufferCoord old_coord) const
- {
- auto new_coord = get_new_coord_tolerant(old_coord);
- return change.type == Buffer::Change::Insert ? change.begin <= new_coord
- : change.begin < new_coord;
- }
-};
-
-const Buffer::Change* forward_sorted_until(const Buffer::Change* first, const Buffer::Change* last)
-{
- if (first != last) {
- const Buffer::Change* next = first;
- while (++next != last) {
- const auto& ref = first->type == Buffer::Change::Insert ? first->end : first->begin;
- if (next->begin <= ref)
- return next;
- first = next;
- }
- }
- return last;
}
-const Buffer::Change* backward_sorted_until(const Buffer::Change* first, const Buffer::Change* last)
-{
- if (first != last) {
- const Buffer::Change* next = first;
- while (++next != last) {
- if (first->begin <= next->end)
- return next;
- first = next;
- }
- }
- return last;
-}
-
-void update_forward(ConstArrayView<Buffer::Change> changes, Vector<Selection>& selections)
-{
- ForwardChangesTracker changes_tracker;
-
- auto change_it = changes.begin();
- auto advance_while_relevant = [&](const BufferCoord& pos) mutable {
- while (change_it != changes.end() and changes_tracker.relevant(*change_it, pos))
- changes_tracker.update(*change_it++);
- };
-
- for (auto& sel : selections)
- {
- auto& sel_min = sel.min();
- auto& sel_max = sel.max();
- advance_while_relevant(sel_min);
- sel_min = changes_tracker.get_new_coord_tolerant(sel_min);
-
- advance_while_relevant(sel_max);
- sel_max = changes_tracker.get_new_coord_tolerant(sel_max);
- }
- kak_assert(std::is_sorted(selections.begin(), selections.end(), compare_selections));
-}
-
-void update_backward(ConstArrayView<Buffer::Change> changes, Vector<Selection>& selections)
-{
- ForwardChangesTracker changes_tracker;
-
- using ReverseIt = std::reverse_iterator<const Buffer::Change*>;
- auto change_it = ReverseIt(changes.end());
- auto change_end = ReverseIt(changes.begin());
- auto advance_while_relevant = [&](const BufferCoord& pos) mutable {
- while (change_it != change_end)
- {
- auto change = *change_it;
- change.begin = changes_tracker.get_new_coord(change.begin);
- change.end = changes_tracker.get_new_coord(change.end);
- if (not changes_tracker.relevant(change, pos))
- break;
- changes_tracker.update(change);
- ++change_it;
- }
- };
-
- for (auto& sel : selections)
- {
- auto& sel_min = sel.min();
- auto& sel_max = sel.max();
- advance_while_relevant(sel_min);
- sel_min = changes_tracker.get_new_coord_tolerant(sel_min);
-
- advance_while_relevant(sel_max);
- sel_max = changes_tracker.get_new_coord_tolerant(sel_max);
- }
- kak_assert(std::is_sorted(selections.begin(), selections.end(), compare_selections));
-}
-
-}
+BufferCoord& get_first(Selection& sel) { return sel.min(); }
+BufferCoord& get_last(Selection& sel) { return sel.max(); }
Vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp)
{
@@ -367,11 +214,11 @@ void update_selections(Vector<Selection>& selections, size_t& main, Buffer& buff
update_backward({ change_it, backward_end }, selections);
change_it = backward_end;
}
+ kak_assert(std::is_sorted(selections.begin(), selections.end(),
+ compare_selections));
selections.erase(
merge_overlapping(selections.begin(), selections.end(),
main, overlaps), selections.end());
- kak_assert(std::is_sorted(selections.begin(), selections.end(),
- compare_selections));
}
for (auto& sel : selections)
clamp(sel, buffer);