When calculating a new selection, we need to take newly inserted text into account.

This commit is contained in:
Blaž Hrastnik 2021-05-15 10:26:41 +09:00
parent 4a9d1163e0
commit 0e5b421646
2 changed files with 33 additions and 10 deletions

View File

@ -65,14 +65,20 @@ fn handle_open(
) -> Transaction { ) -> Transaction {
let mut ranges = SmallVec::with_capacity(selection.len()); let mut ranges = SmallVec::with_capacity(selection.len());
let mut offs = 0;
let mut transaction = Transaction::change_by_selection(doc, selection, |range| { let mut transaction = Transaction::change_by_selection(doc, selection, |range| {
let pos = range.head; let pos = range.head;
let next = next_char(doc, pos); let next = next_char(doc, pos);
let head = pos + open.len_utf8(); let head = pos + offs + open.len_utf8();
// if selection, retain anchor, if cursor, move over // if selection, retain anchor, if cursor, move over
ranges.push(Range::new( ranges.push(Range::new(
if range.is_empty() { head } else { range.anchor }, if range.is_empty() {
head
} else {
range.anchor + offs
},
head, head,
)); ));
@ -88,6 +94,8 @@ fn handle_open(
pair.push_char(open); pair.push_char(open);
pair.push_char(close); pair.push_char(close);
offs += 2;
(pos, pos, Some(pair)) (pos, pos, Some(pair))
} }
} }
@ -99,14 +107,20 @@ fn handle_open(
fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) -> Transaction { fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) -> Transaction {
let mut ranges = SmallVec::with_capacity(selection.len()); let mut ranges = SmallVec::with_capacity(selection.len());
let mut offs = 0;
let mut transaction = Transaction::change_by_selection(doc, selection, |range| { let mut transaction = Transaction::change_by_selection(doc, selection, |range| {
let pos = range.head; let pos = range.head;
let next = next_char(doc, pos); let next = next_char(doc, pos);
let head = pos + close.len_utf8(); let head = pos + offs + close.len_utf8();
// if selection, retain anchor, if cursor, move over // if selection, retain anchor, if cursor, move over
ranges.push(Range::new( ranges.push(Range::new(
if range.is_empty() { head } else { range.anchor }, if range.is_empty() {
head
} else {
range.anchor + offs
},
head, head,
)); ));
@ -114,6 +128,8 @@ fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) ->
// return transaction that moves past close // return transaction that moves past close
(pos, pos, None) // no-op (pos, pos, None) // no-op
} else { } else {
offs += close.len_utf8();
// TODO: else return (use default handler that inserts close) // TODO: else return (use default handler that inserts close)
(pos, pos, Some(Tendril::from_char(close))) (pos, pos, Some(Tendril::from_char(close)))
} }

View File

@ -1644,6 +1644,9 @@ pub mod insert {
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());
// TODO: this is annoying, but we need to do it to properly calculate pos after edits
let mut offs = 0;
let mut transaction = Transaction::change_by_selection(contents, selection, |range| { let mut transaction = Transaction::change_by_selection(contents, selection, |range| {
let pos = range.head; let pos = range.head;
@ -1667,10 +1670,14 @@ pub mod insert {
text.push('\n'); text.push('\n');
text.push_str(&indent); text.push_str(&indent);
let head = pos + text.len(); let head = pos + offs + text.len();
ranges.push(Range::new( ranges.push(Range::new(
if range.is_empty() { head } else { range.anchor }, if range.is_empty() {
head
} else {
range.anchor + offs
},
head, head,
)); ));
@ -1680,11 +1687,11 @@ pub mod insert {
let indent = doc.indent_unit().repeat(indent_level.saturating_sub(1)); let indent = doc.indent_unit().repeat(indent_level.saturating_sub(1));
text.push('\n'); text.push('\n');
text.push_str(&indent); text.push_str(&indent);
(pos, pos, Some(text.into()))
} else {
(pos, pos, Some(text.into()))
} }
offs += text.len();
(pos, pos, Some(text.into()))
}); });
transaction = transaction.with_selection(Selection::new(ranges, selection.primary_index())); transaction = transaction.with_selection(Selection::new(ranges, selection.primary_index()));