sort text for completions
some cursed heuristics for completions, because nvim-cmp kept getting them wrong. nvim-cmp actually prioritizes kind over sort text, so it will still get it wrong, but I'm hoping that having a correct sort-text helps other editors.
This commit is contained in:
parent
1fb27f876b
commit
c127c54937
@ -188,17 +188,33 @@ fntype is one of fn or λ or lambda"
|
||||
:Snippet 15 :Color 16 :File 17 :Reference 18 :Folder 19 :EnumMember 20
|
||||
:Constant 21 :Struct 22 :Event 23 :Operator 24 :TypeParameter 25})
|
||||
|
||||
(fn int-to-str [int]
|
||||
(string.char (math.min 126 (+ 32 int))))
|
||||
|
||||
(fn sort-text [name kind]
|
||||
(let [parts (-> (name:gsub "[.:]+$" #($:gsub "." "x"))
|
||||
(: :gmatch "[^.:]+"))
|
||||
part-scores (icollect [part parts]
|
||||
(int-to-str (length part)))
|
||||
count (length part-scores)
|
||||
kind (if (= kind 1) 100 kind)]
|
||||
(table.insert part-scores (math.max 1 count) (int-to-str kind))
|
||||
(.. (int-to-str count) (table.concat part-scores))))
|
||||
|
||||
(λ completion-item-format [server name definition range ?kind]
|
||||
"Makes a completion item"
|
||||
{:label name
|
||||
:documentation (when (not server.can-do-good-completions?) (hover-format server name definition))
|
||||
:textEdit (when (not server.can-do-good-completions?) {:newText name : range})
|
||||
:kind (or (?. kinds ?kind)
|
||||
(if (name:find ".:") kinds.Method)
|
||||
(case (navigate.getmetadata server definition)
|
||||
metadata (?. kinds metadata.fls/itemKind))
|
||||
kinds.Value)})
|
||||
(let [kind (or (?. kinds ?kind)
|
||||
(if (name:find ".:") kinds.Method)
|
||||
(case (navigate.getmetadata server definition)
|
||||
metadata (?. kinds metadata.fls/itemKind))
|
||||
(if (name:find "%.") kinds.Field kinds.Value))]
|
||||
{:label name
|
||||
:documentation (when (not server.can-do-good-completions?) (hover-format server name definition))
|
||||
:sortText (sort-text name kind)
|
||||
:textEdit (when (not server.can-do-good-completions?) {:newText name : range})
|
||||
: kind}))
|
||||
|
||||
{: signature-help-format
|
||||
: hover-format
|
||||
: completion-item-format}
|
||||
: completion-item-format
|
||||
: sort-text}
|
||||
|
||||
@ -31,7 +31,7 @@ Every time the client sends a message, it gets handled by a function in the corr
|
||||
;; The LSP spec claims that "characters that make up identifiers don't need to be listed here"
|
||||
;; > https://github.com/microsoft/language-server-protocol/blob/4a4ff53db00d8c5e57630ff364dedf1918cbb612/_specifications/lsp/3.18/language/completion.md?plain=1#L205
|
||||
;; but many editors don't consider these to be identifier characters, even though they are
|
||||
"." "!" "^" "$" "%" "&" "*" "+" "/" "<" "=" ">" "?"]
|
||||
"." ":" "!" "^" "$" "%" "&" "*" "+" "/" "<" "=" ">" "?"]
|
||||
:completionItem {:labelDetailsSupport false}}
|
||||
:hoverProvider {:workDoneProgress false}
|
||||
:signatureHelpProvider {:workDoneProgress false
|
||||
|
||||
@ -157,8 +157,8 @@
|
||||
(fn test-field []
|
||||
(check
|
||||
"(let [my-table {:foo 10 :bar 20}]\n my-table.|)))"
|
||||
[{:label :my-table.foo :kind kinds.Value}
|
||||
{:label :my-table.bar :kind kinds.Value}]
|
||||
[{:label :my-table.foo :kind kinds.Field}
|
||||
{:label :my-table.bar :kind kinds.Field}]
|
||||
[])
|
||||
|
||||
nil)
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
(local {: create-client} (require :test.utils))
|
||||
|
||||
(local analyzer (require :fennel-ls.analyzer))
|
||||
(local utils (require :fennel-ls.utils))
|
||||
(local utils (require :fennel-ls.utils))
|
||||
(local {: sort-text} (require :fennel-ls.formatter))
|
||||
|
||||
|
||||
(fn test-multi-sym-split []
|
||||
@ -64,7 +65,40 @@
|
||||
(faith.= "a/b/c/d" (utils.path-join "a/b" "c/d"))
|
||||
nil)
|
||||
|
||||
|
||||
(fn test-sort-text []
|
||||
(fn assert< [a ak b bk]
|
||||
(faith.= true (< (sort-text a ak) (sort-text b bk))
|
||||
(.. "expected (< (sort-text " (fennel.view a) " " ak ") "
|
||||
"(sort-text " (fennel.view b) " " bk "))")))
|
||||
(fn assert= [a ak b bk]
|
||||
(faith.= true (= (sort-text a ak) (sort-text b bk))
|
||||
(.. "expected (= (sort-text " (fennel.view a) " " ak ") "
|
||||
"(sort-text " (fennel.view b) " " bk "))")))
|
||||
|
||||
;; these are brittle so remove them when sort text requirements change
|
||||
(assert< "aaabbb" 2 "a.b" 2)
|
||||
(assert< "a.bb" 2 "aa.b" 2)
|
||||
(assert< "x.y.zzz" 2 "x.yy.z" 2)
|
||||
(assert< "short.a" 2 "short.bb" 2)
|
||||
(assert< "aaa.a" 2 "bbbb.a" 2)
|
||||
(assert< "aa" 2 "a" 3)
|
||||
(assert< "a.aa" 2 "a.a" 3)
|
||||
(assert< "a.a" 3 "aa.a" 2)
|
||||
(assert< "a" 20 "a" 1)
|
||||
(assert< "" 2 "a" 2)
|
||||
(assert= "a.b:c" 1 "a.b.c" 1)
|
||||
|
||||
;; Operators should be the same, regardless of if .'s are in them in non separator spots
|
||||
(assert= "?." 1 ".." 1)
|
||||
(assert= "." 1 "+" 1)
|
||||
|
||||
;; absolutely please stop recommending string methods as more important than the strings themselves
|
||||
(faith.< (sort-text "_VERSION" 2) (sort-text "_VERSION:gsub" 100))
|
||||
nil)
|
||||
|
||||
{: test-multi-sym-split
|
||||
: test-find-symbol
|
||||
: test-failure
|
||||
: test-path-join}
|
||||
: test-path-join
|
||||
: test-sort-text}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user