diff --git a/src/input_handler.cc b/src/input_handler.cc index 6fa41d6f..ffa923b1 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -1314,19 +1314,6 @@ private: SelectionList& selections = context().selections(); Buffer& buffer = context().buffer(); - auto duplicate_selections = [](SelectionList& sels, int count) { - count = count > 0 ? count : 1; - Vector new_sels; - new_sels.reserve(count * sels.size()); - for (auto& sel : sels) - for (int i = 0; i < count; ++i) - new_sels.push_back(sel); - - size_t new_main = sels.main_index() * count + count - 1; - sels = SelectionList{sels.buffer(), std::move(new_sels)}; - sels.set_main_index(new_main); - }; - switch (mode) { case InsertMode::Insert: @@ -1351,22 +1338,41 @@ private: sel.set({sel.max().line, buffer[sel.max().line].length() - 1}); break; case InsertMode::OpenLineBelow: - for (auto& sel : selections) - sel.set({sel.max().line, buffer[sel.max().line].length() - 1}); - duplicate_selections(selections, count); - insert('\n'); - break; - case InsertMode::OpenLineAbove: - for (auto& sel : selections) - sel.set({sel.min().line}); - duplicate_selections(selections, count); - // Do not use insert method here as we need to fixup selection - // before running the InsertChar hook. - selections.insert("\n"_str, InsertMode::InsertCursor); - for (auto& sel : selections) // fixup selection positions - sel.set({sel.cursor().line - 1}); + { + Vector new_sels; + count = count > 0 ? count : 1; + LineCount inserted_count = 0; + for (auto sel : selections) + { + buffer.insert(sel.max().line + inserted_count + 1, + String{'\n', CharCount{count}}); + for (int i = 0; i < count; ++i) + new_sels.push_back({sel.max().line + inserted_count + i + 1}); + inserted_count += count; + } + selections.set(std::move(new_sels), + selections.main_index() * count + count - 1); context().hooks().run_hook("InsertChar", "\n", context()); break; + } + case InsertMode::OpenLineAbove: + { + Vector new_sels; + count = count > 0 ? count : 1; + LineCount inserted_count = 0; + for (auto sel : selections) + { + buffer.insert(sel.min().line + inserted_count, + String{'\n', CharCount{count}}); + for (int i = 0; i < count; ++i) + new_sels.push_back({sel.max().line + inserted_count + i}); + inserted_count += count; + } + selections.set(std::move(new_sels), + selections.main_index() * count + count - 1); + context().hooks().run_hook("InsertChar", "\n", context()); + break; + } case InsertMode::InsertAtLineBegin: for (auto& sel : selections) { diff --git a/test/normal/open-multiple-above/cmd b/test/normal/open-multiple-above/cmd new file mode 100644 index 00000000..b07421f6 --- /dev/null +++ b/test/normal/open-multiple-above/cmd @@ -0,0 +1 @@ +3Obar diff --git a/test/normal/open-multiple-above/in b/test/normal/open-multiple-above/in new file mode 100644 index 00000000..257cc564 --- /dev/null +++ b/test/normal/open-multiple-above/in @@ -0,0 +1 @@ +foo diff --git a/test/normal/open-multiple-above/out b/test/normal/open-multiple-above/out new file mode 100644 index 00000000..de926059 --- /dev/null +++ b/test/normal/open-multiple-above/out @@ -0,0 +1,4 @@ +bar +bar +bar +foo diff --git a/test/normal/open-multiple-below/cmd b/test/normal/open-multiple-below/cmd new file mode 100644 index 00000000..e4be15d6 --- /dev/null +++ b/test/normal/open-multiple-below/cmd @@ -0,0 +1 @@ +3obar diff --git a/test/normal/open-multiple-below/in b/test/normal/open-multiple-below/in new file mode 100644 index 00000000..257cc564 --- /dev/null +++ b/test/normal/open-multiple-below/in @@ -0,0 +1 @@ +foo diff --git a/test/normal/open-multiple-below/out b/test/normal/open-multiple-below/out new file mode 100644 index 00000000..1458786c --- /dev/null +++ b/test/normal/open-multiple-below/out @@ -0,0 +1,4 @@ +foo +bar +bar +bar diff --git a/test/regression/0-open-below-should-not-move-cursor-on-eol/cmd b/test/regression/0-open-below-should-not-move-cursor-on-eol/cmd new file mode 100644 index 00000000..f180a6b2 --- /dev/null +++ b/test/regression/0-open-below-should-not-move-cursor-on-eol/cmd @@ -0,0 +1 @@ +x;:exec -draft o diff --git a/test/regression/0-open-below-should-not-move-cursor-on-eol/in b/test/regression/0-open-below-should-not-move-cursor-on-eol/in new file mode 100644 index 00000000..257cc564 --- /dev/null +++ b/test/regression/0-open-below-should-not-move-cursor-on-eol/in @@ -0,0 +1 @@ +foo diff --git a/test/regression/0-open-below-should-not-move-cursor-on-eol/out b/test/regression/0-open-below-should-not-move-cursor-on-eol/out new file mode 100644 index 00000000..75d7bfb8 --- /dev/null +++ b/test/regression/0-open-below-should-not-move-cursor-on-eol/out @@ -0,0 +1,2 @@ +foo + diff --git a/test/regression/0-open-below-should-not-move-cursor-on-eol/state b/test/regression/0-open-below-should-not-move-cursor-on-eol/state new file mode 100644 index 00000000..d022d3dd --- /dev/null +++ b/test/regression/0-open-below-should-not-move-cursor-on-eol/state @@ -0,0 +1 @@ +1.4,1.4