Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for snippet based completion #50

Closed
amol-mandhane opened this issue Jul 26, 2018 · 10 comments
Closed

Support for snippet based completion #50

amol-mandhane opened this issue Jul 26, 2018 · 10 comments

Comments

@amol-mandhane
Copy link

LSP servers support snippet based completion which can insert template arguments of the functions while completion.

Example of snippet based completion: https://i.stack.imgur.com/4gKHP.gif

The capability of snippet completion can be registered by setting TextDocumentClientCapabilities.completion.completionItem.snippetSupport to true, which is false by default.

Whether the completion item is plaintext or snippet is given by CompletionItem.kind field.

Yasnippet can be used to manage completion snippets. The support can be conditionally enabled if user has yasnippet installed so that package doesn't have hard dependency on yasnippet.

@joaotavora
Copy link
Owner

Here's a screenshot of the diff.

Wow, such technology!

Now, seriously thanks. I'll try to implement this. Ideally, It should use snippet.el, not yasnippet.el, but I never finished that refactoring...

@rgrinberg
Copy link

Ideally, It should use snippet.el, not yasnippet.el, but I never finished that refactoring...

Curious, why is that? yasnippet is your package so you obviously know, but I've never even heard of snippet.el

@joaotavora
Copy link
Owner

Curious, why is that?

Nothing special. It's just that yasnippet is way too bloated with stuff that eglot users might not care about, such as menus and snippet-organization logic.

So a few years ago I started writing snippet.el from scratch in that repository. It's the snippet expansion and navigation core of yasnippet rewritten in good elisp. It's workable already but is missing the final stretch that would make it a library that yasnippet could use.

And if it existed, eglot should use that.

yasnippet is your package

Not quite. Though technically I rewrote every line, it's initially @pluskid's package. @npostavs is the new maintainer now.

joaotavora added a commit that referenced this issue Aug 10, 2018
* eglot.el (eglot-client-capabilities): Declare support for
snippet-based completions.
(eglot-completion-at-point): Expand snippet completions with
YASnippet if that is found.
@joaotavora
Copy link
Owner

@amol-mandhane, can you test the newest version?

@garyo
Copy link
Contributor

garyo commented Oct 29, 2019

I'm using vue mode with vue-language-server. I can't seem to trigger completionItem/resolve with eglot (I'm using the latest github head from yesterday, Oct 28, 2019). This issue says it should work, but I don't know how to make it happen. When I try the same server with lsp-mode, the server returns snippets in completionItem/resolve when you complete a completion, like this:

	[Trace - 05:33:09 PM] Sending request 'completionItem/resolve - (47)'.
	Params: {
	  "data": {
	    "entryName": "entries",
	    "offset": 56,
	    "uri": "file:///c:/tmp/vls-lsp-problem/test.ts"
	  },
	  "sortText": "0",
	  "kind": 3,
	  "label": "entries"
	}
	
	
	[Trace - 05:33:09 PM] Received response 'completionItem/resolve - (47)' in 20ms.
	Result: {
	  "insertTextFormat": 2,
	  "insertText": "entries(${1:obj}, ${2:key})",
	  "detail": "function entries<T>(obj: {\n    [key: string]: T;\n} | ArrayLike<T>): {\n    key: string;\n    value: T;\n}[] (+1 overload)",
	  "documentation": "Returns an array containing the property keys and values of the specified object (an associative array).\nEach entry is an object with a key and value attribute.The order of the returned array is undefined.\n\nThe generic refers to the data type of the values.",
	  "sortText": "0",
	  "kind": 3,
	  "label": "entries"
	}

It has an insertText snippet with format 2, which is right, and then yasnippet lets me fill in the args. Does eglot send completionItem/resolve? How do I trigger it to do that?

@joaotavora
Copy link
Owner

joaotavora commented Oct 29, 2019 via email

joaotavora added a commit that referenced this issue Oct 30, 2019
It was already used to resolve documentation bits of completions, but
it can also be useful to resolve snippet templates and such.

To resolve a completion, you need some part of a completion to start
with.  If it has a :data field exists and the server supports
:resolveProvider, fetch the new object, otherwise use whatever we had
already.

* eglot.el (eglot-completion-at-point): Add another local
function for resolving completions.
@joaotavora
Copy link
Owner

@garyo , this is a totally "blind" since I very much want to avoid installing that Vue thing as much as I can :-).

