@@ -11,14 +11,28 @@ import {
11
11
CompletionParams ,
12
12
CompletionTriggerKind ,
13
13
InsertTextFormat ,
14
+ InsertReplaceEdit ,
14
15
LanguageClientConnection ,
16
+ Range ,
15
17
ServerCapabilities ,
16
18
TextEdit ,
17
19
} from "../languageclient"
18
20
import { Point , TextEditor } from "atom"
19
21
import * as ac from "atom/autocomplete-plus"
20
22
import { Suggestion , TextSuggestion , SnippetSuggestion } from "../types/autocomplete-extended"
21
23
24
+ /**
25
+ * Defines the behavior of suggestion acceptance.
26
+ * Assume you have "cons|ole" in the editor (`|` is the cursor position)
27
+ * and the autocomplete suggestion is `const`.
28
+ * - insert mode: const|ole
29
+ * - replace mode: const|
30
+ */
31
+ enum InsertMode {
32
+ insert = 'insert' ,
33
+ replace = 'replace' ,
34
+ }
35
+
22
36
/**
23
37
* Holds a list of suggestions generated from the CompletionItem[]
24
38
* list sent by the server, as well as metadata about the context
@@ -73,14 +87,16 @@ export default class AutocompleteAdapter {
73
87
* @param onDidConvertCompletionItem An optional function that takes a {CompletionItem},
74
88
* an {atom$AutocompleteSuggestion} and a {atom$AutocompleteRequest}
75
89
* allowing you to adjust converted items.
90
+ * @param insertMode The behavior of suggestion acceptance (see {InsertMode}).
76
91
* @returns A {Promise} of an {Array} of {atom$AutocompleteSuggestion}s containing the
77
92
* AutoComplete+ suggestions to display.
78
93
*/
79
94
public async getSuggestions (
80
95
server : ActiveServer ,
81
96
request : ac . SuggestionsRequestedEvent ,
82
97
onDidConvertCompletionItem ?: CompletionItemAdjuster ,
83
- minimumWordLength ?: number
98
+ minimumWordLength ?: number ,
99
+ insertMode : InsertMode = InsertMode . insert
84
100
) : Promise < ac . AnySuggestion [ ] > {
85
101
const triggerChars =
86
102
server . capabilities . completionProvider != null
@@ -101,6 +117,7 @@ export default class AutocompleteAdapter {
101
117
request ,
102
118
triggerChar ,
103
119
triggerOnly ,
120
+ insertMode ,
104
121
onDidConvertCompletionItem
105
122
)
106
123
@@ -140,6 +157,7 @@ export default class AutocompleteAdapter {
140
157
request : ac . SuggestionsRequestedEvent ,
141
158
triggerChar : string ,
142
159
triggerOnly : boolean ,
160
+ insertMode : InsertMode ,
143
161
onDidConvertCompletionItem ?: CompletionItemAdjuster
144
162
) : Promise < Suggestion [ ] > {
145
163
const cache = this . _suggestionCache . get ( server )
@@ -181,6 +199,7 @@ export default class AutocompleteAdapter {
181
199
completions ,
182
200
request ,
183
201
triggerColumns ,
202
+ insertMode ,
184
203
onDidConvertCompletionItem
185
204
)
186
205
this . _suggestionCache . set ( server , {
@@ -339,6 +358,7 @@ export default class AutocompleteAdapter {
339
358
* @param completionItems An {Array} of {CompletionItem} objects or a {CompletionList} containing completion
340
359
* items to be converted.
341
360
* @param request The {atom$AutocompleteRequest} to satisfy.
361
+ * @param insertMode The behavior of suggestion acceptance (see {InsertMode}).
342
362
* @param onDidConvertCompletionItem A function that takes a {CompletionItem}, an {atom$AutocompleteSuggestion}
343
363
* and a {atom$AutocompleteRequest} allowing you to adjust converted items.
344
364
* @returns A {Map} of AutoComplete+ suggestions ordered by the CompletionItems sortText.
@@ -347,6 +367,7 @@ export default class AutocompleteAdapter {
347
367
completionItems : CompletionItem [ ] | CompletionList | null ,
348
368
request : ac . SuggestionsRequestedEvent ,
349
369
triggerColumns : [ number , number ] ,
370
+ insertMode : InsertMode ,
350
371
onDidConvertCompletionItem ?: CompletionItemAdjuster
351
372
) : Map < Suggestion , PossiblyResolvedCompletionItem > {
352
373
const completionsArray = Array . isArray ( completionItems )
@@ -361,6 +382,7 @@ export default class AutocompleteAdapter {
361
382
{ } as Suggestion ,
362
383
request ,
363
384
triggerColumns ,
385
+ insertMode ,
364
386
onDidConvertCompletionItem
365
387
) ,
366
388
new PossiblyResolvedCompletionItem ( s , false ) ,
@@ -374,6 +396,7 @@ export default class AutocompleteAdapter {
374
396
* @param item An {CompletionItem} containing a completion item to be converted.
375
397
* @param suggestion A {atom$AutocompleteSuggestion} to have the conversion applied to.
376
398
* @param request The {atom$AutocompleteRequest} to satisfy.
399
+ * @param insertMode The behavior of suggestion acceptance (see {InsertMode}).
377
400
* @param onDidConvertCompletionItem A function that takes a {CompletionItem}, an {atom$AutocompleteSuggestion}
378
401
* and a {atom$AutocompleteRequest} allowing you to adjust converted items.
379
402
* @returns The {atom$AutocompleteSuggestion} passed in as suggestion with the conversion applied.
@@ -383,6 +406,7 @@ export default class AutocompleteAdapter {
383
406
suggestion : Suggestion ,
384
407
request : ac . SuggestionsRequestedEvent ,
385
408
triggerColumns : [ number , number ] ,
409
+ insertMode : InsertMode ,
386
410
onDidConvertCompletionItem ?: CompletionItemAdjuster
387
411
) : Suggestion {
388
412
AutocompleteAdapter . applyCompletionItemToSuggestion ( item , suggestion as TextSuggestion )
@@ -391,7 +415,8 @@ export default class AutocompleteAdapter {
391
415
request . editor ,
392
416
triggerColumns ,
393
417
request . bufferPosition ,
394
- suggestion as TextSuggestion
418
+ suggestion as TextSuggestion ,
419
+ insertMode
395
420
)
396
421
AutocompleteAdapter . applySnippetToSuggestion ( item , suggestion as SnippetSuggestion )
397
422
if ( onDidConvertCompletionItem != null ) {
@@ -442,20 +467,29 @@ export default class AutocompleteAdapter {
442
467
* @param textEdit A {TextEdit} from a CompletionItem to apply.
443
468
* @param editor An Atom {TextEditor} used to obtain the necessary text replacement.
444
469
* @param suggestion An {atom$AutocompleteSuggestion} to set the replacementPrefix and text properties of.
470
+ * @param insertMode The behavior of suggestion acceptance (see {InsertMode}).
445
471
*/
446
472
public static applyTextEditToSuggestion (
447
- textEdit : TextEdit | undefined ,
473
+ textEdit : TextEdit | InsertReplaceEdit | undefined ,
448
474
editor : TextEditor ,
449
475
triggerColumns : [ number , number ] ,
450
476
originalBufferPosition : Point ,
451
- suggestion : TextSuggestion
477
+ suggestion : TextSuggestion ,
478
+ insertMode : InsertMode ,
452
479
) : void {
453
- if ( ! textEdit ) {
454
- return
480
+ if ( ! textEdit ) { return ; }
481
+ let range : Range ;
482
+ if ( 'range' in textEdit ) {
483
+ range = textEdit . range ;
484
+ } else if ( insertMode === InsertMode . insert ) {
485
+ range = textEdit . insert ;
486
+ } else {
487
+ range = textEdit . replace ;
455
488
}
456
- if ( textEdit . range . start . character !== triggerColumns [ 0 ] ) {
457
- const range = Convert . lsRangeToAtomRange ( textEdit . range )
458
- suggestion . customReplacmentPrefix = editor . getTextInBufferRange ( [ range . start , originalBufferPosition ] )
489
+
490
+ if ( range . start . character !== triggerColumns [ 0 ] ) {
491
+ const atomRange = Convert . lsRangeToAtomRange ( range ) ;
492
+ suggestion . customReplacmentPrefix = editor . getTextInBufferRange ( [ atomRange . start , originalBufferPosition ] ) ;
459
493
}
460
494
suggestion . text = textEdit . newText
461
495
}
0 commit comments