Window: store a stack of selections

This commit is contained in:
Maxime Coste 2011-12-21 19:06:26 +00:00
parent c11b548662
commit f77fc3980b
2 changed files with 48 additions and 30 deletions

View File

@ -52,7 +52,8 @@ Window::Window(Buffer& buffer)
m_dimensions(0, 0), m_dimensions(0, 0),
m_current_inserter(nullptr) m_current_inserter(nullptr)
{ {
m_selections.push_back(Selection(buffer.begin(), buffer.begin())); m_selections.push_back(SelectionList());
selections().push_back(Selection(buffer.begin(), buffer.begin()));
HighlighterRegistry& registry = HighlighterRegistry::instance(); HighlighterRegistry& registry = HighlighterRegistry::instance();
@ -65,7 +66,7 @@ Window::Window(Buffer& buffer)
void Window::check_invariant() const void Window::check_invariant() const
{ {
assert(not m_selections.empty()); assert(not selections().empty());
} }
DisplayCoord Window::cursor_position() const DisplayCoord Window::cursor_position() const
@ -77,7 +78,7 @@ DisplayCoord Window::cursor_position() const
BufferIterator Window::cursor_iterator() const BufferIterator Window::cursor_iterator() const
{ {
check_invariant(); check_invariant();
return m_selections.back().last(); return selections().back().last();
} }
void Window::erase() void Window::erase()
@ -94,7 +95,7 @@ void Window::erase()
void Window::erase_noundo() void Window::erase_noundo()
{ {
check_invariant(); check_invariant();
for (auto& sel : m_selections) for (auto& sel : selections())
m_buffer.modify(Modification::make_erase(sel.begin(), sel.end())); m_buffer.modify(Modification::make_erase(sel.begin(), sel.end()));
scroll_to_keep_cursor_visible_ifn(); scroll_to_keep_cursor_visible_ifn();
} }
@ -135,7 +136,7 @@ void Window::insert(const String& string)
void Window::insert_noundo(const String& string) void Window::insert_noundo(const String& string)
{ {
for (auto& sel : m_selections) for (auto& sel : selections())
m_buffer.modify(Modification::make_insert(sel.begin(), string)); m_buffer.modify(Modification::make_insert(sel.begin(), string));
scroll_to_keep_cursor_visible_ifn(); scroll_to_keep_cursor_visible_ifn();
} }
@ -153,7 +154,7 @@ void Window::append(const String& string)
void Window::append_noundo(const String& string) void Window::append_noundo(const String& string)
{ {
for (auto& sel : m_selections) for (auto& sel : selections())
m_buffer.modify(Modification::make_insert(sel.end(), string)); m_buffer.modify(Modification::make_insert(sel.end(), string));
scroll_to_keep_cursor_visible_ifn(); scroll_to_keep_cursor_visible_ifn();
} }
@ -228,14 +229,14 @@ DisplayCoord Window::line_and_column_at(const BufferIterator& iterator) const
void Window::clear_selections() void Window::clear_selections()
{ {
check_invariant(); check_invariant();
BufferIterator pos = m_selections.back().last(); BufferIterator pos = selections().back().last();
if (*pos == '\n' and not pos.is_begin() and *(pos-1) != '\n') if (*pos == '\n' and not pos.is_begin() and *(pos-1) != '\n')
--pos; --pos;
Selection sel = Selection(pos, pos); Selection sel = Selection(pos, pos);
m_selections.clear(); selections().clear();
m_selections.push_back(std::move(sel)); selections().push_back(std::move(sel));
} }
void Window::select(const Selector& selector, bool append) void Window::select(const Selector& selector, bool append)
@ -244,13 +245,13 @@ void Window::select(const Selector& selector, bool append)
if (not append) if (not append)
{ {
Selection sel = selector(m_selections.back().last()); Selection sel = selector(selections().back().last());
m_selections.clear(); selections().clear();
m_selections.push_back(std::move(sel)); selections().push_back(std::move(sel));
} }
else else
{ {
for (auto& sel : m_selections) for (auto& sel : selections())
{ {
sel.merge_with(selector(sel.last())); sel.merge_with(selector(sel.last()));
} }
@ -268,7 +269,7 @@ void Window::multi_select(const MultiSelector& selector)
check_invariant(); check_invariant();
SelectionList new_selections; SelectionList new_selections;
for (auto& sel : m_selections) for (auto& sel : selections())
{ {
SelectionList selections = selector(sel); SelectionList selections = selector(sel);
std::copy(selections.begin(), selections.end(), std::copy(selections.begin(), selections.end(),
@ -277,7 +278,7 @@ void Window::multi_select(const MultiSelector& selector)
if (new_selections.empty()) if (new_selections.empty())
throw nothing_selected(); throw nothing_selected();
m_selections = std::move(new_selections); selections() = std::move(new_selections);
scroll_to_keep_cursor_visible_ifn(); scroll_to_keep_cursor_visible_ifn();
} }
@ -285,8 +286,8 @@ BufferString Window::selection_content() const
{ {
check_invariant(); check_invariant();
return m_buffer.string(m_selections.back().begin(), return m_buffer.string(selections().back().begin(),
m_selections.back().end()); selections().back().end());
} }
void Window::move_cursor(const DisplayCoord& offset, bool append) void Window::move_cursor(const DisplayCoord& offset, bool append)
@ -298,7 +299,7 @@ void Window::move_cursor(const DisplayCoord& offset, bool append)
} }
else else
{ {
for (auto& sel : m_selections) for (auto& sel : selections())
{ {
BufferCoord pos = m_buffer.line_and_column_at(sel.last()); BufferCoord pos = m_buffer.line_and_column_at(sel.last());
sel = Selection(sel.first(), m_buffer.iterator_at(pos + BufferCoord(offset))); sel = Selection(sel.first(), m_buffer.iterator_at(pos + BufferCoord(offset)));
@ -309,8 +310,8 @@ void Window::move_cursor(const DisplayCoord& offset, bool append)
void Window::move_cursor_to(const BufferIterator& iterator) void Window::move_cursor_to(const BufferIterator& iterator)
{ {
m_selections.clear(); selections().clear();
m_selections.push_back(Selection(iterator, iterator)); selections().push_back(Selection(iterator, iterator));
scroll_to_keep_cursor_visible_ifn(); scroll_to_keep_cursor_visible_ifn();
} }
@ -343,7 +344,7 @@ void Window::scroll_to_keep_cursor_visible_ifn()
{ {
check_invariant(); check_invariant();
DisplayCoord cursor = line_and_column_at(m_selections.back().last()); DisplayCoord cursor = line_and_column_at(selections().back().last());
if (cursor.line < 0) if (cursor.line < 0)
{ {
m_position.line = std::max(m_position.line + cursor.line, 0); m_position.line = std::max(m_position.line + cursor.line, 0);
@ -365,13 +366,13 @@ void Window::scroll_to_keep_cursor_visible_ifn()
std::string Window::status_line() const std::string Window::status_line() const
{ {
BufferCoord cursor = m_buffer.line_and_column_at(m_selections.back().last()); BufferCoord cursor = m_buffer.line_and_column_at(selections().back().last());
std::ostringstream oss; std::ostringstream oss;
oss << m_buffer.name(); oss << m_buffer.name();
if (m_buffer.is_modified()) if (m_buffer.is_modified())
oss << " [+]"; oss << " [+]";
oss << " -- " << cursor.line+1 << "," << cursor.column+1 oss << " -- " << cursor.line+1 << "," << cursor.column+1
<< " -- " << m_selections.size() << " sel -- "; << " -- " << selections().size() << " sel -- ";
if (m_current_inserter) if (m_current_inserter)
oss << "[Insert]"; oss << "[Insert]";
return oss.str(); return oss.str();
@ -413,6 +414,19 @@ CandidateList Window::complete_filterid(const std::string& prefix,
return m_filters.complete_id<str_to_str>(prefix, cursor_pos); return m_filters.complete_id<str_to_str>(prefix, cursor_pos);
} }
void Window::push_selections()
{
SelectionList current_selections = selections();
m_selections.push_back(std::move(current_selections));
}
void Window::pop_selections()
{
if (m_selections.size() > 1)
m_selections.pop_back();
else
throw runtime_error("no more selections on stack");
}
IncrementalInserter::IncrementalInserter(Window& window, Mode mode) IncrementalInserter::IncrementalInserter(Window& window, Mode mode)
: m_window(window) : m_window(window)
@ -426,7 +440,7 @@ IncrementalInserter::IncrementalInserter(Window& window, Mode mode)
if (mode == Mode::Change) if (mode == Mode::Change)
window.erase_noundo(); window.erase_noundo();
for (auto& sel : m_window.m_selections) for (auto& sel : m_window.selections())
{ {
DynamicBufferIterator pos; DynamicBufferIterator pos;
switch (mode) switch (mode)
@ -478,13 +492,13 @@ void IncrementalInserter::apply(Modification&& modification) const
void IncrementalInserter::insert(const Window::String& string) void IncrementalInserter::insert(const Window::String& string)
{ {
for (auto& sel : m_window.m_selections) for (auto& sel : m_window.selections())
apply(Modification::make_insert(sel.begin(), string)); apply(Modification::make_insert(sel.begin(), string));
} }
void IncrementalInserter::insert_capture(size_t index) void IncrementalInserter::insert_capture(size_t index)
{ {
for (auto& sel : m_window.m_selections) for (auto& sel : m_window.selections())
m_window.m_buffer.modify(Modification::make_insert(sel.begin(), m_window.m_buffer.modify(Modification::make_insert(sel.begin(),
sel.capture(index))); sel.capture(index)));
m_window.scroll_to_keep_cursor_visible_ifn(); m_window.scroll_to_keep_cursor_visible_ifn();
@ -492,7 +506,7 @@ void IncrementalInserter::insert_capture(size_t index)
void IncrementalInserter::erase() void IncrementalInserter::erase()
{ {
for (auto& sel : m_window.m_selections) for (auto& sel : m_window.selections())
{ {
sel = Selection(sel.first() - 1, sel.last() - 1); sel = Selection(sel.first() - 1, sel.last() - 1);
apply(Modification::make_erase(sel.begin(), sel.end())); apply(Modification::make_erase(sel.begin(), sel.end()));
@ -503,7 +517,7 @@ void IncrementalInserter::erase()
void IncrementalInserter::move_cursor(const DisplayCoord& offset) void IncrementalInserter::move_cursor(const DisplayCoord& offset)
{ {
for (auto& sel : m_window.m_selections) for (auto& sel : m_window.selections())
{ {
DisplayCoord pos = m_window.line_and_column_at(sel.last()); DisplayCoord pos = m_window.line_and_column_at(sel.last());
BufferIterator it = m_window.iterator_at(pos + offset); BufferIterator it = m_window.iterator_at(pos + offset);

View File

@ -76,7 +76,7 @@ public:
void select(const Selector& selector, bool append = false); void select(const Selector& selector, bool append = false);
void multi_select(const MultiSelector& selector); void multi_select(const MultiSelector& selector);
BufferString selection_content() const; BufferString selection_content() const;
const SelectionList selections() const { return m_selections; } const SelectionList& selections() const { return m_selections.back(); }
void set_dimensions(const DisplayCoord& dimensions); void set_dimensions(const DisplayCoord& dimensions);
@ -107,6 +107,8 @@ public:
CandidateList complete_filterid(const std::string& prefix, CandidateList complete_filterid(const std::string& prefix,
size_t cursor_pos = std::string::npos); size_t cursor_pos = std::string::npos);
void push_selections();
void pop_selections();
private: private:
friend class Buffer; friend class Buffer;
@ -121,13 +123,15 @@ private:
void insert_noundo(const String& string); void insert_noundo(const String& string);
void append_noundo(const String& string); void append_noundo(const String& string);
SelectionList& selections() { return m_selections.back(); }
friend class IncrementalInserter; friend class IncrementalInserter;
IncrementalInserter* m_current_inserter; IncrementalInserter* m_current_inserter;
Buffer& m_buffer; Buffer& m_buffer;
BufferCoord m_position; BufferCoord m_position;
DisplayCoord m_dimensions; DisplayCoord m_dimensions;
SelectionList m_selections; std::vector<SelectionList> m_selections;
DisplayBuffer m_display_buffer; DisplayBuffer m_display_buffer;
idvaluemap<std::string, HighlighterFunc> m_highlighters; idvaluemap<std::string, HighlighterFunc> m_highlighters;