@@ -1,10 +1,10 @@
11use helix_core::{
2− comment, coords_at_pos, graphemes, match_brackets,
2+ comment, coords_at_pos, graphemes, indent, match_brackets,
33 movement::{self, Direction},
44 object, pos_at_coords,
55 regex::{self, Regex},
66 register, search, selection, Change, ChangeSet, Position, Range, Rope, RopeSlice, Selection,
7− Tendril, Transaction,
7+ SmallVec, Tendril, Transaction,
88};
99
1010use once_cell::sync::Lazy;
@@ -951,26 +951,29 @@ pub fn open_below(cx: &mut Context) {
951951 let (view, doc) = cx.current();
952952 enter_insert_mode(doc);
953953
954+ let text = doc.text().slice(..);
954955 let lines = selection_lines(doc.text(), doc.selection(view.id));
955956
956− let positions = lines.into_iter().map(|index| {
957− // adjust all positions to the end of the line (next line minus one)
958− doc.text().line_to_char(index + 1).saturating_sub(1)
959− });
957+ let mut ranges = SmallVec::with_capacity(lines.len());
960958
961− let text = doc.text().slice(..);
959+ let changes: Vec<Change> = lines
960+ .into_iter()
961+ .map(|line| {
962+ // adjust all positions to the end of the line (next line minus one)
963+ let index = doc.text().line_to_char(line + 1).saturating_sub(1);
962964
963− let changes: Vec<Change> = positions
964− .map(|index| {
965965 // TODO: share logic with insert_newline for indentation
966− let indent_level =
967− helix_core::indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
966+ let indent_level = indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
968967 let indent = doc.indent_unit().repeat(indent_level);
969968 let mut text = String::with_capacity(1 + indent.len());
970969 text.push('\n');
971970 text.push_str(&indent);
972971 let text = text.repeat(count);
973972
973+ // calculate new selection range
974+ let pos = index + text.len();
975+ ranges.push(Range::new(pos, pos));
976+
974977 (index, index, Some(text.into()))
975978 })
976979 .collect();
@@ -978,17 +981,7 @@ pub fn open_below(cx: &mut Context) {
978981 // TODO: count actually inserts "n" new lines and starts editing on all of them.
979982 // TODO: append "count" newlines and modify cursors to those lines
980983
981− let selection = Selection::new(
982− changes
983− .iter()
984− .map(|(start, _end, text): &Change| {
985− let len = text.as_ref().map(|text| text.len()).unwrap(); // minus newline
986− let pos = start + len;
987− Range::new(pos, pos)
988− })
989− .collect(),
990− 0,
991− );
984+ let selection = Selection::new(ranges, 0);
992985
993986 let transaction =
994987 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
@@ -1002,26 +995,29 @@ pub fn open_above(cx: &mut Context) {
1002995 let (view, doc) = cx.current();
1003996 enter_insert_mode(doc);
1004997
998+ let text = doc.text().slice(..);
1005999 let lines = selection_lines(doc.text(), doc.selection(view.id));
10061000
1007− let positions = lines.into_iter().map(|index| {
1008− // adjust all positions to the end of the previous line
1009− doc.text().line_to_char(index).saturating_sub(1)
1010− });
1001+ let mut ranges = SmallVec::with_capacity(lines.len());
10111002
1012− let text = doc.text().slice(..);
1003+ let changes: Vec<Change> = lines
1004+ .into_iter()
1005+ .map(|line| {
1006+ // adjust all positions to the end of the previous line
1007+ let index = doc.text().line_to_char(line).saturating_sub(1);
10131008
1014− let changes: Vec<Change> = positions
1015− .map(|index| {
10161009 // TODO: share logic with insert_newline for indentation
1017− let indent_level =
1018− helix_core::indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
1010+ let indent_level = indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
10191011 let indent = doc.indent_unit().repeat(indent_level);
10201012 let mut text = String::with_capacity(1 + indent.len());
10211013 text.push('\n');
10221014 text.push_str(&indent);
10231015 let text = text.repeat(count);
10241016
1017+ // calculate new selection range
1018+ let pos = index + text.len();
1019+ ranges.push(Range::new(pos, pos));
1020+
10251021 // generate changes
10261022 (index, index, Some(text.into()))
10271023 })
@@ -1030,17 +1026,7 @@ pub fn open_above(cx: &mut Context) {
10301026 // TODO: count actually inserts "n" new lines and starts editing on all of them.
10311027 // TODO: append "count" newlines and modify cursors to those lines
10321028
1033− let selection = Selection::new(
1034− changes
1035− .iter()
1036− .map(|(start, _end, text): &Change| {
1037− let len = text.as_ref().map(|text| text.len()).unwrap(); // minus newline
1038− let pos = start + len;
1039− Range::new(pos, pos)
1040− })
1041− .collect(),
1042− 0,
1043− );
1029+ let selection = Selection::new(ranges, 0);
10441030
10451031 let transaction =
10461032 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
@@ -1359,12 +1345,8 @@ pub mod insert {
13591345 let transaction =
13601346 Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
13611347 // TODO: offset range.head by 1? when calculating?
1362− let indent_level = helix_core::indent::suggested_indent_for_pos(
1363− doc.syntax(),
1364− text,
1365− range.head,
1366− true,
1367− );
1348+ let indent_level =
1349+ indent::suggested_indent_for_pos(doc.syntax(), text, range.head, true);
13681350 let indent = doc.indent_unit().repeat(indent_level);
13691351 let mut text = String::with_capacity(1 + indent.len());
13701352 text.push('\n');