Write (:w) in HTML files selects the whole file and loses position when HTML LSP is active
Summary
Issuing a :w command in an HTML file selects the whole file and loses your current position when HTML LSP is active.
Reproduction Steps
I tried this:
npm i -g vscode-langservers-extractedto install HTML LSP- Create HTML file
:w
I expected this to happen:
File is saved. Nothing is selected. My position is saved.
Instead, this happened:
File is saved. Everything is selected. My position is lost (reverts to top).
Note that this behaviour does not occur if the LSP is not installed/active.
Helix log
~/.cache/helix/helix.log
2022-09-16T11:57:07.545 helix_term::application [ERROR] Language Server: Method not found client/r
Platform
Linux (Fedora Silverblue 36)
Terminal Emulator
Black Box
Helix Version
helix 22.08.1 (714db9c6)
That's because the formatting response from the LSP effectively removes the whole document then inserts the formatted document (rather than a diff)
So is the fix not to include the formatting feature? Because this makes it unusable.
The LSP spec allows for the language server to say what changed in the formatting response in small diffs rather than resending the whole (potentially large) document. This is similar to https://github.com/helix-editor/helix/issues/2655
See also https://github.com/helix-editor/helix/issues/2752 - it may happen because of line-endings of the document. If the language server is replacing CRLFs with LFs it may send the whole document, but that should be a one-time occurrence.
Alternatively, you can specify an external formatter which Helix will generate a diff for.
The solution is to detect a whole document replacement by the format action and run it through the same code we use for external formatters to generate a diff.
similar provides a function: https://docs.rs/similar/2.2.0/similar/fn.get_diff_ratio.html
On second thought, that sounds a little expensive.
Ah right, we could just convert TextEdits into DiffOps. We could generate a diff if a certain amount of the file is entirely replaced, or we could generate a diff only when the entire document is replaced (which is easier/simpler, and what I think most users encounter).
We only want to deal with the latter and it should be easy to detect: a single change that spans the entire document range.