Better handling of linewise inserting when we have multiple selections per line

Fixes #1053
This commit is contained in:
Maxime Coste 2017-01-01 18:07:57 +00:00
parent cdb2c766a5
commit cd89531bd9
4 changed files with 24 additions and 15 deletions

View File

@ -481,7 +481,8 @@ void SelectionList::avoid_eol()
} }
} }
BufferCoord prepare_insert(Buffer& buffer, const Selection& sel, InsertMode mode) BufferCoord get_insert_pos(const Buffer& buffer, const Selection& sel,
InsertMode mode)
{ {
switch (mode) switch (mode)
{ {
@ -489,8 +490,6 @@ BufferCoord prepare_insert(Buffer& buffer, const Selection& sel, InsertMode mode
return sel.min(); return sel.min();
case InsertMode::InsertCursor: case InsertMode::InsertCursor:
return sel.cursor(); return sel.cursor();
case InsertMode::Replace:
return {}; // replace is handled specially, by calling Buffer::replace
case InsertMode::Append: case InsertMode::Append:
{ {
// special case for end of lines, append to current line instead // special case for end of lines, append to current line instead
@ -503,14 +502,11 @@ BufferCoord prepare_insert(Buffer& buffer, const Selection& sel, InsertMode mode
return {sel.max().line, buffer[sel.max().line].length() - 1}; return {sel.max().line, buffer[sel.max().line].length() - 1};
case InsertMode::InsertAtNextLineBegin: case InsertMode::InsertAtNextLineBegin:
return sel.max().line+1; return sel.max().line+1;
case InsertMode::OpenLineBelow: default:
return buffer.insert(sel.max().line + 1, "\n");
case InsertMode::OpenLineAbove:
return buffer.insert(sel.min().line, "\n");
}
kak_assert(false); kak_assert(false);
return {}; return {};
} }
}
void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode, void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode,
Vector<BufferCoord>* out_insert_pos) Vector<BufferCoord>* out_insert_pos)
@ -519,13 +515,21 @@ void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode,
return; return;
update(); update();
Vector<BufferCoord> insert_pos;
if (mode != InsertMode::Replace)
{
for (auto& sel : m_selections)
insert_pos.push_back(get_insert_pos(*m_buffer, sel, mode));
}
ForwardChangesTracker changes_tracker; ForwardChangesTracker changes_tracker;
for (size_t index = 0; index < m_selections.size(); ++index) for (size_t index = 0; index < m_selections.size(); ++index)
{ {
auto& sel = m_selections[index]; auto& sel = m_selections[index];
sel.anchor() = changes_tracker.get_new_coord(sel.anchor()); sel.anchor() = changes_tracker.get_new_coord_tolerant(sel.anchor());
sel.cursor() = changes_tracker.get_new_coord(sel.cursor()); sel.cursor() = changes_tracker.get_new_coord_tolerant(sel.cursor());
kak_assert(m_buffer->is_valid(sel.anchor()) and kak_assert(m_buffer->is_valid(sel.anchor()) and
m_buffer->is_valid(sel.cursor())); m_buffer->is_valid(sel.cursor()));
@ -533,14 +537,13 @@ void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode,
const auto pos = (mode == InsertMode::Replace) ? const auto pos = (mode == InsertMode::Replace) ?
replace(*m_buffer, sel, str) replace(*m_buffer, sel, str)
: m_buffer->insert(prepare_insert(*m_buffer, sel, mode), str); : m_buffer->insert(changes_tracker.get_new_coord(insert_pos[index]), str);
changes_tracker.update(*m_buffer, m_timestamp);
if (out_insert_pos) if (out_insert_pos)
out_insert_pos->push_back(pos); out_insert_pos->push_back(pos);
changes_tracker.update(*m_buffer, m_timestamp);
m_timestamp = m_buffer->timestamp();
if (mode == InsertMode::Replace) if (mode == InsertMode::Replace)
{ {
if (str.empty()) if (str.empty())

View File

@ -0,0 +1 @@
xSo<ret>dp

View File

@ -0,0 +1 @@
foobar

View File

@ -0,0 +1,4 @@
o
f
o
bar