context.vim icon indicating copy to clipboard operation
context.vim copied to clipboard

Unneeded (?) resettings of virtualedit/conceallevel may make context#util#update_state() extremely slow

Open lyokha opened this issue 2 years ago • 0 comments

I found that moving cursor in Normal mode is painfully slow in my auto-generated TeX files with long wrapped lines because of CursorMoved autocmd from the context plugin. My first attempt was to disable tex files using g:context_filetype_blacklist, but this did not help as this won't delete the context's augroup.

After some digging I found that the bottleneck was resetting virtualedit/conceallevel every time the cursor moves in Normal mode. It seems that switching these resettings off completely won't change correctness of the context behaviour: I checked this with all combinations of virtualedit, conceallevel, concealcursor, setting nunber/nonumber, adding marks on the sign column, etc. On the other hand, moving the cursor around got very fast and easy.

Here is my diff:

diff --git a/autoload/context/util.vim b/autoload/context/util.vim
index 5b6db1b..1b29124 100644
--- a/autoload/context/util.vim
+++ b/autoload/context/util.vim
@@ -113,12 +113,12 @@ function! context#util#update_state() abort
 
     " NOTE: we need to save and restore the cursor position because setting
     " 'virtualedit' resets curswant #84
-    let cursor = getcurpos()
-    let old = [&virtualedit, &conceallevel]
-    let [&virtualedit, &conceallevel] = ['all', 0]
+    "let cursor = getcurpos()
+    "let old = [&virtualedit, &conceallevel]
+    "let [&virtualedit, &conceallevel] = ['all', 0]
     let sign_width = wincol() - virtcol('.') - number_width
-    let [&virtualedit, &conceallevel] = old
-    call setpos('.', cursor)
+    "let [&virtualedit, &conceallevel] = old
+    "call setpos('.', cursor)
 
     " NOTE: sign_width can be negative if the cursor is on the wrapped part of
     " a wrapped line. in that case ignore the value

Probably, my Neovim 0.5 behaves differently than Vim. Or maybe I do not know some special scenarios when switching these settings is important, but I feel that virtualedit should not affect correctness of wincol() and virtcol(), while :help virtcol() says that it also ignores conceallevel (and it seems that wincol() does as well).

Historically, I tried to fix horizontal cursor motions by detecting this in context#update() and skipping the call to context#util#update_state(), here is the diff:

diff --git a/autoload/context.vim b/autoload/context.vim
index 9fcf894..0905db3 100644
--- a/autoload/context.vim
+++ b/autoload/context.vim
@@ -82,6 +82,17 @@ function! context#update(...) abort
                     \ }
     endif
 
+    " FIXME: does this always work as supposed?
+    " (at least, this has minor issues when unfolding text)
+    if source == 'CursorMoved' &&
+                \ (0
+                \     || !s:activated
+                \     || !context#util#active()
+                \     || w:context.cursor_line == line('.')
+                \ )
+        return
+    endif
+
     if 1
                 \ && w:context.peek
                 \ && source != 'CursorHold'

However, this is far not as important for the speed as the first hunk. And this has side effects when opening folds.

lyokha avatar Jul 27 '21 16:07 lyokha