22import functools
33import os
44
5+ from traceback import format_exc , format_stack
6+
57from msgpack import ExtType
68
79from .buffer import Buffer
@@ -204,9 +206,9 @@ def out_write(self, msg):
204206 """Print `msg` as a normal message."""
205207 return self ._session .request ('vim_out_write' , msg )
206208
207- def err_write (self , msg ):
209+ def err_write (self , msg , async = False ):
208210 """Print `msg` as an error message."""
209- return self ._session .request ('vim_err_write' , msg )
211+ return self ._session .request ('vim_err_write' , msg , async = async )
210212
211213 def quit (self , quit_command = 'qa!' ):
212214 """Send a quit command to Nvim.
@@ -226,6 +228,29 @@ def new_highlight_source(self):
226228 """Return new src_id for use with Buffer.add_highlight."""
227229 return self .current .buffer .add_highlight ("" , 0 , src_id = 0 )
228230
231+ def async_call (self , fn , * args , ** kwargs ):
232+ """Schedule `fn` to be called by the event loop soon.
233+
234+ This function is thread-safe, and is the only way code not
235+ on the main thread could interact with nvim api objects.
236+
237+ This function can also be called in a synchronous
238+ event handler, just before it returns, to defer execution
239+ that shouldn't block neovim.
240+ """
241+ call_point = '' .join (format_stack (None , 5 )[:- 1 ])
242+
243+ def handler ():
244+ try :
245+ fn (* args , ** kwargs )
246+ except Exception as err :
247+ msg = ("error caught while executing async callback:\n "
248+ "{!r}\n {}\n \n the call was requested at\n {}"
249+ .format (err , format_exc (5 ), call_point ))
250+ self .err_write (msg , async = True )
251+ raise
252+ self ._session .threadsafe_call (handler )
253+
229254
230255class Current (object ):
231256
0 commit comments