@@ -138,19 +138,21 @@ impl SnippetEdit {
138
138
. into_iter ( )
139
139
. zip ( 1 ..)
140
140
. with_position ( )
141
- . map ( |pos| {
141
+ . flat_map ( |pos| {
142
142
let ( snippet, index) = match pos {
143
143
( itertools:: Position :: First , it) | ( itertools:: Position :: Middle , it) => it,
144
144
// last/only snippet gets index 0
145
145
( itertools:: Position :: Last , ( snippet, _) )
146
146
| ( itertools:: Position :: Only , ( snippet, _) ) => ( snippet, 0 ) ,
147
147
} ;
148
148
149
- let range = match snippet {
150
- Snippet :: Tabstop ( pos) => TextRange :: empty ( pos) ,
151
- Snippet :: Placeholder ( range) => range,
152
- } ;
153
- ( index, range)
149
+ match snippet {
150
+ Snippet :: Tabstop ( pos) => vec ! [ ( index, TextRange :: empty( pos) ) ] ,
151
+ Snippet :: Placeholder ( range) => vec ! [ ( index, range) ] ,
152
+ Snippet :: PlaceholderGroup ( ranges) => {
153
+ ranges. into_iter ( ) . map ( |range| ( index, range) ) . collect ( )
154
+ }
155
+ }
154
156
} )
155
157
. collect_vec ( ) ;
156
158
@@ -248,7 +250,7 @@ impl SourceChangeBuilder {
248
250
fn commit ( & mut self ) {
249
251
let snippet_edit = self . snippet_builder . take ( ) . map ( |builder| {
250
252
SnippetEdit :: new (
251
- builder. places . into_iter ( ) . map ( PlaceSnippet :: finalize_position) . collect_vec ( ) ,
253
+ builder. places . into_iter ( ) . flat_map ( PlaceSnippet :: finalize_position) . collect ( ) ,
252
254
)
253
255
} ) ;
254
256
@@ -356,6 +358,17 @@ impl SourceChangeBuilder {
356
358
self . add_snippet ( PlaceSnippet :: Over ( node. syntax ( ) . clone ( ) . into ( ) ) )
357
359
}
358
360
361
+ /// Adds a snippet to move the cursor selected over `nodes`
362
+ ///
363
+ /// This allows for renaming newly generated items without having to go
364
+ /// through a separate rename step.
365
+ pub fn add_placeholder_snippet_group ( & mut self , _cap : SnippetCap , nodes : Vec < SyntaxNode > ) {
366
+ assert ! ( nodes. iter( ) . all( |node| node. parent( ) . is_some( ) ) ) ;
367
+ self . add_snippet ( PlaceSnippet :: OverGroup (
368
+ nodes. into_iter ( ) . map ( |node| node. into ( ) ) . collect ( ) ,
369
+ ) )
370
+ }
371
+
359
372
fn add_snippet ( & mut self , snippet : PlaceSnippet ) {
360
373
let snippet_builder = self . snippet_builder . get_or_insert ( SnippetBuilder { places : vec ! [ ] } ) ;
361
374
snippet_builder. places . push ( snippet) ;
@@ -400,6 +413,13 @@ pub enum Snippet {
400
413
Tabstop ( TextSize ) ,
401
414
/// A placeholder snippet (e.g. `${0:placeholder}`).
402
415
Placeholder ( TextRange ) ,
416
+ /// A group of placeholder snippets, e.g.
417
+ ///
418
+ /// ```no_run
419
+ /// let ${0:new_var} = 4;
420
+ /// fun(1, 2, 3, ${0:new_var});
421
+ /// ```
422
+ PlaceholderGroup ( Vec < TextRange > ) ,
403
423
}
404
424
405
425
enum PlaceSnippet {
@@ -409,14 +429,20 @@ enum PlaceSnippet {
409
429
After ( SyntaxElement ) ,
410
430
/// Place a placeholder snippet in place of the element
411
431
Over ( SyntaxElement ) ,
432
+ /// Place a group of placeholder snippets which are linked together
433
+ /// in place of the elements
434
+ OverGroup ( Vec < SyntaxElement > ) ,
412
435
}
413
436
414
437
impl PlaceSnippet {
415
- fn finalize_position ( self ) -> Snippet {
438
+ fn finalize_position ( self ) -> Vec < Snippet > {
416
439
match self {
417
- PlaceSnippet :: Before ( it) => Snippet :: Tabstop ( it. text_range ( ) . start ( ) ) ,
418
- PlaceSnippet :: After ( it) => Snippet :: Tabstop ( it. text_range ( ) . end ( ) ) ,
419
- PlaceSnippet :: Over ( it) => Snippet :: Placeholder ( it. text_range ( ) ) ,
440
+ PlaceSnippet :: Before ( it) => vec ! [ Snippet :: Tabstop ( it. text_range( ) . start( ) ) ] ,
441
+ PlaceSnippet :: After ( it) => vec ! [ Snippet :: Tabstop ( it. text_range( ) . end( ) ) ] ,
442
+ PlaceSnippet :: Over ( it) => vec ! [ Snippet :: Placeholder ( it. text_range( ) ) ] ,
443
+ PlaceSnippet :: OverGroup ( it) => {
444
+ vec ! [ Snippet :: PlaceholderGroup ( it. into_iter( ) . map( |it| it. text_range( ) ) . collect( ) ) ]
445
+ }
420
446
}
421
447
}
422
448
}
0 commit comments