So I created a new branch and did a commit there which you should test. Maybe it fixes your issue. If it doesn't we'll iterate until it does.

@garyo
Copy link
Contributor

garyo commented Oct 30, 2019

Progress -- I now get snippets in a pure typescript buffer. Per your other message, I already had yasnippet and yas-global-mode set up, and I can confirm eglot is telling the server it supports snippets. Also, the log above is actually from a typescript (jsts-ls) server (my mistake, sorry), and with your patch eglot is working fine with that server now.

I guess vetur/vls doesn't support function completion snippets though. I don't have them working with lsp-mode either. I'm not getting any insertText in the completionItem/resolve reply for a function completion. Hmm, I thought it did -- it has its own global snippets, which are working, but who knows.

client-request (id:75) Wed Oct 30 11:54:38 2019:
(:jsonrpc "2.0" :id 75 :method "textDocument/completion" :params
          (:textDocument
           (:uri "file:///c:/tmp/vls-lsp-problem/test.vue")
           :position
           (:line 12 :character 11)
           :context
           (:triggerKind 1)))

server-reply (id:75) Wed Oct 30 11:54:39 2019:
(:jsonrpc "2.0" :id 75 :result
          (:isIncomplete :json-false :items
                         [(:uri "file:///c:/tmp/vls-lsp-problem/test.vue" :position
                                (:line 12 :character 11)
                                :label "arguments" :sortText "00" :kind 6 :data
                                (:languageId "typescript" :uri "file:///c:/tmp/vls-lsp-problem/test.vue" :offset 194))
                          (:uri "file:///c:/tmp/vls-lsp-problem/test.vue" :position
                                (:line 12 :character 11)
                                :label "fooFunction" :sortText "01" :kind 3 :data
                                (:languageId "typescript" :uri "file:///c:/tmp/vls-lsp-problem/test.vue" :offset 194))
              ...(lots more here)...

client-request (id:82) Wed Oct 30 11:54:39 2019:
(:jsonrpc "2.0" :id 82 :method "completionItem/resolve" :params
          (:uri "file:///c:/tmp/vls-lsp-problem/test.vue" :position
                (:line 12 :character 11)
                :label
                #("fooFunction" 0 1
                  (eglot--lsp-item #1))
                :sortText "01" :kind 3 :data
                (:languageId "typescript" :uri "file:///c:/tmp/vls-lsp-problem/test.vue" :offset 194)))

server-reply (id:82) Wed Oct 30 11:54:39 2019:
(:jsonrpc "2.0" :id 82 :result
          (:uri "file:///c:/tmp/vls-lsp-problem/test.vue" :position
                (:line 12 :character 11)
                :label "fooFunction" :sortText "01" :kind 3 :detail "function fooFunction(alpha: string, beta: number): string" :documentation
                (:kind "markdown" :value "")))

And, I just tested vls in VS Code: same thing. The "special" vue snippets work there (as they do now with your patch in eglot), but no snippets on function completion. So I think your patch in your scratch branch is fine!

@joaotavora
Copy link
Owner

Also, the log above is actually from a typescript (jsts-ls) server (my mistake, sorry), and with your patch eglot is working fine with that server now.

So if I understand correctly the semi-blind untested completionItem/resolve thing is working.

And, I just tested vls in VS Code: same thing. The "special" vue snippets work there (as they do now with your patch in eglot), but no snippets on function completion. So I think your patch in your scratch branch is fine!

Cool!

@garyo
Copy link
Contributor

garyo commented Oct 30, 2019

So if I understand correctly the semi-blind untested completionItem/resolve thing is working.

Yes, it's working for me!

joaotavora added a commit that referenced this issue Oct 30, 2019
It was already used to resolve documentation bits of completions, but
it can also be useful to resolve snippet templates and such.

To resolve a completion, you need some part of a completion to start
with.  If it has a :data field exists and the server supports
:resolveProvider, fetch the new object, otherwise use whatever we had
already.

* eglot.el (eglot-completion-at-point): Add another local
function for resolving completions.
xuchunyang pushed a commit to xuchunyang/eglot that referenced this issue Nov 16, 2019
It was already used to resolve documentation bits of completions, but
it can also be useful to resolve snippet templates and such.

To resolve a completion, you need some part of a completion to start
with.  If it has a :data field exists and the server supports
:resolveProvider, fetch the new object, otherwise use whatever we had
already.

* eglot.el (eglot-completion-at-point): Add another local
function for resolving completions.
bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 18, 2022
* eglot.el (eglot-client-capabilities): Declare support for
snippet-based completions.
(eglot-completion-at-point): Expand snippet completions with
YASnippet if that is found.
(eglot-note, eglot-warning, eglot-error): Diagnostic
overlay priorities have to be slightly lower than yasnippet's,
which must be reasonably high.
bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 18, 2022
It was already used to resolve documentation bits of completions, but
it can also be useful to resolve snippet templates and such.

To resolve a completion, you need some part of a completion to start
with.  If it has a :data field exists and the server supports
:resolveProvider, fetch the new object, otherwise use whatever we had
already.

* eglot.el (eglot-completion-at-point): Add another local
function for resolving completions.
bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 19, 2022
* eglot.el (eglot-client-capabilities): Declare support for
snippet-based completions.
(eglot-completion-at-point): Expand snippet completions with
YASnippet if that is found.
(eglot-note, eglot-warning, eglot-error): Diagnostic
overlay priorities have to be slightly lower than yasnippet's,
which must be reasonably high.
bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 19, 2022
It was already used to resolve documentation bits of completions, but
it can also be useful to resolve snippet templates and such.

To resolve a completion, you need some part of a completion to start
with.  If it has a :data field exists and the server supports
:resolveProvider, fetch the new object, otherwise use whatever we had
already.

* eglot.el (eglot-completion-at-point): Add another local
function for resolving completions.
bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 19, 2022
* eglot.el (eglot-client-capabilities): Declare support for
snippet-based completions.
(eglot-completion-at-point): Expand snippet completions with
YASnippet if that is found.
(eglot-note, eglot-warning, eglot-error): Diagnostic
overlay priorities have to be slightly lower than yasnippet's,
which must be reasonably high.

#50: joaotavora/eglot#50
bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 19, 2022
It was already used to resolve documentation bits of completions, but
it can also be useful to resolve snippet templates and such.

To resolve a completion, you need some part of a completion to start
with.  If it has a :data field exists and the server supports
:resolveProvider, fetch the new object, otherwise use whatever we had
already.

* eglot.el (eglot-completion-at-point): Add another local
function for resolving completions.

#50: joaotavora/eglot#50
jollaitbot pushed a commit to sailfishos-mirror/emacs that referenced this issue Oct 12, 2022
* eglot.el (eglot-client-capabilities): Declare support for
snippet-based completions.
(eglot-completion-at-point): Expand snippet completions with
YASnippet if that is found.
(eglot-note, eglot-warning, eglot-error): Diagnostic
overlay priorities have to be slightly lower than yasnippet's,
which must be reasonably high.

GitHub-reference: close joaotavora/eglot#50
jollaitbot pushed a commit to sailfishos-mirror/emacs that referenced this issue Oct 12, 2022
It was already used to resolve documentation bits of completions, but
it can also be useful to resolve snippet templates and such.

To resolve a completion, you need some part of a completion to start
with.  If it has a :data field exists and the server supports
:resolveProvider, fetch the new object, otherwise use whatever we had
already.

* eglot.el (eglot-completion-at-point): Add another local
function for resolving completions.

GitHub-reference: per joaotavora/eglot#50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants