helix icon indicating copy to clipboard operation
helix copied to clipboard

Write (:w) in HTML files selects the whole file and loses position when HTML LSP is active

Open aral opened this issue 3 years ago • 8 comments

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:

  1. npm i -g vscode-langservers-extracted to install HTML LSP
  2. Create HTML file
  3. :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)

aral avatar Sep 16 '22 10:09 aral

That's because the formatting response from the LSP effectively removes the whole document then inserts the formatted document (rather than a diff)

archseer avatar Sep 16 '22 11:09 archseer

So is the fix not to include the formatting feature? Because this makes it unusable.

aral avatar Sep 16 '22 12:09 aral

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.

the-mikedavis avatar Sep 16 '22 13:09 the-mikedavis

Alternatively, you can specify an external formatter which Helix will generate a diff for.

kirawi avatar Sep 16 '22 14:09 kirawi

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.

archseer avatar Sep 17 '22 03:09 archseer

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.

kirawi avatar Sep 17 '22 03:09 kirawi

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).

kirawi avatar Sep 17 '22 04:09 kirawi

We only want to deal with the latter and it should be easy to detect: a single change that spans the entire document range.

archseer avatar Sep 17 '22 07:09 archseer