diff --git a/src/context.cc b/src/context.cc index 9dcc87e4..e909f1f5 100644 --- a/src/context.cc +++ b/src/context.cc @@ -21,7 +21,7 @@ Buffer& Context::buffer() const { if (not has_buffer()) throw runtime_error("no buffer in context"); - return (*m_selections).registry(); + return const_cast((*m_selections).buffer()); } Window& Context::window() const @@ -175,7 +175,7 @@ void Context::change_buffer(Buffer& buffer) if (has_client()) client().change_buffer(buffer); else - m_selections = DynamicSelectionList{ { buffer, Selection{} } }; + m_selections = SelectionList{buffer, Selection{}}; if (has_input_handler()) input_handler().reset_normal_mode(); } @@ -184,14 +184,13 @@ SelectionList& Context::selections() { if (not m_selections) throw runtime_error("no selections in context"); + (*m_selections).update(); return *m_selections; } const SelectionList& Context::selections() const { - if (not m_selections) - throw runtime_error("no selections in context"); - return *m_selections; + return const_cast(*this).selections(); } std::vector Context::selections_content() const diff --git a/src/context.hh b/src/context.hh index 786386e2..90961216 100644 --- a/src/context.hh +++ b/src/context.hh @@ -1,7 +1,7 @@ #ifndef context_hh_INCLUDED #define context_hh_INCLUDED -#include "dynamic_selection_list.hh" +#include "selection.hh" #include @@ -85,7 +85,7 @@ private: safe_ptr m_client; friend class Client; - boost::optional m_selections; + boost::optional m_selections; String m_name; diff --git a/src/dynamic_selection_list.cc b/src/dynamic_selection_list.cc deleted file mode 100644 index f49b36c7..00000000 --- a/src/dynamic_selection_list.cc +++ /dev/null @@ -1,30 +0,0 @@ -#include "dynamic_selection_list.hh" - -namespace Kakoune -{ - -DynamicSelectionList::DynamicSelectionList(SelectionList selections) - : SelectionList(std::move(selections)), - BufferChangeListener_AutoRegister(const_cast(buffer())) -{ - check_invariant(); -} - -DynamicSelectionList& DynamicSelectionList::operator=(SelectionList selections) -{ - SelectionList::operator=(std::move(selections)); - check_invariant(); - return *this; -} - -void DynamicSelectionList::on_insert(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end) -{ - update(); -} - -void DynamicSelectionList::on_erase(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end) -{ - update(); -} - -} diff --git a/src/dynamic_selection_list.hh b/src/dynamic_selection_list.hh deleted file mode 100644 index 65f37915..00000000 --- a/src/dynamic_selection_list.hh +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef dynamic_selection_list_hh_INCLUDED -#define dynamic_selection_list_hh_INCLUDED - -#include "selection.hh" - -namespace Kakoune -{ - -class DynamicSelectionList : public SelectionList, - public BufferChangeListener_AutoRegister -{ -public: - using iterator = SelectionList::iterator; - using const_iterator = SelectionList::const_iterator; - - DynamicSelectionList(SelectionList selections); - - DynamicSelectionList& operator=(SelectionList selections); - - using SelectionList::buffer; - -private: - void on_insert(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end) override; - void on_erase(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end) override; -}; - -} - -#endif // dynamic_selection_list_hh_INCLUDED - diff --git a/src/input_handler.cc b/src/input_handler.cc index 62e3068f..08cd7f44 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -764,6 +764,7 @@ private: size_t index = std::min(i, strings.size()-1); buffer.insert(buffer.iterator_at(selections[i].cursor()), strings[index]); + selections.update(); } } @@ -771,8 +772,12 @@ private: { auto str = codepoint_to_str(key); auto& buffer = context().buffer(); - for (auto& sel : context().selections()) + auto& selections = context().selections(); + for (auto& sel : selections) + { buffer.insert(buffer.iterator_at(sel.cursor()), str); + selections.update(); + } context().hooks().run_hook("InsertChar", str, context()); } @@ -829,6 +834,8 @@ private: anchor = buffer.char_prev(anchor); if (buffer.is_end(cursor)) cursor = buffer.char_prev(cursor); + + selections.update(); sel.anchor() = anchor; sel.cursor() = cursor; } diff --git a/src/insert_completer.cc b/src/insert_completer.cc index 7b7d52fe..def3b951 100644 --- a/src/insert_completer.cc +++ b/src/insert_completer.cc @@ -185,13 +185,14 @@ void InsertCompleter::select(int offset) if (m_current_candidate < 0) m_current_candidate += m_matching_candidates.size(); const String& candidate = m_matching_candidates[m_current_candidate]; - const auto& cursor_pos = m_context.selections().main().cursor(); + auto& selections = m_context.selections(); + const auto& cursor_pos = selections.main().cursor(); const auto prefix_len = buffer.distance(m_completions.begin, cursor_pos); const auto suffix_len = std::max(0_byte, buffer.distance(cursor_pos, m_completions.end)); const auto buffer_len = buffer.byte_count(); auto ref = buffer.string(m_completions.begin, m_completions.end); - for (auto& sel : m_context.selections()) + for (auto& sel : selections) { auto offset = buffer.offset(sel.cursor()); auto pos = buffer.iterator_at(sel.cursor()); @@ -200,6 +201,7 @@ void InsertCompleter::select(int offset) { pos = buffer.erase(pos - prefix_len, pos + suffix_len); buffer.insert(pos, candidate); + const_cast(selections).update(); } } m_completions.end = cursor_pos; diff --git a/src/normal.cc b/src/normal.cc index 14526d2f..a8386b32 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -70,6 +70,7 @@ void insert(Buffer& buffer, SelectionList& selections, const String& str) { auto pos = prepare_insert(buffer, sel); pos = buffer.insert(pos, str); + selections.update(); if (mode == InsertMode::Replace and pos != buffer.end()) { sel.anchor() = pos.coord(); @@ -93,6 +94,7 @@ void insert(Buffer& buffer, SelectionList& selections, memoryview string auto pos = prepare_insert(buffer, sel); const String& str = strings[std::min(i, strings.size()-1)]; pos = buffer.insert(pos, str); + selections.update(); if (mode == InsertMode::Replace and pos != buffer.end()) { sel.anchor() = pos.coord(); diff --git a/src/selection.cc b/src/selection.cc index 0d90cc35..746253f9 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -134,6 +134,9 @@ void update_erase(std::vector& sels, ByteCoord begin, ByteCoord end, void SelectionList::update() { + if (m_timestamp == m_buffer->timestamp()) + return; + for (auto& change : m_buffer->changes_since(m_timestamp)) { if (change.type == Buffer::Change::Insert) @@ -141,9 +144,10 @@ void SelectionList::update() else update_erase(m_selections, change.begin, change.end, change.at_end); } - m_timestamp = m_buffer->timestamp(); check_invariant(); + + m_timestamp = m_buffer->timestamp(); } void SelectionList::check_invariant() const @@ -152,12 +156,11 @@ void SelectionList::check_invariant() const auto& buffer = this->buffer(); kak_assert(size() > 0); kak_assert(m_main < size()); - for (size_t i = 0; i+1 < size(); ++ i) - kak_assert((*this)[i].min() <= (*this)[i+1].min()); - for (size_t i = 0; i < size(); ++i) { auto& sel = (*this)[i]; + if (i+1 < size()) + kak_assert((*this)[i].min() <= (*this)[i+1].min()); kak_assert(buffer.is_valid(sel.anchor())); kak_assert(buffer.is_valid(sel.cursor())); kak_assert(not buffer.is_end(sel.anchor()));