-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
LSP: vim.lsp.buf.formatting_sync() messes up marks #14307
Comments
I think the root cause of this is that There's a PR pending (#13703) which would change it to use |
I think the author might be talking about regular vim marks instead of extmarks; |
Yes, that's correct, talking about regular marks! Wasn't sure what extmarks were 😄 |
I noticed that as well, but never thought I was due to LSP :) Will see if I can make a PR for this, since it's pretty annoying |
Any chance the maintainers could revisit this? I noticed that @folke was kind enough to provide a pr that has been closed. In the comments to the PR a contributer mentioned that this is due to the fact that after formatting some marks point to garbage; and as such the user should "assume" that after formatting a file all marks will be removed. As a user I don't agree, and would appreciate some config option that would incorporate this pr. Something like: nvim_lsp.my_lang_server.setup({ keep_marks_even_if_garbage = True }) In practise, formatting the text would in all likelihood keep most of my marks exactly the same. Let's take this example:
On the first column we have the marks, second we have the line number. Assume that mark C points to the 'p' character in "python" on line 4. After running my formatting program I'd end up with:
Marks 'a' and 'b' remain exactly the same, and using Edit: Another point in favour of adopting the PR is that marks aren't deleted when calling an external formatter on a buffer. If I invoke |
PROBLEM: Whenever any text edits are applied to the buffer, the `marks` part of those lines will be lost. This is mostly problematic for code formatters that format the whole buffer like `prettier`, `luafmt`, ... When doing atomic changes inside a vim doc, vim keeps track of those changes and can update the positions of marks accordingly, but in this case we have a whole doc that changed. There's no simple way to update the positions of all marks from the previous document state to the new document state. SOLUTION: * save marks right before `nvim_buf_set_lines` is called inside `apply_text_edits` * check if any marks were lost after doing `nvim_buf_set_lines` * restore those marks to the previous positions TEST CASE: * have a formatter enabled * open any file * create a couple of marks * indent the whole file to the right * save the file Before this change: all marks will be removed. After this change: they will be preserved. Fixes #14307
The signs flickered because nvim_buf_set_lines() removes all signs from lines that it touches, which will immediately be readded by Ale (causing the brief flicker). This is intended behaviour in neovim [0]. Neovim itself faced this problem in their own LSP formatting sync, although they had the problem with marks instead of signs [1]. Similar to how neovim fixed it by storing and restoring the marks [2], we can do the same thing with signs. In fact it is easier with signs, because sign_placelist() will just ignore and skip invalid line numbers, so we don't need to filter signs that are not valid anymore. [0] neovim/neovim#10880 (comment) [1] neovim/neovim#14307 [2] neovim/neovim#14630
The signs flickered because nvim_buf_set_lines() removes all signs from lines that it touches, which will immediately be readded by Ale (causing the brief flicker). This is intended behaviour in neovim [0]. Neovim itself faced this problem in their own LSP formatting sync, although they had the problem with marks instead of signs [1]. Similar to how neovim fixed it by storing and restoring the marks [2], we can do the same thing with signs. In fact it is easier with signs, because sign_placelist() will just ignore and skip invalid line numbers, so we don't need to filter signs that are not valid anymore. [0] neovim/neovim#10880 (comment) [1] neovim/neovim#14307 [2] neovim/neovim#14630
The signs flickered because nvim_buf_set_lines() removes all signs from lines that it touches, which will immediately be readded by Ale (causing the brief flicker). This is intended behaviour in neovim [0]. Neovim itself faced this problem in their own LSP formatting sync, although they had the problem with marks instead of signs [1]. Similar to how neovim fixed it by storing and restoring the marks [2], we can do the same thing with signs. In fact it is easier with signs, because sign_placelist() will just ignore and skip invalid line numbers, so we don't need to filter signs that are not valid anymore. [0] neovim/neovim#10880 (comment) [1] neovim/neovim#14307 [2] neovim/neovim#14630
* Avoid performance problems with setbufline() and Treesitter Call nvim_buf_set_lines() instead. Since this is a performance problem only in Neovim (Treesitter is only available there), it doesn't matter that this API is unavailable in Vim. Note: nvim_buf_set_lines() returns E5555, when set nomodifiable is on. Fixes #3669 * Avoid sign flickering The signs flickered because nvim_buf_set_lines() removes all signs from lines that it touches, which will immediately be readded by Ale (causing the brief flicker). This is intended behaviour in neovim [0]. Neovim itself faced this problem in their own LSP formatting sync, although they had the problem with marks instead of signs [1]. Similar to how neovim fixed it by storing and restoring the marks [2], we can do the same thing with signs. In fact it is easier with signs, because sign_placelist() will just ignore and skip invalid line numbers, so we don't need to filter signs that are not valid anymore. [0] neovim/neovim#10880 (comment) [1] neovim/neovim#14307 [2] neovim/neovim#14630
* Avoid performance problems with setbufline() and Treesitter Call nvim_buf_set_lines() instead. Since this is a performance problem only in Neovim (Treesitter is only available there), it doesn't matter that this API is unavailable in Vim. Note: nvim_buf_set_lines() returns E5555, when set nomodifiable is on. Fixes dense-analysis#3669 * Avoid sign flickering The signs flickered because nvim_buf_set_lines() removes all signs from lines that it touches, which will immediately be readded by Ale (causing the brief flicker). This is intended behaviour in neovim [0]. Neovim itself faced this problem in their own LSP formatting sync, although they had the problem with marks instead of signs [1]. Similar to how neovim fixed it by storing and restoring the marks [2], we can do the same thing with signs. In fact it is easier with signs, because sign_placelist() will just ignore and skip invalid line numbers, so we don't need to filter signs that are not valid anymore. [0] neovim/neovim#10880 (comment) [1] neovim/neovim#14307 [2] neovim/neovim#14630
nvim --version
:Steps to reproduce using nvim -u minimal_init.lua
(You will need prettier installed in the example below, but I don't think the particular formatter matters)
Actual behaviour
Mark is removed (or moved to the top of the file)
Observation:
If
:wshada!
is executed before saving and:rshada!
after, the marks are restored to proper positionExpected behaviour
Marks stay in place.
A hacky workaround:
Wasn't sure how expensive
:wshada/rshada
are so wrote the following instead to use on BufWritePreThe text was updated successfully, but these errors were encountered: