diff options
author | Gokul Soumya | 2021-06-16 16:11:54 +0000 |
---|---|---|
committer | Blaž Hrastnik | 2021-06-17 09:54:07 +0000 |
commit | 20d6b202d5e31f6cd040e73924036f9600112dad (patch) | |
tree | 0fb84993ab3a1e5a6f2ab7974e8a5744b862c39c /helix-term/src | |
parent | a364d6c3837c36225dcd4ec9b15ef2c192feef0b (diff) |
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
Diffstat (limited to 'helix-term/src')
-rw-r--r-- | helix-term/src/commands.rs | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index c80716d4..59ae0e79 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1495,53 +1495,55 @@ fn open(cx: &mut Context, open: Open) { enter_insert_mode(doc); let text = doc.text().slice(..); + let contents = doc.text(); let selection = doc.selection(view.id); let mut ranges = SmallVec::with_capacity(selection.len()); + let mut offs = 0; - let changes: Vec<Change> = selection - .iter() - .map(|range| { - let line = text.char_to_line(range.head); - - let line = match open { - // adjust position to the end of the line (next line - 1) - Open::Below => line + 1, - // adjust position to the end of the previous line (current line - 1) - Open::Above => line, - }; + let mut transaction = Transaction::change_by_selection(contents, selection, |range| { + let line = text.char_to_line(range.head); - let index = doc.text().line_to_char(line).saturating_sub(1); + let line = match open { + // adjust position to the end of the line (next line - 1) + Open::Below => line + 1, + // adjust position to the end of the previous line (current line - 1) + Open::Above => line, + }; - // TODO: share logic with insert_newline for indentation - let indent_level = indent::suggested_indent_for_pos( - doc.language_config(), - doc.syntax(), - text, - index, - true, - ); - let indent = doc.indent_unit().repeat(indent_level); - let mut text = String::with_capacity(1 + indent.len()); - text.push('\n'); - text.push_str(&indent); - let text = text.repeat(count); + let index = doc.text().line_to_char(line).saturating_sub(1); - // calculate new selection range - let pos = index + text.chars().count(); - ranges.push(Range::new(pos, pos)); + // TODO: share logic with insert_newline for indentation + let indent_level = indent::suggested_indent_for_pos( + doc.language_config(), + doc.syntax(), + text, + index, + true, + ); + let indent = doc.indent_unit().repeat(indent_level); + let mut text = String::with_capacity(1 + indent.len()); + text.push('\n'); + text.push_str(&indent); + let text = text.repeat(count); + + // calculate new selection range + let pos = if line == 0 { + 0 // Required since text will have a min len of 1 (\n) + } else { + index + offs + text.chars().count() + }; + ranges.push(Range::new(pos, pos)); - (index, index, Some(text.into())) - }) - .collect(); + offs += text.chars().count(); + + (index, index, Some(text.into())) + }); // 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(ranges, 0); - - let transaction = - Transaction::change(doc.text(), changes.into_iter()).with_selection(selection); + transaction = transaction.with_selection(Selection::new(ranges, selection.primary_index())); doc.apply(&transaction, view.id); } |