diff --git a/helix-core/src/auto_pairs.rs b/helix-core/src/auto_pairs.rs index ffd16dafa..a04b0d3e9 100644 --- a/helix-core/src/auto_pairs.rs +++ b/helix-core/src/auto_pairs.rs @@ -65,14 +65,20 @@ fn handle_open( ) -> Transaction { let mut ranges = SmallVec::with_capacity(selection.len()); + let mut offs = 0; + let mut transaction = Transaction::change_by_selection(doc, selection, |range| { let pos = range.head; 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 ranges.push(Range::new( - if range.is_empty() { head } else { range.anchor }, + if range.is_empty() { + head + } else { + range.anchor + offs + }, head, )); @@ -88,6 +94,8 @@ fn handle_open( pair.push_char(open); pair.push_char(close); + offs += 2; + (pos, pos, Some(pair)) } } @@ -99,14 +107,20 @@ fn handle_open( fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) -> Transaction { let mut ranges = SmallVec::with_capacity(selection.len()); + let mut offs = 0; + let mut transaction = Transaction::change_by_selection(doc, selection, |range| { let pos = range.head; 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 ranges.push(Range::new( - if range.is_empty() { head } else { range.anchor }, + if range.is_empty() { + head + } else { + range.anchor + offs + }, head, )); @@ -114,6 +128,8 @@ fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) -> // return transaction that moves past close (pos, pos, None) // no-op } else { + offs += close.len_utf8(); + // TODO: else return (use default handler that inserts close) (pos, pos, Some(Tendril::from_char(close))) } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 104df72f9..5520c5afc 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1644,6 +1644,9 @@ pub mod insert { let selection = doc.selection(view.id); 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 pos = range.head; @@ -1667,10 +1670,14 @@ pub mod insert { text.push('\n'); text.push_str(&indent); - let head = pos + text.len(); + let head = pos + offs + text.len(); ranges.push(Range::new( - if range.is_empty() { head } else { range.anchor }, + if range.is_empty() { + head + } else { + range.anchor + offs + }, head, )); @@ -1680,11 +1687,11 @@ pub mod insert { let indent = doc.indent_unit().repeat(indent_level.saturating_sub(1)); text.push('\n'); 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()));