diff --git a/src/buffer.cc b/src/buffer.cc index 5d3702eb7a..5599bdbdab 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -439,12 +439,12 @@ void Buffer::check_invariant() const #endif } -BufferCoord Buffer::do_insert(BufferCoord pos, StringView content) +BufferCoordPair Buffer::do_insert(BufferCoord pos, StringView content) { kak_assert(is_valid(pos)); if (content.empty()) - return pos; + return {pos, pos}; const bool at_end = is_end(pos); const bool append_lines = at_end and (m_lines.empty() or byte_at(back_coord()) == '\n'); @@ -480,11 +480,19 @@ BufferCoord Buffer::do_insert(BufferCoord pos, StringView content) std::make_move_iterator(new_lines.end())); const LineCount last_line = pos.line + new_lines.size() - 1; - const auto end = at_end ? line_count() - : BufferCoord{ last_line, m_lines[last_line].length() - suffix.length() }; + auto end = at_end ? line_count() + : BufferCoord{ last_line, m_lines[last_line].length() - suffix.length() }; m_changes.push_back({ Change::Insert, pos, end }); - return pos; + if (not end.column) + { + end.line--; + end.column = m_lines[end.line].length() - 1; + } + else + end.column--; + + return {pos, end}; } BufferCoord Buffer::do_erase(BufferCoord begin, BufferCoord end) @@ -538,13 +546,13 @@ void Buffer::apply_modification(const Modification& modification) } } -BufferCoord Buffer::insert(BufferCoord pos, StringView content) +BufferCoordPair Buffer::insert(BufferCoord pos, StringView content) { throw_if_read_only(); kak_assert(is_valid(pos)); if (content.empty()) - return pos; + return {pos, pos}; StringDataPtr real_content; if (is_end(pos) and content.back() != '\n') @@ -593,7 +601,7 @@ BufferCoord Buffer::replace(BufferCoord begin, BufferCoord end, StringView conte return begin; auto pos = erase(begin, end); - return insert(pos, content); + return insert(pos, content).first; } bool Buffer::is_modified() const @@ -811,7 +819,7 @@ UnitTest test_undo{[]() Buffer buffer("test", Buffer::Flags::None, "allo ?\nmais que fais la police\n hein ?\n youpi\n"); auto pos = buffer.insert(buffer.end_coord(), "kanaky\n"); // change 1 buffer.commit_undo_group(); - buffer.erase(pos, buffer.end_coord()); // change 2 + buffer.erase(pos.first, buffer.end_coord()); // change 2 buffer.commit_undo_group(); buffer.insert(2_line, "tchou\n"); // change 3 buffer.commit_undo_group(); diff --git a/src/buffer.hh b/src/buffer.hh index 4d48987f57..5d7bbf80b0 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -137,9 +137,9 @@ public: bool set_name(String name); void update_display_name(); - BufferCoord insert(BufferCoord pos, StringView content); - BufferCoord erase(BufferCoord begin, BufferCoord end); - BufferCoord replace(BufferCoord begin, BufferCoord end, StringView content); + BufferCoordPair insert(BufferCoord pos, StringView content); + BufferCoord erase(BufferCoord begin, BufferCoord end); + BufferCoord replace(BufferCoord begin, BufferCoord end, StringView content); size_t timestamp() const; timespec fs_timestamp() const; @@ -229,8 +229,8 @@ public: private: void on_option_changed(const Option& option) override; - BufferCoord do_insert(BufferCoord pos, StringView content); - BufferCoord do_erase(BufferCoord begin, BufferCoord end); + BufferCoordPair do_insert(BufferCoord pos, StringView content); + BufferCoord do_erase(BufferCoord begin, BufferCoord end); struct Modification; diff --git a/src/coord.hh b/src/coord.hh index 6109bf14c3..fe849e9592 100644 --- a/src/coord.hh +++ b/src/coord.hh @@ -94,6 +94,15 @@ struct BufferCoord : LineAndColumn : LineAndColumn{line, column} {} }; +struct BufferCoordPair +{ + BufferCoord first; + BufferCoord second; + + BufferCoordPair(BufferCoord first = {}, BufferCoord second = {}) + : first(first), second(second) {} +}; + struct DisplayCoord : LineAndColumn { [[gnu::always_inline]] diff --git a/src/normal.cc b/src/normal.cc index 9300bda59f..42092539f6 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -617,10 +617,23 @@ void insert_output(Context& context, NormalParams) if (cmdline.empty()) return; + auto& sels = context.selections(); auto str = ShellManager::instance().eval( cmdline, context, {}, ShellManager::Flags::WaitForStdout).first; ScopedEdition edition(context); - context.selections().insert(str, mode); + if (not str.empty()) + { + Vector out_insert_coords; + sels.insert(str, mode, &out_insert_coords); + + for (size_t i = 0; i < sels.size(); ++i) + { + auto& sel = sels[i]; + const auto& coords = out_insert_coords[i]; + + sel.set(coords); + } + } }); } @@ -700,7 +713,7 @@ void paste_all(Context& context, NormalParams params) offsets.push_back(all.length()); } - Vector insert_pos; + Vector insert_pos; auto& selections = context.selections(); { ScopedEdition edition(context); @@ -714,8 +727,8 @@ void paste_all(Context& context, NormalParams params) ByteCount pos = 0; for (auto offset : offsets) { - result.emplace_back(buffer.advance(ins_pos, pos), - buffer.advance(ins_pos, offset-1)); + result.emplace_back(buffer.advance(ins_pos.first, pos), + buffer.advance(ins_pos.first, offset-1)); pos = offset; } } diff --git a/src/selection.cc b/src/selection.cc index c245095d48..a9d4324078 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -382,7 +382,7 @@ static void fix_overflowing_selections(Vector& selections, } void SelectionList::insert(ConstArrayView strings, InsertMode mode, - Vector* out_insert_pos) + Vector* out_insert_coords) { if (strings.empty()) return; @@ -408,21 +408,26 @@ void SelectionList::insert(ConstArrayView strings, InsertMode mode, const String& str = strings[std::min(index, strings.size()-1)]; - const auto pos = (mode == InsertMode::Replace) ? - replace(*m_buffer, sel, str) - : m_buffer->insert(changes_tracker.get_new_coord(insert_pos[index]), str); + BufferCoordPair pos; + if (mode == InsertMode::Replace) + { + const BufferCoord first = replace(*m_buffer, sel, str); + pos = {first, first}; + } + else + pos = m_buffer->insert(changes_tracker.get_new_coord(insert_pos[index]), str); size_t old_timestamp = m_timestamp; changes_tracker.update(*m_buffer, m_timestamp); - if (out_insert_pos) - out_insert_pos->push_back(pos); + if (out_insert_coords) + out_insert_coords->push_back(pos); if (mode == InsertMode::Replace) { auto changes = m_buffer->changes_since(old_timestamp); if (changes.size() == 1) // Nothing got inserted, either str was empty, or just \n at end of buffer - sel.anchor() = sel.cursor() = m_buffer->clamp(pos); + sel.anchor() = sel.cursor() = m_buffer->clamp(pos.first); else if (changes.size() == 2) { // we want min and max from *before* we do any change diff --git a/src/selection.hh b/src/selection.hh index 510f999bca..379e5dc35a 100644 --- a/src/selection.hh +++ b/src/selection.hh @@ -33,6 +33,7 @@ struct Selection } void set(BufferCoord coord) { set(coord, coord); } + void set(BufferCoordPair coords) { set(coords.first, coords.second); } CaptureList& captures() { return m_captures; } const CaptureList& captures() const { return m_captures; } @@ -142,7 +143,7 @@ struct SelectionList size_t timestamp() const { return m_timestamp; } void insert(ConstArrayView strings, InsertMode mode, - Vector* out_insert_pos = nullptr); + Vector* out_insert_coords = nullptr); void erase(); private: