From f160008add247567f8e6704b54e9cd87fbe72983 Mon Sep 17 00:00:00 2001
From: Cor <prive@corpeters.nl>
Date: Sat, 17 Jul 2021 14:09:46 +0200
Subject: [PATCH] Vertical Selection

---
 helix-term/src/commands.rs | 30 ++++++++++++++++++++++++++++++
 helix-term/src/keymap.rs   |  4 ++++
 2 files changed, 34 insertions(+)

diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index ceb01ef3..d9c26c4a 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -172,6 +172,8 @@ impl Command {
         extend_char_right, "Extend right",
         extend_line_up, "Extend up",
         extend_line_down, "Extend down",
+        copy_selection_on_next_line, "Copy selection on next line",
+        copy_selection_on_prev_line, "Copy selection on previous line",
         move_next_word_start, "Move to beginning of next word",
         move_prev_word_start, "Move to beginning of previous word",
         move_next_word_end, "Move to end of next word",
@@ -958,6 +960,34 @@ fn extend_char_right(cx: &mut Context) {
     doc.set_selection(view.id, selection);
 }
 
+fn copy_selection_on_prev_line(cx: &mut Context) {
+    let count = cx.count();
+    let (view, doc) = current!(cx.editor);
+    let text = doc.text().slice(..);
+    let old_selection = doc.selection(view.id).clone();
+    let mut ranges: SmallVec<_> = old_selection.ranges().into();
+    for r in old_selection.iter() {
+        ranges.push(Range::point(
+            movement::move_vertically(text, *r, Direction::Backward, count, Movement::Extend).head,
+        ));
+    }
+    doc.set_selection(view.id, Selection::new(ranges, old_selection.cursor()));
+}
+
+fn copy_selection_on_next_line(cx: &mut Context) {
+    let count = cx.count();
+    let (view, doc) = current!(cx.editor);
+    let text = doc.text().slice(..);
+    let old_selection = doc.selection(view.id).clone();
+    let mut ranges: SmallVec<_> = old_selection.ranges().into();
+    for r in old_selection.iter() {
+        ranges.push(Range::point(
+            movement::move_vertically(text, *r, Direction::Forward, count, Movement::Extend).head,
+        ));
+    }
+    doc.set_selection(view.id, Selection::new(ranges, old_selection.cursor()));
+}
+
 fn extend_line_up(cx: &mut Context) {
     let count = cx.count();
     let (view, doc) = current!(cx.editor);
diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs
index cba3b3d0..77a3b8bc 100644
--- a/helix-term/src/keymap.rs
+++ b/helix-term/src/keymap.rs
@@ -387,6 +387,10 @@ impl Default for Keymaps {
             "c" => change_selection,
             // TODO: also change delete without yanking
 
+            "C" => copy_selection_on_next_line,
+            "alt-C" => copy_selection_on_prev_line,
+
+
             "s" => select_regex,
             "A-s" => split_selection_on_newline,
             "S" => split_selection,