@@ -59,50 +59,6 @@ export class GenericCompleterModel<
59
59
return item as T ;
60
60
}
61
61
62
- setCompletionItems ( newValue : T [ ] ) {
63
- super . setCompletionItems ( newValue ) ;
64
-
65
- if ( this . current && this . cursor ) {
66
- // set initial query to pre-filter items; in future we should use:
67
- // https://github.com/jupyterlab/jupyterlab/issues/9763#issuecomment-1001603348
68
-
69
- // note: start/end from cursor are not ideal because these get populated from fetch
70
- // reply which will vary depending on what providers decide to return; we want the
71
- // actual position in token, the same as passed in request to fetch. We can get it
72
- // by searching for longest common prefix as seen below (or by counting characters).
73
- // Maybe upstream should expose it directly?
74
- const { start, end } = this . cursor ;
75
- const { text, line, column } = this . original ! ;
76
-
77
- const queryRange = text . substring ( start , end ) . trim ( ) ;
78
- const linePrefix = text . split ( '\n' ) [ line ] . substring ( 0 , column ) . trim ( ) ;
79
- let query = '' ;
80
- for ( let i = queryRange . length ; i > 0 ; i -- ) {
81
- if ( queryRange . slice ( 0 , i ) == linePrefix . slice ( - i ) ) {
82
- query = linePrefix . slice ( - i ) ;
83
- break ;
84
- }
85
- }
86
- if ( ! query ) {
87
- return ;
88
- }
89
-
90
- let trimmedQuotes = false ;
91
- // special case for "Completes Paths In Strings" test case
92
- if ( query . startsWith ( '"' ) || query . startsWith ( "'" ) ) {
93
- query = query . substring ( 1 ) ;
94
- trimmedQuotes = true ;
95
- }
96
- if ( query . endsWith ( '"' ) || query . endsWith ( "'" ) ) {
97
- query = query . substring ( 0 , - 1 ) ;
98
- trimmedQuotes = true ;
99
- }
100
- if ( this . settings . preFilterMatches || trimmedQuotes ) {
101
- this . query = query ;
102
- }
103
- }
104
- }
105
-
106
62
private _markFragment ( value : string ) : string {
107
63
return `<mark>${ value } </mark>` ;
108
64
}
@@ -138,7 +94,11 @@ export class GenericCompleterModel<
138
94
return super . createPatch ( patch ) ;
139
95
}
140
96
141
- private _sortAndFilter ( query : string , items : T [ ] ) : T [ ] {
97
+ protected resolveQuery ( userQuery : string , _item : T ) {
98
+ return userQuery ;
99
+ }
100
+
101
+ private _sortAndFilter ( userQuery : string , items : T [ ] ) : T [ ] {
142
102
let results : ICompletionMatch < T > [ ] = [ ] ;
143
103
144
104
for ( let item of items ) {
@@ -149,6 +109,8 @@ export class GenericCompleterModel<
149
109
let filterText : string | null = null ;
150
110
let filterMatch : StringExt . IMatchResult | null = null ;
151
111
112
+ const query = this . resolveQuery ( userQuery , item ) ;
113
+
152
114
let lowerCaseQuery = query . toLowerCase ( ) ;
153
115
154
116
if ( query ) {
@@ -246,10 +208,6 @@ export namespace GenericCompleterModel {
246
208
* Whether perfect matches should be included (default = true)
247
209
*/
248
210
includePerfectMatches ?: boolean ;
249
- /**
250
- * Whether matches should be pre-filtered (default = true)
251
- */
252
- preFilterMatches ?: boolean ;
253
211
/**
254
212
* Whether kernel completions should be shown first.
255
213
*/
@@ -258,7 +216,6 @@ export namespace GenericCompleterModel {
258
216
export const defaultOptions : IOptions = {
259
217
caseSensitive : true ,
260
218
includePerfectMatches : true ,
261
- preFilterMatches : true ,
262
219
kernelCompletionsFirst : false
263
220
} ;
264
221
}
@@ -267,13 +224,73 @@ type MaybeCompletionItem = Partial<CompletionItem> &
267
224
CompletionHandler . ICompletionItem ;
268
225
269
226
export class LSPCompleterModel extends GenericCompleterModel < MaybeCompletionItem > {
227
+ public settings : LSPCompleterModel . IOptions ;
228
+
229
+ constructor ( settings : LSPCompleterModel . IOptions = { } ) {
230
+ super ( ) ;
231
+ this . settings = { ...LSPCompleterModel . defaultOptions , ...settings } ;
232
+ }
233
+
270
234
protected getFilterText ( item : MaybeCompletionItem ) : string {
271
235
if ( item . filterText ) {
272
236
return item . filterText ;
273
237
}
274
238
return super . getFilterText ( item ) ;
275
239
}
276
240
241
+ setCompletionItems ( newValue : MaybeCompletionItem [ ] ) {
242
+ super . setCompletionItems ( newValue ) ;
243
+ this . _preFilterQuery = '' ;
244
+
245
+ if ( this . current && this . cursor ) {
246
+ // set initial query to pre-filter items; in future we should use:
247
+ // https://github.com/jupyterlab/jupyterlab/issues/9763#issuecomment-1001603348
248
+
249
+ // note: start/end from cursor are not ideal because these get populated from fetch
250
+ // reply which will vary depending on what providers decide to return; we want the
251
+ // actual position in token, the same as passed in request to fetch. We can get it
252
+ // by searching for longest common prefix as seen below (or by counting characters).
253
+ // Maybe upstream should expose it directly?
254
+ const { start, end } = this . cursor ;
255
+ const { text, line, column } = this . original ! ;
256
+
257
+ const queryRange = text . substring ( start , end ) . trim ( ) ;
258
+ const linePrefix = text . split ( '\n' ) [ line ] . substring ( 0 , column ) . trim ( ) ;
259
+ let query = '' ;
260
+ for ( let i = queryRange . length ; i > 0 ; i -- ) {
261
+ if ( queryRange . slice ( 0 , i ) == linePrefix . slice ( - i ) ) {
262
+ query = linePrefix . slice ( - i ) ;
263
+ break ;
264
+ }
265
+ }
266
+ if ( ! query ) {
267
+ return ;
268
+ }
269
+
270
+ let trimmedQuotes = false ;
271
+ // special case for "Completes Paths In Strings" test case
272
+ if ( query . startsWith ( '"' ) || query . startsWith ( "'" ) ) {
273
+ query = query . substring ( 1 ) ;
274
+ trimmedQuotes = true ;
275
+ }
276
+ if ( query . endsWith ( '"' ) || query . endsWith ( "'" ) ) {
277
+ query = query . substring ( 0 , - 1 ) ;
278
+ trimmedQuotes = true ;
279
+ }
280
+ if ( this . settings . preFilterMatches || trimmedQuotes ) {
281
+ this . _preFilterQuery = query ;
282
+ }
283
+ }
284
+ }
285
+
286
+ protected resolveQuery ( userQuery : string , item : MaybeCompletionItem ) {
287
+ return userQuery
288
+ ? userQuery
289
+ : item . source === 'LSP'
290
+ ? this . _preFilterQuery
291
+ : '' ;
292
+ }
293
+
277
294
protected harmoniseItem ( item : CompletionHandler . ICompletionItem ) {
278
295
if ( ( item as any ) . self ) {
279
296
const self = ( item as any ) . self ;
@@ -306,4 +323,19 @@ export class LSPCompleterModel extends GenericCompleterModel<MaybeCompletionItem
306
323
a . score - b . score
307
324
) ;
308
325
}
326
+
327
+ private _preFilterQuery : string = '' ;
328
+ }
329
+
330
+ export namespace LSPCompleterModel {
331
+ export interface IOptions extends GenericCompleterModel . IOptions {
332
+ /**
333
+ * Whether matches should be pre-filtered (default = true)
334
+ */
335
+ preFilterMatches ?: boolean ;
336
+ }
337
+ export const defaultOptions : IOptions = {
338
+ ...GenericCompleterModel . defaultOptions ,
339
+ preFilterMatches : true
340
+ } ;
309
341
}
0 commit comments