commands: refactor open_below to support count.

pull/8/head
Blaž Hrastnik 4 years ago
parent 6bd16a7320
commit 5fa1ba6b1c

@ -5,7 +5,7 @@ use helix_core::{
regex::{self, Regex}, regex::{self, Regex},
register, selection, register, selection,
state::{Direction, Granularity, State}, state::{Direction, Granularity, State},
ChangeSet, Range, Selection, Tendril, Transaction, Change, ChangeSet, Range, Selection, Tendril, Transaction,
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -588,47 +588,51 @@ pub fn append_to_line(cx: &mut Context) {
// 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(cx: &mut Context) { pub fn open_below(cx: &mut Context) {
let count = cx.count;
let doc = cx.doc(); let doc = cx.doc();
enter_insert_mode(doc); enter_insert_mode(doc);
let lines = selection_lines(&doc.state); let lines = selection_lines(&doc.state);
let positions = lines.into_iter().map(|index| { let positions = lines.into_iter().map(|index| {
// adjust all positions to the end of the line/start of the next one. // adjust all positions to the end of the line (next line minus one)
doc.text().line_to_char(index + 1) doc.text().line_to_char(index + 1).saturating_sub(1)
}); });
let changes = positions.map(|index| { let changes: Vec<Change> = positions
// TODO: share logic with insert_newline for indentation .map(|index| {
let indent_level = helix_core::indent::suggested_indent_for_pos( // TODO: share logic with insert_newline for indentation
doc.syntax.as_ref(), let indent_level = helix_core::indent::suggested_indent_for_pos(
&doc.state, doc.syntax.as_ref(),
index - 1, // need to match the indentation to the prev line &doc.state,
true, index,
); true,
let indent = " ".repeat(TAB_WIDTH).repeat(indent_level); );
let mut text = String::with_capacity(1 + indent.len()); let indent = " ".repeat(TAB_WIDTH).repeat(indent_level);
text.push_str(&indent); let mut text = String::with_capacity(1 + indent.len());
text.push('\n'); text.push('\n');
text.push_str(&indent);
// TODO: ideally we want to run a hook over the transactions to figure out and reindent all let text = text.repeat(count);
// \n's as a post-processing step?
// behaviors: // TODO: ideally we want to run a hook over the transactions to figure out and reindent all
// - on insert mode enter: we add newline + indent and position cursor at the end // \n's as a post-processing step?
// - on 3o/3O: we insert 3 newlines + indents each and position cursors at ends // behaviors:
// - on insert mode enter: we add newline + indent and position cursor at the end
// generate changes // - on 3o/3O: we insert 3 newlines + indents each and position cursors at ends
(index, index, Some(text.into()))
}); // generate changes
(index, index, Some(text.into()))
})
.collect();
// TODO: count actually inserts "n" new lines and starts editing on all of them. // TODO: count actually inserts "n" new lines and starts editing on all of them.
// TODO: append "count" newlines and modify cursors to those lines // TODO: append "count" newlines and modify cursors to those lines
let selection = Selection::new( let selection = Selection::new(
changes changes
.clone() .iter()
.map(|(start, end, text): (usize, usize, Option<Tendril>)| { .map(|(start, _end, text): &Change| {
let len = text.map(|text| text.len()).unwrap() - 1; // minus newline let len = text.as_ref().map(|text| text.len()).unwrap(); // minus newline
let pos = start + len; let pos = start + len;
Range::new(pos, pos) Range::new(pos, pos)
}) })
@ -636,7 +640,8 @@ pub fn open_below(cx: &mut Context) {
0, 0,
); );
let transaction = Transaction::change(&doc.state, changes).with_selection(selection); let transaction =
Transaction::change(&doc.state, changes.into_iter()).with_selection(selection);
doc.apply(&transaction); doc.apply(&transaction);
} }

Loading…
Cancel
Save