diff options
| author | Maxime Coste <frrrwww@gmail.com> | 2014-05-13 23:22:54 +0100 |
|---|---|---|
| committer | Maxime Coste <frrrwww@gmail.com> | 2014-05-13 23:22:54 +0100 |
| commit | 11d9b607668d56c8deaf9062d48d9ce7aa6f5928 (patch) | |
| tree | c7473586d11e33c2d2841ef459b3feed698be3d0 /src | |
| parent | a06094b00e92d34e9f0be6abf80e5f4ce64998b3 (diff) | |
Make it harder to have an invalid SelectionList
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynamic_selection_list.cc | 6 | ||||
| -rw-r--r-- | src/normal.cc | 47 | ||||
| -rw-r--r-- | src/selection.cc | 28 | ||||
| -rw-r--r-- | src/selection.hh | 16 | ||||
| -rw-r--r-- | src/selectors.cc | 6 |
5 files changed, 53 insertions, 50 deletions
diff --git a/src/dynamic_selection_list.cc b/src/dynamic_selection_list.cc index 4087bb0c..f49b36c7 100644 --- a/src/dynamic_selection_list.cc +++ b/src/dynamic_selection_list.cc @@ -19,14 +19,12 @@ DynamicSelectionList& DynamicSelectionList::operator=(SelectionList selections) void DynamicSelectionList::on_insert(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end) { - update_insert(begin, end, at_end); - set_timestamp(buffer.timestamp()); + update(); } void DynamicSelectionList::on_erase(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end) { - update_erase(begin, end, at_end); - set_timestamp(buffer.timestamp()); + update(); } } diff --git a/src/normal.cc b/src/normal.cc index 7ac51ad5..15068fce 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -739,7 +739,7 @@ void split_lines(Context& context, int) { auto& selections = context.selections(); auto& buffer = context.buffer(); - SelectionList res(context.buffer()); + std::vector<Selection> res; for (auto& sel : selections) { if (sel.anchor().line == sel.cursor().line) @@ -754,14 +754,13 @@ void split_lines(Context& context, int) res.push_back({line, {line, buffer[line].length()-1}}); res.push_back({max.line, max}); } - res.set_main_index(res.size() - 1); selections = std::move(res); } void join_select_spaces(Context& context, int) { auto& buffer = context.buffer(); - SelectionList selections(buffer); + std::vector<Selection> selections; for (auto& sel : context.selections()) { for (LineCount line = sel.min().line; line <= sel.max().line; ++line) @@ -776,7 +775,6 @@ void join_select_spaces(Context& context, int) } if (selections.empty()) return; - selections.sort_and_merge_overlapping(); context.selections() = selections; ScopedEdition edition(context); insert<InsertMode::Replace>(buffer, context.selections(), " "); @@ -801,7 +799,7 @@ void keep(Context& context, int) if (ex.empty()) return; const Buffer& buffer = context.buffer(); - SelectionList keep(buffer); + std::vector<Selection> keep; for (auto& sel : context.selections()) { if (boost::regex_search(buffer.iterator_at(sel.min()), @@ -823,7 +821,7 @@ void keep_pipe(Context& context, int) return; const Buffer& buffer = context.buffer(); auto& shell_manager = ShellManager::instance(); - SelectionList keep(buffer); + std::vector<Selection> keep; for (auto& sel : context.selections()) { int status = 0; @@ -844,7 +842,7 @@ void indent(Context& context, int) String indent = indent_width == 0 ? "\t" : String{' ', indent_width}; auto& buffer = context.buffer(); - SelectionList sels(buffer); + std::vector<Selection> sels; for (auto& sel : context.selections()) { for (auto line = sel.min().line; line < sel.max().line+1; ++line) @@ -856,7 +854,8 @@ void indent(Context& context, int) if (not sels.empty()) { ScopedEdition edition(context); - insert<InsertMode::Insert>(buffer, sels, indent); + SelectionList selections{buffer, std::move(sels)}; + insert<InsertMode::Insert>(buffer, selections, indent); } } @@ -869,7 +868,7 @@ void deindent(Context& context, int) indent_width = tabstop; auto& buffer = context.buffer(); - SelectionList sels(buffer); + std::vector<Selection> sels; for (auto& sel : context.selections()) { for (auto line = sel.min().line; line < sel.max().line+1; ++line) @@ -900,7 +899,8 @@ void deindent(Context& context, int) if (not sels.empty()) { ScopedEdition edition(context); - erase(context.buffer(), sels); + SelectionList selections{context.buffer(), std::move(sels)}; + erase(context.buffer(), selections); } } @@ -1238,16 +1238,16 @@ void spaces_to_tabs(Context& context, int ts) } } -static SelectionList compute_modified_ranges(const Buffer& buffer, size_t timestamp) +static boost::optional<SelectionList> compute_modified_ranges(const Buffer& buffer, size_t timestamp) { - SelectionList ranges(buffer); + std::vector<Selection> ranges; for (auto& change : buffer.changes_since(timestamp)) { const ByteCoord& begin = change.begin; const ByteCoord& end = change.end; if (change.type == Buffer::Change::Insert) { - ranges.update_insert(begin, end, change.at_end); + update_insert(ranges, begin, end, change.at_end); auto it = std::upper_bound(ranges.begin(), ranges.end(), begin, [](ByteCoord c, const Selection& sel) { return c < sel.min(); }); @@ -1255,7 +1255,7 @@ static SelectionList compute_modified_ranges(const Buffer& buffer, size_t timest } else { - ranges.update_erase(begin, end, change.at_end); + update_erase(ranges, begin, end, change.at_end); auto pos = begin; if (change.at_end) pos = begin.column ? ByteCoord{begin.line, begin.column - 1} @@ -1267,23 +1267,22 @@ static SelectionList compute_modified_ranges(const Buffer& buffer, size_t timest } } if (ranges.empty()) - return ranges; + return {}; - ranges.set_timestamp(buffer.timestamp()); - ranges.set_main_index(ranges.size() - 1); + SelectionList result{buffer, std::move(ranges)}; auto touches = [&](const Selection& lhs, const Selection& rhs) { return lhs.min() <= rhs.min() ? buffer.char_next(lhs.max()) >= rhs.min() : lhs.min() <= buffer.char_next(rhs.max()); }; - ranges.merge_overlapping(touches); + result.merge_overlapping(touches); - for (auto& sel : ranges) + for (auto& sel : result) { if (sel.anchor() != sel.cursor()) sel.cursor() = buffer.char_prev(sel.cursor()); } - return ranges; + return result; } void undo(Context& context, int) @@ -1294,8 +1293,8 @@ void undo(Context& context, int) if (res) { auto ranges = compute_modified_ranges(buffer, timestamp); - if (not ranges.empty()) - context.selections() = std::move(ranges); + if (ranges) + context.selections() = std::move(*ranges); } else if (not res) context.print_status({ "nothing left to undo", get_color("Information") }); @@ -1310,8 +1309,8 @@ void redo(Context& context, int) if (res) { auto ranges = compute_modified_ranges(buffer, timestamp); - if (not ranges.empty()) - context.selections() = std::move(ranges); + if (ranges) + context.selections() = std::move(*ranges); } else if (not res) diff --git a/src/selection.cc b/src/selection.cc index 895c1f96..3dee22ec 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -18,7 +18,7 @@ namespace { template<template <bool, bool> class UpdateFunc> -void on_buffer_change(SelectionList& sels, +void on_buffer_change(std::vector<Selection>& sels, ByteCoord begin, ByteCoord end, bool at_end, LineCount end_line) { auto update_beg = std::lower_bound(sels.begin(), sels.end(), begin, @@ -101,14 +101,11 @@ struct UpdateErase } -SelectionList::SelectionList(const Buffer& buffer) - : m_buffer(&buffer), m_timestamp(buffer.timestamp()) -{ -} - SelectionList::SelectionList(const Buffer& buffer, Selection s, size_t timestamp) : m_buffer(&buffer), m_selections({ s }), m_timestamp(timestamp) -{} +{ + check_invariant(); +} SelectionList::SelectionList(const Buffer& buffer, Selection s) : SelectionList(buffer, s, buffer.timestamp()) @@ -116,20 +113,23 @@ SelectionList::SelectionList(const Buffer& buffer, Selection s) SelectionList::SelectionList(const Buffer& buffer, std::vector<Selection> s, size_t timestamp) : m_buffer(&buffer), m_selections(std::move(s)), m_timestamp(timestamp) -{} +{ + kak_assert(size() > 0); + check_invariant(); +} SelectionList::SelectionList(const Buffer& buffer, std::vector<Selection> s) : SelectionList(buffer, std::move(s), buffer.timestamp()) {} -void SelectionList::update_insert(ByteCoord begin, ByteCoord end, bool at_end) +void update_insert(std::vector<Selection>& sels, ByteCoord begin, ByteCoord end, bool at_end) { - on_buffer_change<UpdateInsert>(*this, begin, end, at_end, begin.line); + on_buffer_change<UpdateInsert>(sels, begin, end, at_end, begin.line); } -void SelectionList::update_erase(ByteCoord begin, ByteCoord end, bool at_end) +void update_erase(std::vector<Selection>& sels, ByteCoord begin, ByteCoord end, bool at_end) { - on_buffer_change<UpdateErase>(*this, begin, end, at_end, end.line); + on_buffer_change<UpdateErase>(sels, begin, end, at_end, end.line); } void SelectionList::update() @@ -137,9 +137,9 @@ void SelectionList::update() for (auto& change : m_buffer->changes_since(m_timestamp)) { if (change.type == Buffer::Change::Insert) - update_insert(change.begin, change.end, change.at_end); + update_insert(m_selections, change.begin, change.end, change.at_end); else - update_erase(change.begin, change.end, change.at_end); + update_erase(m_selections, change.begin, change.end, change.at_end); } m_timestamp = m_buffer->timestamp(); diff --git a/src/selection.hh b/src/selection.hh index 9b3f747a..f8727b90 100644 --- a/src/selection.hh +++ b/src/selection.hh @@ -57,15 +57,11 @@ static bool compare_selections(const Selection& lhs, const Selection& rhs) struct SelectionList { - SelectionList(const Buffer& buffer); SelectionList(const Buffer& buffer, Selection s); SelectionList(const Buffer& buffer, Selection s, size_t timestamp); SelectionList(const Buffer& buffer, std::vector<Selection> s); SelectionList(const Buffer& buffer, std::vector<Selection> s, size_t timestamp); - void update_insert(ByteCoord begin, ByteCoord end, bool at_end); - void update_erase(ByteCoord begin, ByteCoord end, bool at_end); - void update(); void check_invariant() const; @@ -83,6 +79,15 @@ struct SelectionList Selection& operator[](size_t i) { return m_selections[i]; } const Selection& operator[](size_t i) const { return m_selections[i]; } + SelectionList& operator=(std::vector<Selection> list) + { + m_selections = std::move(list); + m_main = size()-1; + sort_and_merge_overlapping(); + check_invariant(); + return *this; + } + using iterator = std::vector<Selection>::iterator; iterator begin() { return m_selections.begin(); } iterator end() { return m_selections.end(); } @@ -148,6 +153,9 @@ private: size_t m_timestamp; }; +void update_insert(std::vector<Selection>& sels, ByteCoord begin, ByteCoord end, bool at_end); +void update_erase(std::vector<Selection>& sels, ByteCoord begin, ByteCoord end, bool at_end); + } #endif // selection_hh_INCLUDED diff --git a/src/selectors.cc b/src/selectors.cc index 40db98c9..2e823d9d 100644 --- a/src/selectors.cc +++ b/src/selectors.cc @@ -437,7 +437,7 @@ void select_whole_buffer(const Buffer& buffer, SelectionList& selections) void select_all_matches(const Buffer& buffer, SelectionList& selections, const Regex& regex) { - SelectionList result(buffer); + std::vector<Selection> result; for (auto& sel : selections) { auto sel_end = utf8::next(buffer.iterator_at(sel.max())); @@ -463,14 +463,13 @@ void select_all_matches(const Buffer& buffer, SelectionList& selections, } if (result.empty()) throw runtime_error("nothing selected"); - result.set_main_index(result.size() - 1); selections = std::move(result); } void split_selections(const Buffer& buffer, SelectionList& selections, const Regex& regex) { - SelectionList result(buffer); + std::vector<Selection> result; for (auto& sel : selections) { auto begin = buffer.iterator_at(sel.min()); @@ -489,7 +488,6 @@ void split_selections(const Buffer& buffer, SelectionList& selections, if (begin.coord() <= sel.max()) result.push_back({ begin.coord(), sel.max() }); } - result.set_main_index(result.size() - 1); selections = std::move(result); } |
