@@ -103,17 +103,14 @@ func (s *server) completeMetricName(ctx context.Context, completions *[]protocol
103103 return err
104104 }
105105
106- names := make ([]string , len (allMetadata ))
107- i := 0
106+ names := make ([]string , 0 , len (allMetadata ))
108107 for name := range allMetadata {
109- names [i ] = name
110- i ++
108+ names = append (names , name )
111109 }
112- matches := fuzzy .Find (metricName , names )
113- for _ , match := range matches {
110+ for _ , match := range getMatches (metricName , names ) {
114111 item := protocol.CompletionItem {
115112 Label : match .Str ,
116- SortText : fmt .Sprintf ("__3__%d " , match .Score ),
113+ SortText : fmt .Sprintf ("__3__%09d " , match .Score ),
117114 Kind : 12 , //Value
118115 Documentation : allMetadata [match .Str ][0 ].Help ,
119116 Detail : string (allMetadata [match .Str ][0 ].Type ),
@@ -130,20 +127,22 @@ func (s *server) completeMetricName(ctx context.Context, completions *[]protocol
130127 return err
131128 }
132129
130+ names = make ([]string , 0 , len (queries ))
133131 for _ , q := range queries {
134- if rec := q . Record ; rec != "" && strings . HasPrefix ( rec , metricName ) {
135- item := protocol. CompletionItem {
136- Label : rec ,
137- SortText : "__2__" + rec ,
138- Kind : 3 , //Value
139- InsertTextFormat : 2 , //Snippet
140- TextEdit : & protocol. TextEdit {
141- Range : editRange ,
142- NewText : rec ,
143- } ,
144- }
145- * completions = append ( * completions , item )
132+ names = append ( names , q . Record )
133+ }
134+ for _ , match := range getMatches ( metricName , names ) {
135+ item := protocol. CompletionItem {
136+ Label : match . Str ,
137+ SortText : fmt . Sprintf ( "__2__%09d" , match . Score ),
138+ Kind : 3 , //Value
139+ InsertTextFormat : 2 , //Snippet
140+ TextEdit : & protocol. TextEdit {
141+ Range : editRange ,
142+ NewText : match . Str ,
143+ },
146144 }
145+ * completions = append (* completions , item )
147146 }
148147
149148 return nil
@@ -155,41 +154,45 @@ func (s *server) completeFunctionName(completions *[]protocol.CompletionItem, lo
155154 return err
156155 }
157156
157+ names := make ([]string , 0 , len (promql .Functions ))
158158 for name := range promql .Functions {
159- if strings . HasPrefix ( strings . ToLower ( name ), metricName ) {
160- item := protocol. CompletionItem {
161- Label : name ,
162- SortText : "__1__" + name ,
163- Kind : 3 , //Function
164- InsertTextFormat : 2 , //Snippet
165- TextEdit : & protocol. TextEdit {
166- Range : editRange ,
167- NewText : name + "($1)" ,
168- } ,
169- Command : & protocol. Command {
170- // This might create problems with non VS Code clients
171- Command : "editor.action.triggerParameterHints" ,
172- },
173- }
174- * completions = append ( * completions , item )
159+ names = append ( names , name )
160+ }
161+ for _ , match := range getMatches ( metricName , names ) {
162+ item := protocol. CompletionItem {
163+ Label : match . Str ,
164+ SortText : fmt . Sprintf ( "__1__%09d" , match . Score ),
165+ Kind : 3 , //Function
166+ InsertTextFormat : 2 , //Snippet
167+ TextEdit : & protocol. TextEdit {
168+ Range : editRange ,
169+ NewText : match . Str + "($1)" ,
170+ },
171+ Command : & protocol. Command {
172+ // This might create problems with non VS Code clients
173+ Command : "editor.action.triggerParameterHints" ,
174+ },
175175 }
176+ * completions = append (* completions , item )
176177 }
177178
178- for name , desc := range aggregators {
179- if strings .HasPrefix (strings .ToLower (name ), metricName ) {
180- item := protocol.CompletionItem {
181- Label : name ,
182- SortText : "__1__" + name ,
183- Kind : 3 , //Function
184- InsertTextFormat : 2 , //Snippet
185- Detail : desc ,
186- TextEdit : & protocol.TextEdit {
187- Range : editRange ,
188- NewText : name + "($1)" ,
189- },
190- }
191- * completions = append (* completions , item )
179+ names = make ([]string , 0 , len (aggregators ))
180+ for name := range aggregators {
181+ names = append (names , name )
182+ }
183+ for _ , match := range getMatches (strings .ToLower (metricName ), names ) {
184+ item := protocol.CompletionItem {
185+ Label : match .Str ,
186+ SortText : fmt .Sprintf ("__1__%09d" , match .Score ),
187+ Kind : 3 , //Function
188+ InsertTextFormat : 2 , //Snippet
189+ Detail : aggregators [match .Str ],
190+ TextEdit : & protocol.TextEdit {
191+ Range : editRange ,
192+ NewText : match .Str + "($1)" ,
193+ },
192194 }
195+ * completions = append (* completions , item )
193196 }
194197
195198 return nil
@@ -318,41 +321,38 @@ func (s *server) completeLabel(ctx context.Context, completions *[]protocol.Comp
318321 return err
319322 }
320323
321- sort .Strings (allNames )
322-
323324 editRange , err := getEditRange (location , "" )
324325 if err != nil {
325326 return err
326327 }
327328
329+ labelName := location .Node .(* promql.Item ).Val
330+ var prevMatched string
328331OUTER:
329- for i , name := range allNames {
332+ for _ , match := range getMatches ( labelName , allNames ) {
330333 // Skip duplicates
331- if i > 0 && allNames [ i - 1 ] == name {
334+ if prevMatched == match . Str {
332335 continue
333336 }
334-
335- if strings .HasPrefix (name , location .Node .(* promql.Item ).Val ) {
336- // Skip labels that already have matchers
337- if vs != nil {
338- for _ , m := range vs .LabelMatchers {
339- if m != nil && m .Name == name {
340- continue OUTER
341- }
337+ prevMatched = match .Str
338+ // Skip labels that already have matchers
339+ if vs != nil {
340+ for _ , m := range vs .LabelMatchers {
341+ if m != nil && m .Name == match .Str {
342+ continue OUTER
342343 }
343344 }
345+ }
344346
345- item := protocol.CompletionItem {
346- Label : name ,
347- Kind : 12 , //Value
348- TextEdit : & protocol.TextEdit {
349- Range : editRange ,
350- NewText : name ,
351- },
352- }
353-
354- * completions = append (* completions , item )
347+ item := protocol.CompletionItem {
348+ Label : match .Str ,
349+ Kind : 12 , //Value
350+ TextEdit : & protocol.TextEdit {
351+ Range : editRange ,
352+ NewText : match .Str ,
353+ },
355354 }
355+ * completions = append (* completions , item )
356356 }
357357
358358 return nil
@@ -392,40 +392,42 @@ func (s *server) completeLabelValue(ctx context.Context, completions *[]protocol
392392 quote = '"'
393393 }
394394
395- for _ , name := range labelValues {
396- if strings .HasPrefix (string (name ), unquoted ) {
397- var quoted string
395+ names := make ([]string , 0 , len (labelValues ))
396+ for _ , v := range labelValues {
397+ names = append (names , string (v ))
398+ }
399+ for _ , match := range getMatches (unquoted , names ) {
400+ var quoted string
398401
399- if quote == '`' {
400- if strings .ContainsRune (string (name ), '`' ) {
401- quote = '"'
402- } else {
403- quoted = fmt .Sprint ("`" , name , "`" )
404- }
402+ if quote == '`' {
403+ if strings .ContainsRune (match .Str , '`' ) {
404+ quote = '"'
405+ } else {
406+ quoted = fmt .Sprint ("`" , match .Str , "`" )
405407 }
408+ }
406409
407- if quoted == "" {
408- quoted = strconv .Quote (string ( name ) )
409- }
410+ if quoted == "" {
411+ quoted = strconv .Quote (match . Str )
412+ }
410413
411- if quote == '\'' {
412- quoted = quoted [1 : len (quoted )- 1 ]
414+ if quote == '\'' {
415+ quoted = quoted [1 : len (quoted )- 1 ]
413416
414- quoted = strings .ReplaceAll (quoted , `\"` , `"` )
415- quoted = strings .ReplaceAll (quoted , `'` , `\'` )
416- quoted = fmt .Sprint ("'" , quoted , "'" )
417- }
417+ quoted = strings .ReplaceAll (quoted , `\"` , `"` )
418+ quoted = strings .ReplaceAll (quoted , `'` , `\'` )
419+ quoted = fmt .Sprint ("'" , quoted , "'" )
420+ }
418421
419- item := protocol.CompletionItem {
420- Label : quoted ,
421- Kind : 12 , //Value
422- TextEdit : & protocol.TextEdit {
423- Range : editRange ,
424- NewText : quoted ,
425- },
426- }
427- * completions = append (* completions , item )
422+ item := protocol.CompletionItem {
423+ Label : quoted ,
424+ Kind : 12 , //Value
425+ TextEdit : & protocol.TextEdit {
426+ Range : editRange ,
427+ NewText : quoted ,
428+ },
428429 }
430+ * completions = append (* completions , item )
429431 }
430432
431433 return nil
@@ -452,3 +454,21 @@ func getEditRange(location *cache.Location, oldname string) (editRange protocol.
452454
453455 return
454456}
457+
458+ // getMatches returns fuzzy matches for a slice of string and a pattern.
459+ func getMatches (pattern string , names []string ) fuzzy.Matches {
460+ if pattern == "" {
461+ var matches fuzzy.Matches
462+ sort .Strings (names )
463+ for i , name := range names {
464+ matches = append (matches ,
465+ fuzzy.Match {
466+ Str : name ,
467+ Index : i ,
468+ Score : len (names ) - i ,
469+ })
470+ }
471+ return matches
472+ }
473+ return fuzzy .Find (pattern , names )
474+ }
0 commit comments