on master help sign in
Fix cursor position bugs related to o and O

- `O` at the beginning of file didn't move cursor - `o` and `O` messed up cursor position with multiple cursors Fixes #127

commit20d6b202d5e31f6cd040e73924036f9600112dad authorGokul Soumya <gokulps15@gmail.com> dateWed 16 Jun 2021, 21:41 (5 years ago) parenta364d6c
1 file changed+37−35
helix-term/src/commands.rs+37−35
helix-term/src/commands.rs+37−35
@@ -1495,53 +1495,55 @@ fn open(cx: &mut Context, open: Open) {
14951495 enter_insert_mode(doc);
14961496
14971497 let text = doc.text().slice(..);
1498+ let contents = doc.text();
14981499 let selection = doc.selection(view.id);
14991500
15001501 let mut ranges = SmallVec::with_capacity(selection.len());
1502+ let mut offs = 0;
15011503
1502− let changes: Vec<Change> = selection
1503− .iter()
1504− .map(|range| {
1505− let line = text.char_to_line(range.head);
1506−
1507− let line = match open {
1508− // adjust position to the end of the line (next line - 1)
1509− Open::Below => line + 1,
1510− // adjust position to the end of the previous line (current line - 1)
1511− Open::Above => line,
1512− };
1504+ let mut transaction = Transaction::change_by_selection(contents, selection, |range| {
1505+ let line = text.char_to_line(range.head);
15131506
1514− let index = doc.text().line_to_char(line).saturating_sub(1);
1507+ let line = match open {
1508+ // adjust position to the end of the line (next line - 1)
1509+ Open::Below => line + 1,
1510+ // adjust position to the end of the previous line (current line - 1)
1511+ Open::Above => line,
1512+ };
15151513
1516− // TODO: share logic with insert_newline for indentation
1517− let indent_level = indent::suggested_indent_for_pos(
1518− doc.language_config(),
1519− doc.syntax(),
1520− text,
1521− index,
1522− true,
1523− );
1524− let indent = doc.indent_unit().repeat(indent_level);
1525− let mut text = String::with_capacity(1 + indent.len());
1526− text.push('\n');
1527− text.push_str(&indent);
1528− let text = text.repeat(count);
1514+ let index = doc.text().line_to_char(line).saturating_sub(1);
15291515
1530− // calculate new selection range
1531− let pos = index + text.chars().count();
1532− ranges.push(Range::new(pos, pos));
1516+ // TODO: share logic with insert_newline for indentation
1517+ let indent_level = indent::suggested_indent_for_pos(
1518+ doc.language_config(),
1519+ doc.syntax(),
1520+ text,
1521+ index,
1522+ true,
1523+ );
1524+ let indent = doc.indent_unit().repeat(indent_level);
1525+ let mut text = String::with_capacity(1 + indent.len());
1526+ text.push('\n');
1527+ text.push_str(&indent);
1528+ let text = text.repeat(count);
1529+
1530+ // calculate new selection range
1531+ let pos = if line == 0 {
1532+ 0 // Required since text will have a min len of 1 (\n)
1533+ } else {
1534+ index + offs + text.chars().count()
1535+ };
1536+ ranges.push(Range::new(pos, pos));
15331537
1534− (index, index, Some(text.into()))
1535− })
1536− .collect();
1538+ offs += text.chars().count();
1539+
1540+ (index, index, Some(text.into()))
1541+ });
15371542
15381543 // TODO: count actually inserts "n" new lines and starts editing on all of them.
15391544 // TODO: append "count" newlines and modify cursors to those lines
15401545
1541− let selection = Selection::new(ranges, 0);
1542−
1543− let transaction =
1544− Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
1546+ transaction = transaction.with_selection(Selection::new(ranges, selection.primary_index()));
15451547
15461548 doc.apply(&transaction, view.id);
15471549}