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

[Bug]: Invalid highlighting after buffer changes from outside neovim #28

Closed
LiadOz opened this issue Aug 21, 2023 · 6 comments
Closed
Assignees
Labels
bug Something isn't working

Comments

@LiadOz
Copy link

LiadOz commented Aug 21, 2023

Neovim version

0.9.1

Language affected

No response

Query

No response

Strategy

No response

Description

When a file content changes outside of neovim the existing buffer highlights are still the same, meaning that it may highlight characters that were in a position of brackets before the change. In believe this is the same issue as HiPhish/nvim-ts-rainbow2#49 (comment) mrjones2014/nvim-ts-rainbow#9 p00f/nvim-ts-rainbow#112
I have submitted the following fix to one of the rainbow forks mrjones2014/nvim-ts-rainbow#8 I believe it should be a similar fix here.
To easily reproduce create a file called a.py with the following content:

hello
((()))

Then with another editor add a line before hello, when switching back to neovim you should see that hello has highlights.

@LiadOz LiadOz added the bug Something isn't working label Aug 21, 2023
@HiPhish
Copy link
Owner

HiPhish commented Aug 24, 2023

Yes, that's a known issue. This will most likely take a good while to fix. In the meantime you can :edit the file to force highlighting to be fixed.

@LiadOz
Copy link
Author

LiadOz commented Aug 24, 2023

I don't think the solution should be too complex, here is a dirty way to achieve it:

diff --git a/plugin/rainbow-delimiters.lua b/plugin/rainbow-delimiters.lua
index 6dfbe70..59f811e 100644
--- a/plugin/rainbow-delimiters.lua
+++ b/plugin/rainbow-delimiters.lua
@@ -55,11 +55,18 @@ function attach(bufnr)
        end
        log.trace('Attaching to buffer %d with language %s.', bufnr, lang)

+       local first = true
        if lib.buffers[bufnr] then
-               if lib.buffers[bufnr].lang == lang then return end
-               -- The file type of the buffer has change, so we need to detach first
-               -- before we re-attach
-               detach(bufnr)
+               if lib.buffers[bufnr].lang == lang then
+                       local _, parser = pcall(get_parser, bufnr, lang)
+                       parser:invalidate(true)
+                       parser:parse()
+                       first = false
+               else
+                       -- The file type of the buffer has change, so we need to detach first
+                       -- before we re-attach
+                       detach(bufnr)
+               end
        end

        local parser
@@ -85,15 +92,17 @@ function attach(bufnr)
                log.warn('No strategy defined for %s', lang)
        end

-       parser:register_cbs {
-               on_detach = function(bnr)
-                       if not lib.buffers[bnr] then return end
-                       detach(bufnr)
-               end,
-               on_child_removed = function(child)
-                       lib.clear_namespace(bufnr, child:lang())
-               end,
-       }
+       if first then
+               parser:register_cbs {
+                       on_detach = function(bnr)
+                               if not lib.buffers[bnr] then return end
+                               detach(bufnr)
+                       end,
+                       on_child_removed = function(child)
+                               lib.clear_namespace(bufnr, child:lang())
+                       end,
+               }
+       end

        local settings = {
                strategy = strategy,

The idea here is to use lib.buffers[bufnr].lang to check if the buffer is already loaded then invalidate the current parser. Then you need to update all of the highlights in the buffer, in the global strategy calling on_attach will do a full update of all the highlights of the buffer.
To make this prettier, an on_reload function can be added to the strategies which goes over the entire tree and updates all the highlights.

@HiPhish
Copy link
Owner

HiPhish commented Aug 25, 2023

I like your idea, especially the on_reset function. However, when I press u to undo the edit the attach does not get called. It's still better than what we have now, so I will adopt it, but it is not perfect.

@HiPhish
Copy link
Owner

HiPhish commented Aug 26, 2023

Can you please try the current master branch with a recent snapshot of Neovim 0.10? Undo will not work on 0.9 and if you redo after an undo there will be stray extmarks again. But it should work fine on 0.10.

@chrisgrieser
Copy link

I am on 0.9 and just tried the current master. The issue is fixed for me, and undo works fine for me.

@LiadOz
Copy link
Author

LiadOz commented Aug 28, 2023

@HiPhish works for me, thanks!

@HiPhish HiPhish closed this as completed Sep 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants