From 2fd42fe5fcd7af52ce2306ea78a416b4ed0d06ef Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sun, 4 Mar 2018 10:28:35 +1100 Subject: [PATCH] Insert: Do not move end of line on open line (o/O) Change the logic of open line commands so that if a selection lies on the end of line character of the line from which we open a new line, that selection does not move. If we have two clients, A and B, with B's cursor on the eol character of line L, and A hits `o` while on line L, B's cursor should stay on the same (logical) line. Previous behaviour would make B's cursor jump on the newly inserted line. --- src/input_handler.cc | 60 ++++++++++--------- test/normal/open-multiple-above/cmd | 1 + test/normal/open-multiple-above/in | 1 + test/normal/open-multiple-above/out | 4 ++ test/normal/open-multiple-below/cmd | 1 + test/normal/open-multiple-below/in | 1 + test/normal/open-multiple-below/out | 4 ++ .../cmd | 1 + .../in | 1 + .../out | 2 + .../state | 1 + 11 files changed, 50 insertions(+), 27 deletions(-) create mode 100644 test/normal/open-multiple-above/cmd create mode 100644 test/normal/open-multiple-above/in create mode 100644 test/normal/open-multiple-above/out create mode 100644 test/normal/open-multiple-below/cmd create mode 100644 test/normal/open-multiple-below/in create mode 100644 test/normal/open-multiple-below/out create mode 100644 test/regression/0-open-below-should-not-move-cursor-on-eol/cmd create mode 100644 test/regression/0-open-below-should-not-move-cursor-on-eol/in create mode 100644 test/regression/0-open-below-should-not-move-cursor-on-eol/out create mode 100644 test/regression/0-open-below-should-not-move-cursor-on-eol/state 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