@@ -1874,57 +1874,69 @@ is not active."
1874
1874
1875
1875
(defun eglot-completion-at-point ()
1876
1876
" EGLOT's `completion-at-point' function."
1877
- (let* ((bounds (bounds-of-thing-at-point 'symbol ))
1878
- (server (eglot--current-server-or-lose))
1879
- (completion-capability (eglot--server-capable :completionProvider ))
1880
- (sort-completions (lambda (completions )
1881
- (sort completions
1882
- (lambda (a b )
1883
- (string-lessp
1884
- (or (get-text-property 0 :sortText a) " " )
1885
- (or (get-text-property 0 :sortText b) " " ))))))
1886
- (metadata `(metadata . ((display-sort-function . , sort-completions ))))
1887
- completions)
1888
- (when completion-capability
1877
+ ; ; Commit logs for this function help understand what's going on.
1878
+ (when-let (completion-capability (eglot--server-capable :completionProvider ))
1879
+ (let* ((server (eglot--current-server-or-lose))
1880
+ (sort-completions (lambda (completions )
1881
+ (sort completions
1882
+ (lambda (a b )
1883
+ (string-lessp
1884
+ (or (get-text-property 0 :sortText a) " " )
1885
+ (or (get-text-property 0 :sortText b) " " ))))))
1886
+ (metadata `(metadata . ((display-sort-function . , sort-completions ))))
1887
+ (response (jsonrpc-request server
1888
+ :textDocument/completion
1889
+ (eglot--CompletionParams)
1890
+ :deferred :textDocument/completion
1891
+ :cancel-on-input t ))
1892
+ (items (append ; coerce to list
1893
+ (if (vectorp response) response (plist-get response :items ))
1894
+ nil ))
1895
+ (proxies
1896
+ (mapcar (jsonrpc-lambda
1897
+ (&rest item &key label insertText insertTextFormat
1898
+ &allow-other-keys)
1899
+ (let ((proxy
1900
+ (cond ((and (eql insertTextFormat 2 )
1901
+ (eglot--snippet-expansion-fn))
1902
+ (string-trim-left label))
1903
+ (t
1904
+ (or insertText (string-trim-left label))))))
1905
+ (put-text-property 0 1 'eglot--lsp-item item proxy)
1906
+ proxy))
1907
+ items))
1908
+ (bounds
1909
+ (cl-loop with probe =
1910
+ (plist-get (plist-get (car items) :textEdit ) :range )
1911
+ for item in (cdr items)
1912
+ for range = (plist-get (plist-get item :textEdit ) :range )
1913
+ unless (and range (equal range probe))
1914
+ return (bounds-of-thing-at-point 'symbol )
1915
+ finally (cl-return (or (and probe
1916
+ (eglot--range-region probe))
1917
+ (bounds-of-thing-at-point 'symbol ))))))
1889
1918
(list
1890
1919
(or (car bounds) (point ))
1891
1920
(or (cdr bounds) (point ))
1892
- (lambda (comp pred action )
1921
+ (lambda (probe pred action )
1893
1922
(cond
1894
- ((eq action 'metadata ) metadata) ; metadata
1895
- ((eq action 'lambda ) (member comp completions)) ; test-completion
1896
- ((eq (car-safe action) 'boundaries ) nil ) ; boundaries
1897
- ((and (null action) (member comp completions) t )) ; try-completion
1898
- ((eq action t ) ; all-completions
1899
- (let* ((resp (jsonrpc-request server
1900
- :textDocument/completion
1901
- (eglot--CompletionParams)
1902
- :deferred :textDocument/completion
1903
- :cancel-on-input t ))
1904
- (items (if (vectorp resp) resp (plist-get resp :items ))))
1905
- (setq
1906
- completions
1907
- (all-completions ; <-stuck with prefix-comp because <facepalm> LSP
1908
- comp
1909
- (mapcar
1910
- (jsonrpc-lambda
1911
- (&rest all &key label insertText insertTextFormat
1912
- &allow-other-keys)
1913
- (let ((completion
1914
- (cond ((and (eql insertTextFormat 2 )
1915
- (eglot--snippet-expansion-fn))
1916
- (string-trim-left label))
1917
- (t
1918
- (or insertText (string-trim-left label))))))
1919
- (put-text-property 0 1 'eglot--lsp-completion
1920
- all completion)
1921
- completion))
1922
- items)
1923
- pred))))))
1923
+ ((eq action 'metadata ) metadata) ; metadata
1924
+ ((eq action 'lambda ) (member probe proxies)) ; test-completion
1925
+ ((eq (car-safe action) 'boundaries ) nil ) ; boundaries
1926
+ ((and (null action) (member probe proxies) t )) ; try-completion
1927
+ ((eq action t ) ; all-completions
1928
+ (cl-remove-if-not
1929
+ (lambda (proxy )
1930
+ (let* ((item (get-text-property 0 'eglot--lsp-item proxy))
1931
+ (filterText (plist-get item :filterText )))
1932
+ (and (or (null pred) (funcall pred proxy))
1933
+ (string-prefix-p
1934
+ probe (or filterText proxy) completion-ignore-case))))
1935
+ proxies))))
1924
1936
:annotation-function
1925
- (lambda (obj )
1937
+ (lambda (proxy )
1926
1938
(eglot--dbind ((CompletionItem) detail kind insertTextFormat)
1927
- (get-text-property 0 'eglot--lsp-completion obj )
1939
+ (get-text-property 0 'eglot--lsp-item proxy )
1928
1940
(let* ((detail (and (stringp detail)
1929
1941
(not (string= detail " " ))
1930
1942
detail))
@@ -1939,10 +1951,9 @@ is not active."
1939
1951
(eglot--snippet-expansion-fn)
1940
1952
" (snippet)" ))))))
1941
1953
:company-doc-buffer
1942
- (lambda (obj )
1954
+ (lambda (proxy )
1943
1955
(let* ((documentation
1944
- (let ((lsp-comp
1945
- (get-text-property 0 'eglot--lsp-completion obj)))
1956
+ (let ((lsp-comp (get-text-property 0 'eglot--lsp-item proxy)))
1946
1957
(or (plist-get lsp-comp :documentation )
1947
1958
(and (eglot--server-capable :completionProvider
1948
1959
:resolveProvider )
@@ -1966,46 +1977,45 @@ is not active."
1966
1977
(cl-coerce (cl-getf completion-capability :triggerCharacters ) 'list ))
1967
1978
(line-beginning-position ))))
1968
1979
:exit-function
1969
- (lambda (comp _status )
1970
- (let ((comp (if (get-text-property 0 'eglot--lsp-completion comp)
1971
- comp
1972
- ; ; When selecting from the *Completions*
1973
- ; ; buffer, `comp' won't have any properties. A
1974
- ; ; lookup should fix that (github#148)
1975
- (cl-find comp completions :test #'string= ))))
1976
- (eglot--dbind ((CompletionItem) insertTextFormat
1977
- insertText
1978
- textEdit
1979
- additionalTextEdits)
1980
- (get-text-property 0 'eglot--lsp-completion comp)
1981
- (let ((snippet-fn (and (eql insertTextFormat 2 )
1982
- (eglot--snippet-expansion-fn))))
1983
- (cond (textEdit
1984
- ; ; Undo the just the completed bit. If before
1985
- ; ; completion the buffer was "foo.b" and now is
1986
- ; ; "foo.bar", `comp' will be "bar". We want to
1987
- ; ; delete only "ar" (`comp' minus the symbol
1988
- ; ; whose bounds we've calculated before)
1989
- ; ; (github#160).
1990
- (delete-region (+ (- (point ) (length comp))
1991
- (if bounds (- (cdr bounds) (car bounds)) 0 ))
1992
- (point ))
1993
- (eglot--dbind ((TextEdit) range newText) textEdit
1994
- (pcase-let ((`(, beg . , end ) (eglot--range-region range)))
1995
- (delete-region beg end)
1996
- (goto-char beg)
1997
- (funcall (or snippet-fn #'insert ) newText)))
1998
- (when (cl-plusp (length additionalTextEdits))
1999
- (eglot--apply-text-edits additionalTextEdits)))
2000
- (snippet-fn
2001
- ; ; A snippet should be inserted, but using plain
2002
- ; ; `insertText' . This requires us to delete the
2003
- ; ; whole completion, since `insertText' is the full
2004
- ; ; completion's text.
2005
- (delete-region (- (point ) (length comp)) (point ))
2006
- (funcall snippet-fn insertText))))
2007
- (eglot--signal-textDocument/didChange)
2008
- (eglot-eldoc-function))))))))
1980
+ (lambda (proxy _status )
1981
+ (eglot--dbind ((CompletionItem) insertTextFormat
1982
+ insertText
1983
+ textEdit
1984
+ additionalTextEdits)
1985
+ (or (get-text-property 0 'eglot--lsp-item proxy)
1986
+ ; ; When selecting from the *Completions*
1987
+ ; ; buffer, `proxy' won't have any properties. A
1988
+ ; ; lookup should fix that (github#148)
1989
+ (get-text-property
1990
+ 0 'eglot--lsp-item (cl-find proxy proxies :test #'string= )))
1991
+ (let ((snippet-fn (and (eql insertTextFormat 2 )
1992
+ (eglot--snippet-expansion-fn))))
1993
+ (cond (textEdit
1994
+ ; ; Undo (yes, undo) the newly inserted completion.
1995
+ ; ; If before completion the buffer was "foo.b" and
1996
+ ; ; now is "foo.bar", `proxy' will be "bar". We
1997
+ ; ; want to delete only "ar" (`proxy' minus the
1998
+ ; ; symbol whose bounds we've calculated before)
1999
+ ; ; (github#160).
2000
+ (delete-region (+ (- (point ) (length proxy))
2001
+ (if bounds (- (cdr bounds) (car bounds)) 0 ))
2002
+ (point ))
2003
+ (eglot--dbind ((TextEdit) range newText) textEdit
2004
+ (pcase-let ((`(, beg . , end ) (eglot--range-region range)))
2005
+ (delete-region beg end)
2006
+ (goto-char beg)
2007
+ (funcall (or snippet-fn #'insert ) newText)))
2008
+ (when (cl-plusp (length additionalTextEdits))
2009
+ (eglot--apply-text-edits additionalTextEdits)))
2010
+ (snippet-fn
2011
+ ; ; A snippet should be inserted, but using plain
2012
+ ; ; `insertText' . This requires us to delete the
2013
+ ; ; whole completion, since `insertText' is the full
2014
+ ; ; completion's text.
2015
+ (delete-region (- (point ) (length proxy)) (point ))
2016
+ (funcall snippet-fn insertText))))
2017
+ (eglot--signal-textDocument/didChange)
2018
+ (eglot-eldoc-function)))))))
2009
2019
2010
2020
(defvar eglot--highlights nil " Overlays for textDocument/documentHighlight." )
2011
2021
0 commit comments