aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlaž Hrastnik2020-09-13 10:51:42 +0000
committerBlaž Hrastnik2020-09-13 10:51:42 +0000
commitfb0f56b7472d221e57b2bec13c9c8668fe673e77 (patch)
treed294eaa9b633ecb6d2a37234007edbba4667d739
parenteb6b9a9ca958b0141a4cf6cc4dc59781e905fcc7 (diff)
Add 'o' command.
-rw-r--r--helix-core/src/commands.rs53
-rw-r--r--helix-core/src/transaction.rs5
-rw-r--r--helix-term/src/keymap.rs4
3 files changed, 59 insertions, 3 deletions
diff --git a/helix-core/src/commands.rs b/helix-core/src/commands.rs
index 860ec1cb..836667a1 100644
--- a/helix-core/src/commands.rs
+++ b/helix-core/src/commands.rs
@@ -1,5 +1,5 @@
use crate::graphemes;
-use crate::selection::Range;
+use crate::selection::{Range, Selection};
use crate::state::{Direction, Granularity, Mode, State};
use crate::transaction::{ChangeSet, Transaction};
use crate::Tendril;
@@ -62,8 +62,55 @@ pub fn append_mode(state: &mut State, _count: usize) {
// I inserts at the start of each line with a selection
// A inserts at the end of each line with a selection
-// o inserts a new line before each line with a selection
-// O inserts a new line after each line with a selection
+
+// o inserts a new line after each line with a selection
+pub fn open_below(state: &mut State, _count: usize) {
+ state.mode = Mode::Insert;
+
+ // calculate line numbers for each selection range
+ let mut lines = state
+ .selection
+ .ranges()
+ .iter()
+ .map(|range| state.doc.char_to_line(range.head))
+ .collect::<Vec<_>>();
+
+ lines.sort();
+ lines.dedup();
+
+ let positions: Vec<_> = lines
+ .into_iter()
+ .map(|index| {
+ // adjust all positions to the end of the line.
+ let line = state.doc.line(index);
+ let line_start = state.doc.line_to_char(index);
+ line_start + line.len_chars()
+ })
+ .collect();
+
+ let changes = positions.iter().copied().map(|index|
+ // generate changes
+ (index, index, Some(Tendril::from_char('\n'))));
+
+ // TODO: count actually inserts "n" new lines and starts editing on all of them.
+ // TODO: append "count" newlines and modify cursors to those lines
+
+ let selection = Selection::new(
+ positions
+ .iter()
+ .copied()
+ .map(|pos| Range::new(pos, pos))
+ .collect(),
+ 0,
+ );
+
+ let transaction = Transaction::change(state, changes.collect()).with_selection(selection);
+
+ transaction.apply(state);
+ // TODO: need to store into history if successful
+}
+
+// O inserts a new line before each line with a selection
pub fn normal_mode(state: &mut State, _count: usize) {
// TODO: if leaving append mode, move cursor back by 1
diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs
index 7fbcbf6c..3d03de19 100644
--- a/helix-core/src/transaction.rs
+++ b/helix-core/src/transaction.rs
@@ -339,6 +339,11 @@ impl Transaction {
true
}
+ pub fn with_selection(mut self, selection: Selection) -> Self {
+ self.selection = Some(selection);
+ self
+ }
+
/// Generate a transaction from a set of changes.
// TODO: take an owned iter instead of Vec
pub fn change(state: &State, changes: Vec<Change>) -> Self {
diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs
index 148611e3..32515761 100644
--- a/helix-term/src/keymap.rs
+++ b/helix-term/src/keymap.rs
@@ -108,6 +108,10 @@ pub fn default() -> Keymap {
modifiers: Modifiers::NONE
} => commands::append_mode as Command,
Key {
+ code: KeyCode::Char('o'),
+ modifiers: Modifiers::NONE
+ } => commands::open_below as Command,
+ Key {
code: KeyCode::Esc,
modifiers: Modifiers::NONE
} => commands::normal_mode as Command,