Fix assertion when replacing with empty strings

Replacing with empty strings is essentially a deletion, which means
it can end up push some selections out of the buffer (imagine 3 a
2 empty line buffer, and deleting the second one). We are fixing
the selections in SelectionList::erase, but we were not doing that
in SelectionList::insert.

Fixes #1504
This commit is contained in:
Maxime Coste 2017-07-14 13:05:52 +09:00
parent 53f5b3d709
commit 8650c99f13
4 changed files with 21 additions and 7 deletions

View File

@ -373,6 +373,17 @@ BufferCoord get_insert_pos(const Buffer& buffer, const Selection& sel,
}
}
static void fix_overflowing_selections(Vector<Selection>& selections,
const Buffer& buffer)
{
const BufferCoord back_coord = buffer.back_coord();
for (auto& sel : selections)
{
auto pos = buffer.clamp(sel.cursor());
sel.anchor() = sel.cursor() = std::min(pos, back_coord);
}
}
void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode,
Vector<BufferCoord>* out_insert_pos)
{
@ -431,6 +442,12 @@ void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode,
sel.cursor() = m_buffer->clamp(update_insert(sel.cursor(), change.begin, change.end));
}
}
// We might just have been deleting text if strings were empty,
// in which case we could have some selections pushed out of the buffer
if (mode == InsertMode::Replace)
fix_overflowing_selections(m_selections, *m_buffer);
check_invariant();
m_buffer->check_invariant();
}
@ -453,13 +470,7 @@ void SelectionList::erase()
changes_tracker.update(*m_buffer, m_timestamp);
}
BufferCoord back_coord = m_buffer->back_coord();
for (auto& sel : m_selections)
{
auto pos = m_buffer->clamp(sel.cursor());
sel.anchor() = sel.cursor() = std::min(pos, back_coord);
}
fix_overflowing_selections(m_selections, *m_buffer);
m_buffer->check_invariant();
}

View File

@ -0,0 +1 @@
2o<esc>|echo>&2<ret>

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@