neovim / pynvim

Python client and plugin host for Nvim
http://pynvim.readthedocs.io/en/latest/
Apache License 2.0
1.53k stars 119 forks source link

non-blocking next_message (peek_message) #214

Open bfredl opened 8 years ago

justinmk commented 8 years ago

Peek usually doesn't pop. Perhaps try_next_message ?

bfredl commented 8 years ago

Peek is the most general API, as try_next_message (next_message(block=False) ?) could be implemented as

if nvim.peek_message():
    msg = nvim.next_message()
    # do stuff with msg

but of course we can have both.

raghur commented 7 years ago

Chiming in for a me too:). I'm trying to implement a plugin for GhostText and basically need two workers that both need to be on the main thread since they call nvim apis. I don't have a good understanding of the underlying libuv event loop - but as of now, I'm running into all sorts of problems because nvim.next_message() blocks. I've tried python threads and gevent greenlets but basically pulling my hair out now :)

An alternative may be to provide a nvim.next_message(timeout) - and looks like it was there earlier but removed (see Issue 12).

For my case, I even tried to implement the approach alluded to there by having a timer job post a notification so that next_message gets unblocked - but even that is flaky at best.

It would also help a lot to have some documentation on dos and donts of usage - esp for folks who don't fully grok the libuv event loop.

bfredl commented 7 years ago

The most scalable way to integrate multiple event sources and yieldable workers is to use the event loop nvim.run_loop(request_cb, notification_cb, setup_cb) and not nvim.next_message. It implements a gevent-like interface, also using greenlets. But I agree it is poorly documented.

raghur commented 7 years ago

@bfredl thanks.. can you point me to some more documentation/details on how to use nvim.run_loop?

raghur commented 7 years ago

So I tried to nvim.run_loop with gevent greenlets and hasn't worked out well. It's most likely my poor understanding of the nvim.run_loop - but could it be that mixing Gevent greenlets with the run_loop greenlets is causing problems? One thing I do know is that Gevent has it's own event loop - the hub - but this would mean that the greenlets in nvim.run_loop are unaware of this?

Just looking for somsalksjfe advice on how to use the python client. Is it better to just use threads while working with the python client? (I need to start a http server and on each request from the browser, start a websocket server. When a message arrives at the websocket channel, I need to open a buffer in nvim and whenever the buffer is modified, push back the modified text to the websocket channel.

Thanks for reading.

bfredl commented 7 years ago

Literally mixing with gevent code will likely never work, what I meant is that it implements a gevent-like abstraction: you typically don't need to suspend and resume greenlets yourself, rather, when you do nvim.some_blocking_method() inside a event handler (or even setub_cb), nvim will suspend the greenlet and potentially let other event handlers run, or even a callback scheduled by another thread using nvim.async_call(callable, args) (which is the only thread-safe function)

raghur commented 7 years ago

Got it. By the way, can I start multiple nvim.run_loop - one per thread?

bfredl commented 7 years ago

I think you can, but you must have then created different nvim objects by multiple neovim.attach calls, and then always use the correct nvim instance in each loop.