on master help sign in
When calculating a new selection, we need to take newly inserted text into account.
0e5b421Blaž Hrastnik
helix-core/src/auto_pairs.rs+20−4
@@ -65,14 +65,20 @@ fn handle_open(
65) -> Transaction {
65) -> Transaction {
66 let mut ranges = SmallVec::with_capacity(selection.len());
66 let mut ranges = SmallVec::with_capacity(selection.len());
67
67
68+ let mut offs = 0;
69+
68 let mut transaction = Transaction::change_by_selection(doc, selection, |range| {
70 let mut transaction = Transaction::change_by_selection(doc, selection, |range| {
69 let pos = range.head;
71 let pos = range.head;
70 let next = next_char(doc, pos);
72 let next = next_char(doc, pos);
71
73
72− let head = pos + open.len_utf8();
74+ let head = pos + offs + open.len_utf8();
73 // if selection, retain anchor, if cursor, move over
75 // if selection, retain anchor, if cursor, move over
74 ranges.push(Range::new(
76 ranges.push(Range::new(
75− if range.is_empty() { head } else { range.anchor },
77+ if range.is_empty() {
78+ head
79+ } else {
80+ range.anchor + offs
81+ },
76 head,
82 head,
77 ));
83 ));
78
84
@@ -88,6 +94,8 @@ fn handle_open(
88 pair.push_char(open);
94 pair.push_char(open);
89 pair.push_char(close);
95 pair.push_char(close);
90
96
97+ offs += 2;
98+
91 (pos, pos, Some(pair))
99 (pos, pos, Some(pair))
92 }
100 }
93 }
101 }
@@ -99,14 +107,20 @@ fn handle_open(
99fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) -> Transaction {
107fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) -> Transaction {
100 let mut ranges = SmallVec::with_capacity(selection.len());
108 let mut ranges = SmallVec::with_capacity(selection.len());
101
109
110+ let mut offs = 0;
111+
102 let mut transaction = Transaction::change_by_selection(doc, selection, |range| {
112 let mut transaction = Transaction::change_by_selection(doc, selection, |range| {
103 let pos = range.head;
113 let pos = range.head;
104 let next = next_char(doc, pos);
114 let next = next_char(doc, pos);
105
115
106− let head = pos + close.len_utf8();
116+ let head = pos + offs + close.len_utf8();
107 // if selection, retain anchor, if cursor, move over
117 // if selection, retain anchor, if cursor, move over
108 ranges.push(Range::new(
118 ranges.push(Range::new(
109− if range.is_empty() { head } else { range.anchor },
119+ if range.is_empty() {
120+ head
121+ } else {
122+ range.anchor + offs
123+ },
110 head,
124 head,
111 ));
125 ));
112
126
@@ -114,6 +128,8 @@ fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) ->
114 // return transaction that moves past close
128 // return transaction that moves past close
115 (pos, pos, None) // no-op
129 (pos, pos, None) // no-op
116 } else {
130 } else {
131+ offs += close.len_utf8();
132+
117 // TODO: else return (use default handler that inserts close)
133 // TODO: else return (use default handler that inserts close)
118 (pos, pos, Some(Tendril::from_char(close)))
134 (pos, pos, Some(Tendril::from_char(close)))
119 }
135 }
helix-term/src/commands.rs+13−6
@@ -1644,6 +1644,9 @@ pub mod insert {
1644 let selection = doc.selection(view.id);
1644 let selection = doc.selection(view.id);
1645 let mut ranges = SmallVec::with_capacity(selection.len());
1645 let mut ranges = SmallVec::with_capacity(selection.len());
1646
1646
1647+ // TODO: this is annoying, but we need to do it to properly calculate pos after edits
1648+ let mut offs = 0;
1649+
1647 let mut transaction = Transaction::change_by_selection(contents, selection, |range| {
1650 let mut transaction = Transaction::change_by_selection(contents, selection, |range| {
1648 let pos = range.head;
1651 let pos = range.head;
1649
1652
@@ -1667,10 +1670,14 @@ pub mod insert {
1667 text.push('\n');
1670 text.push('\n');
1668 text.push_str(&indent);
1671 text.push_str(&indent);
1669
1672
1670− let head = pos + text.len();
1673+ let head = pos + offs + text.len();
1671
1674
1672 ranges.push(Range::new(
1675 ranges.push(Range::new(
1673− if range.is_empty() { head } else { range.anchor },
1676+ if range.is_empty() {
1677+ head
1678+ } else {
1679+ range.anchor + offs
1680+ },
1674 head,
1681 head,
1675 ));
1682 ));
1676
1683
@@ -1680,11 +1687,11 @@ pub mod insert {
1680 let indent = doc.indent_unit().repeat(indent_level.saturating_sub(1));
1687 let indent = doc.indent_unit().repeat(indent_level.saturating_sub(1));
1681 text.push('\n');
1688 text.push('\n');
1682 text.push_str(&indent);
1689 text.push_str(&indent);
1683−
1684− (pos, pos, Some(text.into()))
1685− } else {
1686− (pos, pos, Some(text.into()))
1687 }
1690 }
1691+
1692+ offs += text.len();
1693+
1694+ (pos, pos, Some(text.into()))
1688 });
1695 });
1689
1696
1690 transaction = transaction.with_selection(Selection::new(ranges, selection.primary_index()));
1697 transaction = transaction.with_selection(Selection::new(ranges, selection.primary_index()));