1
1
use std:: iter;
2
2
3
+ use ropey:: RopeSlice ;
3
4
use tree_sitter:: Node ;
4
5
5
- use crate :: { Rope , Syntax } ;
6
+ use crate :: Syntax ;
6
7
7
8
const MAX_PLAINTEXT_SCAN : usize = 10000 ;
8
9
const MATCH_LIMIT : usize = 16 ;
@@ -27,7 +28,7 @@ const PAIRS: &[(char, char)] = &[
27
28
///
28
29
/// If no matching bracket is found, `None` is returned.
29
30
#[ must_use]
30
- pub fn find_matching_bracket ( syntax : & Syntax , doc : & Rope , pos : usize ) -> Option < usize > {
31
+ pub fn find_matching_bracket ( syntax : & Syntax , doc : RopeSlice , pos : usize ) -> Option < usize > {
31
32
if pos >= doc. len_chars ( ) || !is_valid_bracket ( doc. char ( pos) ) {
32
33
return None ;
33
34
}
@@ -45,13 +46,18 @@ pub fn find_matching_bracket(syntax: &Syntax, doc: &Rope, pos: usize) -> Option<
45
46
//
46
47
// If no surrounding scope is found, the function returns `None`.
47
48
#[ must_use]
48
- pub fn find_matching_bracket_fuzzy ( syntax : & Syntax , doc : & Rope , pos : usize ) -> Option < usize > {
49
+ pub fn find_matching_bracket_fuzzy ( syntax : & Syntax , doc : RopeSlice , pos : usize ) -> Option < usize > {
49
50
find_pair ( syntax, doc, pos, true )
50
51
}
51
52
52
- fn find_pair ( syntax : & Syntax , doc : & Rope , pos : usize , traverse_parents : bool ) -> Option < usize > {
53
+ fn find_pair (
54
+ syntax : & Syntax ,
55
+ doc : RopeSlice ,
56
+ pos_ : usize ,
57
+ traverse_parents : bool ,
58
+ ) -> Option < usize > {
53
59
let tree = syntax. tree ( ) ;
54
- let pos = doc. char_to_byte ( pos ) ;
60
+ let pos = doc. char_to_byte ( pos_ ) ;
55
61
56
62
let mut node = tree. root_node ( ) . descendant_for_byte_range ( pos, pos) ?;
57
63
@@ -92,7 +98,7 @@ fn find_pair(syntax: &Syntax, doc: &Rope, pos: usize, traverse_parents: bool) ->
92
98
}
93
99
}
94
100
if node. is_named ( ) {
95
- return None ;
101
+ break ;
96
102
}
97
103
}
98
104
@@ -104,8 +110,13 @@ fn find_pair(syntax: &Syntax, doc: &Rope, pos: usize, traverse_parents: bool) ->
104
110
return doc. try_byte_to_char ( close. start_byte ( ) ) . ok ( ) ;
105
111
}
106
112
}
107
- node = node. parent ( ) ?;
113
+ let Some ( parent) = node. parent ( ) else { break ; } ;
114
+ node = parent;
108
115
}
116
+ let node = tree. root_node ( ) . named_descendant_for_byte_range ( pos, pos) ?;
117
+ let node_start = doc. byte_to_char ( node. start_byte ( ) ) ;
118
+ find_matching_bracket_plaintext ( doc. byte_slice ( node. byte_range ( ) ) , pos_ - node_start)
119
+ . map ( |pos| pos + node_start)
109
120
}
110
121
111
122
/// Returns the position of the matching bracket under cursor.
@@ -120,10 +131,7 @@ fn find_pair(syntax: &Syntax, doc: &Rope, pos: usize, traverse_parents: bool) ->
120
131
///
121
132
/// If no matching bracket is found, `None` is returned.
122
133
#[ must_use]
123
- pub fn find_matching_bracket_current_line_plaintext (
124
- doc : & Rope ,
125
- cursor_pos : usize ,
126
- ) -> Option < usize > {
134
+ pub fn find_matching_bracket_plaintext ( doc : RopeSlice , cursor_pos : usize ) -> Option < usize > {
127
135
// Don't do anything when the cursor is not on top of a bracket.
128
136
let bracket = doc. char ( cursor_pos) ;
129
137
if !is_valid_bracket ( bracket) {
@@ -179,11 +187,11 @@ fn is_forward_bracket(c: char) -> bool {
179
187
PAIRS . iter ( ) . any ( |( l, _) | * l == c)
180
188
}
181
189
182
- fn is_valid_pair ( doc : & Rope , start_char : usize , end_char : usize ) -> bool {
190
+ fn is_valid_pair ( doc : RopeSlice , start_char : usize , end_char : usize ) -> bool {
183
191
PAIRS . contains ( & ( doc. char ( start_char) , doc. char ( end_char) ) )
184
192
}
185
193
186
- fn surrounding_bytes ( doc : & Rope , node : & Node ) -> Option < ( usize , usize ) > {
194
+ fn surrounding_bytes ( doc : RopeSlice , node : & Node ) -> Option < ( usize , usize ) > {
187
195
let len = doc. len_bytes ( ) ;
188
196
189
197
let start_byte = node. start_byte ( ) ;
@@ -201,7 +209,7 @@ fn surrounding_bytes(doc: &Rope, node: &Node) -> Option<(usize, usize)> {
201
209
/// # Returns
202
210
///
203
211
/// The position of the found node or `None` otherwise
204
- fn find_open_pair ( doc : & Rope , node : Option < Node > , open : char ) -> Option < usize > {
212
+ fn find_open_pair ( doc : RopeSlice , node : Option < Node > , open : char ) -> Option < usize > {
205
213
iter:: successors ( node, |node| node. prev_sibling ( ) )
206
214
. take ( MATCH_LIMIT )
207
215
. find_map ( |node| {
@@ -211,7 +219,7 @@ fn find_open_pair(doc: &Rope, node: Option<Node>, open: char) -> Option<usize> {
211
219
}
212
220
213
221
/// Tests if this node is a pair close char and returns the expected open char
214
- fn as_close_pair ( doc : & Rope , node : & Node ) -> Option < char > {
222
+ fn as_close_pair ( doc : RopeSlice , node : & Node ) -> Option < char > {
215
223
let close = as_char ( doc, node) ?. 1 ;
216
224
PAIRS
217
225
. iter ( )
@@ -223,7 +231,7 @@ fn as_close_pair(doc: &Rope, node: &Node) -> Option<char> {
223
231
/// # Returns
224
232
///
225
233
/// The position of the found node or `None` otherwise
226
- fn find_close_pair ( doc : & Rope , node : Option < Node > , close : char ) -> Option < usize > {
234
+ fn find_close_pair ( doc : RopeSlice , node : Option < Node > , close : char ) -> Option < usize > {
227
235
iter:: successors ( node, |node| node. next_sibling ( ) )
228
236
. take ( MATCH_LIMIT )
229
237
. find_map ( |node| {
@@ -233,15 +241,15 @@ fn find_close_pair(doc: &Rope, node: Option<Node>, close: char) -> Option<usize>
233
241
}
234
242
235
243
/// Tests if this node is a pair close char and returns the expected open char
236
- fn as_open_pair ( doc : & Rope , node : & Node ) -> Option < char > {
244
+ fn as_open_pair ( doc : RopeSlice , node : & Node ) -> Option < char > {
237
245
let close = as_char ( doc, node) ?. 1 ;
238
246
PAIRS
239
247
. iter ( )
240
248
. find_map ( |& ( open, close_) | ( close_ == close) . then_some ( open) )
241
249
}
242
250
243
251
/// Tests if this node is a pair opening and returns the expected close char
244
- fn as_char ( doc : & Rope , node : & Node ) -> Option < ( usize , char ) > {
252
+ fn as_char ( doc : RopeSlice , node : & Node ) -> Option < ( usize , char ) > {
245
253
// TODO: multi char/non ASCII pairs
246
254
if node. byte_range ( ) . len ( ) != 1 {
247
255
return None ;
@@ -257,11 +265,11 @@ mod tests {
257
265
#[ test]
258
266
fn test_find_matching_bracket_current_line_plaintext ( ) {
259
267
let assert = |input : & str , pos, expected| {
260
- let input = & Rope :: from ( input) ;
261
- let actual = find_matching_bracket_current_line_plaintext ( input, pos) ;
268
+ let input = RopeSlice :: from ( input) ;
269
+ let actual = find_matching_bracket_plaintext ( input, pos) ;
262
270
assert_eq ! ( expected, actual. unwrap( ) ) ;
263
271
264
- let actual = find_matching_bracket_current_line_plaintext ( input, expected) ;
272
+ let actual = find_matching_bracket_plaintext ( input, expected) ;
265
273
assert_eq ! ( pos, actual. unwrap( ) , "expected symmetrical behaviour" ) ;
266
274
} ;
267
275
0 commit comments