-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Documentation request: best practices for creating parts with high latency #2496
Comments
Yeah, we have a differing goals here:
What some plugins usually do, is to only perform some work if a buffer-local variable has been set and otherwise use the cached result. That buffer-local variable is then reset on different autocommands, e.g. when saving the buffer. Check the branch extension or the wordcount extension. That should give some ideas. But in general, I agree, properly documenting would be good :) |
About question 2: I don't know. Would it be possible in python3 to start an extra python3 thread that way it shouldn't block vim I guess? But that sounds pretty complex architecture already :( |
I took at look at branch, wordcount, and then ultimately arrived at a best practice looking at vim-airline-clock. I spent several hours trying to use Python multithread, but kept running into segfaults. The single-threaded nature along with non-threadsafe code in vim core makes it impossible to use multithreading. Lesson learned: it's really important to understand to never do anything slow within vimscript or even embedded py3/lua/ruby. So, I ended up using a combination of To start, define a timer rig in function! s:timerfn(timer)
call my_plugin#DoSomethingExpensive()
endfunction
" you can set 5000 to &updatetime or a higher time depending on sensitivity of the expensive thing.
let g:airline#extensions#my_plugin#updatetime = get(g:, 'airline#extensions#my_plugin#updatetime', 5000)
let g:airline#extensions#my_plugin#timer = timer_start(
\ g:airline#extensions#my_plugin#updatetime,
\ funcref('<sid>timerfn'), {'repeat': -1})
autocmd User AirlineToggledOff call timer_pause(g:airline#extensions#my_plugin#timer, 1)
autocmd User AirlineToggledOn call timer_pause(g:airline#extensions#my_plugin#timer, 0) Then define the asynchronous interaction in let s:param4 = 0
let s:info = {}
function! my_plugin#InfoHandler(channel, msg)
let s:info = json_decode(a:msg)
" You could ask airline to refresh, but it slows things down when another event triggers refresh anyway.
" :AirlineRefresh
endfunction
function! my_plugin#DoSomethingExpensive()
" add any necessary checks to skip the slow op.
if s:param1 > 0
let s:job = job_start(['/path/to/binary', 'param1',
\ 'param2', 'param3', '--', s:param4], {"out_cb": "my_plugin#InfoHandler"})
endif
endfunction
" You can dynamically set parameters like this.
function! my_plugin#SetParam(value)
let s:param4 = a:value
endfunction |
One more note. I will try to add an afk-detect mechanism in this to stop the timer when a user is not using vim .. either in background tmux window or they're just not using terminal at the moment. Probably something like this: https://vi.stackexchange.com/questions/27180/does-vim-8-have-some-screensaver-like-mechanism |
Great stuff. I'll review and add something to the documentation then. |
This is a documentation request or at least a link to a vim-best practices doc for pseudo-asynchronous communication to populate a part from a high latency source. What follows is a description of my setup. Everything works great -- except
vim
slows for a bit while I am editing a file. I don't use neovim, just vim.Overall, I'm writing a part that takes 150ms to 200ms (or longer) to compute.
I chose the following design:
Split the logic into two different vim plugins that talk to each other through a
g:
level variable.Plugin 1 (foo)
airline#extensions#{name}#init(...)
API to define a part function and condition.g:
level variable populated with JSON data.code snippet:
Plugin 2 (bar)
vim.command
API.code snippet:
Observations
foo#GetBarFindings
gets invoked on every keystroke, in addition to other kinds of events like buffer change. Luckily, it's just looking up data in a global vim variable. But practicably speaking, I know it won't change for another 30 seconds .. even then, it'll probably remain the same .. since it's tracking a state change that happens on a server.py3
really gums things up when it takes 200ms.Alternatives considered
I had considered writing
Plugin 2 (bar)
as a shell script and then write the data to a file. However, I do aspire to make this plugin available to others via git (internal). So, I thought implementing it solely in vim would make distribution and install much easier.The text was updated successfully, but these errors were encountered: