-
-
Notifications
You must be signed in to change notification settings - Fork 917
expand-snippet: indent according to the line where snippet is expanded #1939
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
Conversation
@yyoncho Can you check if this change still works fine with your snippets? |
65db4c9
to
cf9ede9
Compare
When I tested it I noticed that the snippets that come from jdtls are not indented with the proper indent level, e. g.
The completion is |
The snippet is indeed indented with I found this redhat-developer/vscode-java#557 (comment), it seems that setting
I can |
In general, this is true, but practically we follow what vscode does. The thing is that there is nothing in the spec that says that the server should format the snippets properly. Also, vscode ATM is performing client-side formatting (I verified that it is also getting |
I think they're still on discussion about that microsoft/language-server-protocol#83. Also I wonder if range formatting in |
It will be an improvement for org-mode integration.
Most likely we should fix formatting after applying text edits as well. FWIW vscode hasn't implemented the client-side formatting for snippets only for JDTLS. It is very likely that there are other servers relying on this undocumented behaviour. |
I'm a little bit skeptical about this, as formatting in elisp is fairly slow, and the indentation may completely different from what language server suggested. |
Most likely we may use rangeFormattingProvider if present, but yes, we should try to avoid elisp formatting. |
cf9ede9
to
333eb28
Compare
If we use |
According to microsoft/language-server-protocol#221 and microsoft/language-server-protocol#83 the default will be relativeIndent = off but in this PR relative indentation is promoted as the default behaviour. Can you point me a scenario with real language server in which the proposed behaviour is better than the 'auto behaviour of yasnippet? |
From what I see in https://github.com/microsoft/language-server-protocol/pull/221/files, the default behavior is
The
Here is some benchmark results (benchmark-run 1000
(with-temp-buffer
(yas-minor-mode +1)
(let ((yas-indent-line 'auto)
(indent-line-function 'rust-mode-indent-line))
(yas-expand-snippet "match list {\n {1:_}: {0},\n}" 1 1))))
(0.308898 0 0.0)
(benchmark-run 1000
(with-temp-buffer
(yas-minor-mode +1)
(let* ((inhibit-field-text-motion t)
(offset (save-excursion
(goto-char 1)
(back-to-indentation)
(buffer-substring-no-properties
(line-beginning-position)
(point))))
(yas-indent-line 'auto)
(yas-also-auto-indent-first-line nil)
(indent-line-function (lambda () (save-excursion
(forward-line 0)
(insert offset)
(if indent-tabs-mode
(tabify (line-beginning-position) (line-end-position))
(untabify (line-beginning-position) (line-end-position)))))))
(yas-expand-snippet "match list {\n {1:_}: {0},\n}" 1 1))))
(0.208318 0 0.0) |
I can point servers with problems with proposed implementation - for example, replacing |
I don't think this is entirely correct, since the server has settings itself to indicate the format. If we have server formatting functionality, I can't see why we shouldn't use server relative indentation here in this case too. |
@yyoncho I found a problem in real language server ( The Also, more information in this microsoft/language-server-protocol#83 (comment) and microsoft/language-server-protocol#880 (comment), it seems that new property Come back to my proposal, do you think it would be ok to use relative indentation when:
|
Can you elaborate on that? I would like to avoid calling the server after expanding the server. Although, we may use the same strategy as the additionalTextEdits but IMO it will be like too much. Especially, with the poor primitives for async programming that we currently have. If we start using deferred/promises it will be easier to compose async calls. |
333eb28
to
8c6ad26
Compare
I mean this kind of check (and lsp-enable-indentation
(or (lsp-feature? "textDocument/rangeFormatting")
(lsp-feature? "textDocument/formatting"))) |
I understand the checks but I do not understand what we will do in then/else clauses |
If the check passed, we will use relative indentation as in https://github.com/microsoft/vscode/blob/master/src/vs/vscode.d.ts#L3865-L3869, since the server can provide format. If the check is not passing, we fallback to Emacs indentation function (same with setting |
I do not like this heuristic. Some server like intelephense allow user defined ATM both relative and 'auto do not cover all of the cases and fail to handle |
Then that's server side issue, isn't it?
Which case it doesn't cover?
It's because we're using My main argument is that snippets are normally defined with correct indentation already, but since we're applying snippets with a certain level of offset, we need to readjust it. Using client side indentation is mostly wasteful, and sometimes may not working well. |
kiennq writes:
Then that's server side issue, isn't it?
No, it is not - the formatting settings are passed when you call
textDocument/format* methods so there is **no** way for the server to
guess them and format the snippet properly because it doesn't know what
are the client settings. So, it is guaranteed that the server will
provide wrongly formatted snippets unless there is some magical/language
spefic way to find the indent size, right?
Which case it doesn't cover?
Relative indentation does not work with JDTLS as I described in previous
comments. And generally, relative indentation will **always** fail ATM
just do
```
(setq tab-width 2)
```
```
(setq tab-width 4)
```
and expand the snippet 2 times.
|
Ok, that makes sense. How about this, I will create a local variable that user can set (via |
Ok, let's have that as an optional feature and later bind it to the new property in CompletionItem.
We should rather introduce server-specific hook e. g. |
Can you elaborate more on this? |
I mean that if we do something like:
And then use that hook we will allow clients to turn off/on a feature. If we use after-open-fn users will have to modify internal structure to achieve what they want. |
Interesting, do you have any suggestion how can we define that hook? |
FTR it will work without defining it.
works just fine. Changing lsp-register-client to be a macro is an old idea, we should do it at some point. And not only about the hook but priority, binary name + args(so we can unify it), etc. But IMO better to introduce a new method or keep the method and call the macro inside of it otherwise we will break the binary compatibility and again that will cause a lot of questions/issues. |
Thinking more about that it is better not to have that as a macro at all. This means that every time we change the macro the code that is bytecompiled agaist that macro will break... Also, when users update all packages package.el does not update the packages in the correct order(e. g. from the root package to the other). This again will cause breakages. |
8c6ad26
to
fea3e01
Compare
@yyoncho Done, I've added new hooks for every client that use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
We should probably think of a way to mark the in which the property was added to the protocol. Because atm we have some experimental one.
lsp-mode.el
Outdated
@@ -3470,10 +3471,14 @@ in that particular folder." | |||
(lsp-managed-mode 1) | |||
|
|||
(run-hooks 'lsp-after-open-hook) | |||
(-some-> lsp--cur-workspace | |||
(-some->> lsp--cur-workspace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit weird structure - can you refactor to (let ((client ..)
and then the lambda block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
77dc4c0
to
7a7b0b4
Compare
Doing what's suggest in #1935 to simply align the expanded snippet with the indentation level of where snippet is expanded.
This should be fairly fast and could be used even in
org-mode
.