diff --git a/src/buffer.cc b/src/buffer.cc index afc78976..608161d3 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -137,6 +137,24 @@ BufferCoord Buffer::clamp(BufferCoord coord) const return coord; } +BufferCoord Buffer::offset_coord(BufferCoord coord, CharCount offset) +{ + auto& line = m_lines[coord.line].content; + auto character = std::max(0_char, std::min(line.char_count_to(coord.column) + offset, + line.char_length() - 1)); + return {coord.line, line.byte_count_to(character)}; +} + +BufferCoord Buffer::offset_coord(BufferCoord coord, LineCount offset) +{ + auto character = m_lines[coord.line].content.char_count_to(coord.column); + auto line = Kakoune::clamp(coord.line + offset, 0_line, line_count()-1); + auto& content = m_lines[line].content; + + character = std::max(0_char, std::min(character, content.char_length() - 2)); + return {line, content.byte_count_to(character)}; +} + BufferIterator Buffer::begin() const { return BufferIterator(*this, { 0_line, 0 }); diff --git a/src/buffer.hh b/src/buffer.hh index 7f8ef25e..81b1bab4 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -147,6 +147,9 @@ public: // returns nearest valid coordinates from given ones BufferCoord clamp(BufferCoord coord) const; + BufferCoord offset_coord(BufferCoord coord, CharCount offset); + BufferCoord offset_coord(BufferCoord coord, LineCount offset); + const String& name() const { return m_name; } String display_name() const; diff --git a/src/editor.cc b/src/editor.cc index 0863e94c..d7bf52e0 100644 --- a/src/editor.cc +++ b/src/editor.cc @@ -107,50 +107,6 @@ std::vector Editor::selections_content() const return contents; } -BufferCoord Editor::offset_coord(BufferCoord coord, CharCount offset) -{ - auto& line = buffer()[coord.line]; - auto character = std::max(0_char, std::min(line.char_count_to(coord.column) + offset, - line.char_length() - 2)); - return {coord.line, line.byte_count_to(character)}; -} - -void Editor::move_selections(CharCount offset, SelectMode mode) -{ - kak_assert(mode == SelectMode::Replace or mode == SelectMode::Extend); - for (auto& sel : m_selections) - { - auto last = offset_coord(sel.last(), offset); - sel.first() = mode == SelectMode::Extend ? sel.first() : last; - sel.last() = last; - avoid_eol(*m_buffer, sel); - } - m_selections.sort_and_merge_overlapping(); -} - -BufferCoord Editor::offset_coord(BufferCoord coord, LineCount offset) -{ - auto character = (*m_buffer)[coord.line].char_count_to(coord.column); - auto line = clamp(coord.line + offset, 0_line, m_buffer->line_count()-1); - auto& content = (*m_buffer)[line]; - - character = std::max(0_char, std::min(character, content.char_length() - 2)); - return {line, content.byte_count_to(character)}; -} - -void Editor::move_selections(LineCount offset, SelectMode mode) -{ - kak_assert(mode == SelectMode::Replace or mode == SelectMode::Extend); - for (auto& sel : m_selections) - { - auto pos = offset_coord(sel.last(), offset); - sel.first() = mode == SelectMode::Extend ? sel.first() : pos; - sel.last() = pos; - avoid_eol(*m_buffer, sel); - } - m_selections.sort_and_merge_overlapping(); -} - class ModifiedRangesListener : public BufferChangeListener_AutoRegister { public: diff --git a/src/editor.hh b/src/editor.hh index 3af52494..b26a8fee 100644 --- a/src/editor.hh +++ b/src/editor.hh @@ -53,11 +53,6 @@ public: void insert(memoryview strings, InsertMode mode = InsertMode::Insert); - void move_selections(LineCount move, - SelectMode mode = SelectMode::Replace); - void move_selections(CharCount move, - SelectMode mode = SelectMode::Replace); - const SelectionList& selections() const { return m_selections; } SelectionList& selections() { return m_selections; } std::vector selections_content() const; @@ -72,9 +67,6 @@ private: void begin_edition(); void end_edition(); - virtual BufferCoord offset_coord(BufferCoord coord, LineCount move); - virtual BufferCoord offset_coord(BufferCoord coord, CharCount move); - int m_edition_level; void check_invariant() const; diff --git a/src/input_handler.cc b/src/input_handler.cc index 79501e59..c7f809b2 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -923,22 +923,22 @@ public: erase(); else if (key == Key::Left) { - m_edition.editor().move_selections(-1_char, SelectMode::Replace); + move(-1_char); moved = true; } else if (key == Key::Right) { - m_edition.editor().move_selections(1_char, SelectMode::Replace); + move(1_char); moved = true; } else if (key == Key::Up) { - m_edition.editor().move_selections(-1_line, SelectMode::Replace); + move(-1_line); moved = true; } else if (key == Key::Down) { - m_edition.editor().move_selections(1_line, SelectMode::Replace); + move(1_line); moved = true; } else if (key.modifiers == Key::Modifiers::None) @@ -992,6 +992,19 @@ private: } } + template + void move(Type offset) + { + auto& selections = context().editor().selections(); + for (auto& sel : selections) + { + auto last = context().has_window() ? context().window().offset_coord(sel.last(), offset) + : context().buffer().offset_coord(sel.last(), offset); + sel.first() = sel.last() = last; + } + selections.sort_and_merge_overlapping(); + } + void insert(memoryview strings) { auto& buffer = m_edition.editor().buffer(); diff --git a/src/normal.cc b/src/normal.cc index fad234af..f5625cd8 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -1007,8 +1007,21 @@ constexpr Repeated repeated(T func) { return Repeated(func); } template void move(Context& context, int count) { + kak_assert(mode == SelectMode::Replace or mode == SelectMode::Extend); Type offset(std::max(count,1)); - context.editor().move_selections(direction == Backward ? -offset : offset, mode); + if (direction == Backward) + offset = -offset; + auto& selections = context.editor().selections(); + for (auto& sel : selections) + { + auto last = context.has_window() ? context.window().offset_coord(sel.last(), offset) + : context.buffer().offset_coord(sel.last(), offset); + + sel.first() = mode == SelectMode::Extend ? sel.first() : last; + sel.last() = last; + avoid_eol(context.buffer(), sel); + } + selections.sort_and_merge_overlapping(); } KeyMap keymap = diff --git a/src/window.cc b/src/window.cc index fc053bde..bd47aea6 100644 --- a/src/window.cc +++ b/src/window.cc @@ -233,6 +233,11 @@ DisplayCoord Window::display_position(BufferCoord coord) return { 0, 0 }; } +BufferCoord Window::offset_coord(BufferCoord coord, CharCount offset) +{ + return buffer().offset_coord(coord, offset); +} + BufferCoord Window::offset_coord(BufferCoord coord, LineCount offset) { auto line = clamp(coord.line + offset, 0_line, buffer().line_count()-1); diff --git a/src/window.hh b/src/window.hh index 49bbe39e..533f9b98 100644 --- a/src/window.hh +++ b/src/window.hh @@ -53,6 +53,8 @@ public: size_t timestamp() const { return m_timestamp; } void forget_timestamp() { m_timestamp = -1; } + BufferCoord offset_coord(BufferCoord coord, CharCount offset); + BufferCoord offset_coord(BufferCoord coord, LineCount offset); private: Window(const Window&) = delete; @@ -60,8 +62,6 @@ private: void scroll_to_keep_cursor_visible_ifn(); - BufferCoord offset_coord(BufferCoord coord, LineCount move) override; - DisplayCoord m_position; DisplayCoord m_dimensions; DisplayBuffer m_display_buffer;