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
pull/268/head^2
Gokul Soumya 2021-06-16 21:41:54 +05:30 committed by Blaž Hrastnik
parent a364d6c383
commit 20d6b202d5
1 changed files with 36 additions and 34 deletions

View File

@ -1495,53 +1495,55 @@ fn open(cx: &mut Context, open: Open) {
enter_insert_mode(doc); enter_insert_mode(doc);
let text = doc.text().slice(..); let text = doc.text().slice(..);
let contents = doc.text();
let selection = doc.selection(view.id); let selection = doc.selection(view.id);
let mut ranges = SmallVec::with_capacity(selection.len()); let mut ranges = SmallVec::with_capacity(selection.len());
let mut offs = 0;
let changes: Vec<Change> = selection let mut transaction = Transaction::change_by_selection(contents, selection, |range| {
.iter() let line = text.char_to_line(range.head);
.map(|range| {
let line = text.char_to_line(range.head);
let line = match open { let line = match open {
// adjust position to the end of the line (next line - 1) // adjust position to the end of the line (next line - 1)
Open::Below => line + 1, Open::Below => line + 1,
// adjust position to the end of the previous line (current line - 1) // adjust position to the end of the previous line (current line - 1)
Open::Above => line, Open::Above => line,
}; };
let index = doc.text().line_to_char(line).saturating_sub(1); let index = doc.text().line_to_char(line).saturating_sub(1);
// TODO: share logic with insert_newline for indentation // TODO: share logic with insert_newline for indentation
let indent_level = indent::suggested_indent_for_pos( let indent_level = indent::suggested_indent_for_pos(
doc.language_config(), doc.language_config(),
doc.syntax(), doc.syntax(),
text, text,
index, index,
true, true,
); );
let indent = doc.indent_unit().repeat(indent_level); let indent = doc.indent_unit().repeat(indent_level);
let mut text = String::with_capacity(1 + indent.len()); let mut text = String::with_capacity(1 + indent.len());
text.push('\n'); text.push('\n');
text.push_str(&indent); text.push_str(&indent);
let text = text.repeat(count); let text = text.repeat(count);
// calculate new selection range // calculate new selection range
let pos = index + text.chars().count(); let pos = if line == 0 {
ranges.push(Range::new(pos, pos)); 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())) offs += text.chars().count();
})
.collect(); (index, index, Some(text.into()))
});
// 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(ranges, 0); transaction = transaction.with_selection(Selection::new(ranges, selection.primary_index()));
let transaction =
Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
doc.apply(&transaction, view.id); doc.apply(&transaction, view.id);
} }