on master help sign in
Add 'o' command.
fb0f56bBlaž Hrastnik
helix-core/src/commands.rs+50−3
@@ -1,5 +1,5 @@
1use crate::graphemes;
1use crate::graphemes;
2−use crate::selection::Range;
2+use crate::selection::{Range, Selection};
3use crate::state::{Direction, Granularity, Mode, State};
3use crate::state::{Direction, Granularity, Mode, State};
4use crate::transaction::{ChangeSet, Transaction};
4use crate::transaction::{ChangeSet, Transaction};
5use crate::Tendril;
5use crate::Tendril;
@@ -62,8 +62,55 @@ pub fn append_mode(state: &mut State, _count: usize) {
62
62
63// I inserts at the start of each line with a selection
63// I inserts at the start of each line with a selection
64// A inserts at the end of each line with a selection
64// A inserts at the end of each line with a selection
65+
65−// o inserts a new line before each line with a selection
66+// o inserts a new line after each line with a selection
67+pub fn open_below(state: &mut State, _count: usize) {
68+ state.mode = Mode::Insert;
69+
70+ // calculate line numbers for each selection range
71+ let mut lines = state
72+ .selection
73+ .ranges()
74+ .iter()
75+ .map(|range| state.doc.char_to_line(range.head))
76+ .collect::<Vec<_>>();
77+
78+ lines.sort();
79+ lines.dedup();
80+
81+ let positions: Vec<_> = lines
82+ .into_iter()
83+ .map(|index| {
84+ // adjust all positions to the end of the line.
85+ let line = state.doc.line(index);
86+ let line_start = state.doc.line_to_char(index);
87+ line_start + line.len_chars()
88+ })
89+ .collect();
90+
91+ let changes = positions.iter().copied().map(|index|
92+ // generate changes
93+ (index, index, Some(Tendril::from_char('\n'))));
94+
95+ // TODO: count actually inserts "n" new lines and starts editing on all of them.
96+ // TODO: append "count" newlines and modify cursors to those lines
97+
98+ let selection = Selection::new(
99+ positions
100+ .iter()
101+ .copied()
102+ .map(|pos| Range::new(pos, pos))
103+ .collect(),
104+ 0,
105+ );
106+
107+ let transaction = Transaction::change(state, changes.collect()).with_selection(selection);
108+
109+ transaction.apply(state);
110+ // TODO: need to store into history if successful
111+}
112+
66−// O inserts a new line after each line with a selection
113+// O inserts a new line before each line with a selection
67
114
68pub fn normal_mode(state: &mut State, _count: usize) {
115pub fn normal_mode(state: &mut State, _count: usize) {
69 // TODO: if leaving append mode, move cursor back by 1
116 // TODO: if leaving append mode, move cursor back by 1
helix-core/src/transaction.rs+5
@@ -339,6 +339,11 @@ impl Transaction {
339 true
339 true
340 }
340 }
341
341
342+ pub fn with_selection(mut self, selection: Selection) -> Self {
343+ self.selection = Some(selection);
344+ self
345+ }
346+
342 /// Generate a transaction from a set of changes.
347 /// Generate a transaction from a set of changes.
343 // TODO: take an owned iter instead of Vec
348 // TODO: take an owned iter instead of Vec
344 pub fn change(state: &State, changes: Vec<Change>) -> Self {
349 pub fn change(state: &State, changes: Vec<Change>) -> Self {
helix-term/src/keymap.rs+4
@@ -107,6 +107,10 @@ pub fn default() -> Keymap {
107 code: KeyCode::Char('a'),
107 code: KeyCode::Char('a'),
108 modifiers: Modifiers::NONE
108 modifiers: Modifiers::NONE
109 } => commands::append_mode as Command,
109 } => commands::append_mode as Command,
110+ Key {
111+ code: KeyCode::Char('o'),
112+ modifiers: Modifiers::NONE
113+ } => commands::open_below as Command,
110 Key {
114 Key {
111 code: KeyCode::Esc,
115 code: KeyCode::Esc,
112 modifiers: Modifiers::NONE
116 modifiers: Modifiers::NONE