1919
2020os_chdir = os .chdir
2121
22+ lua_module = """
23+ local a = vim.api
24+ local function update_highlights(buf, src_id, hls, clear_first, clear_end)
25+ if clear_first ~= nil then
26+ a.nvim_buf_clear_highlight(buf, src_id, clear_first, clear_end)
27+ end
28+ for _,hl in pairs(hls) do
29+ local group, line, col_start, col_end = unpack(hl)
30+ if col_start == nil then
31+ col_start = 0
32+ end
33+ if col_end == nil then
34+ col_end = -1
35+ end
36+ a.nvim_buf_add_highlight(buf, src_id, group, line, col_start, col_end)
37+ end
38+ end
39+
40+ local chid = ...
41+ local mod = {update_highlights=update_highlights}
42+ _G["_pynvim_"..chid] = mod
43+ """
44+
2245
2346class Nvim (object ):
2447
@@ -92,6 +115,7 @@ def __init__(self, session, channel_id, metadata, types,
92115 self .current = Current (self )
93116 self .session = CompatibilitySession (self )
94117 self .funcs = Funcs (self )
118+ self .lua = LuaFuncs (self )
95119 self .error = NvimError
96120 self ._decode = decode
97121 self ._err_cb = err_cb
@@ -115,6 +139,12 @@ def _to_nvim(self, obj):
115139 return ExtType (* obj .code_data )
116140 return obj
117141
142+ def _get_lua_private (self ):
143+ if not getattr (self ._session , "_has_lua" , False ):
144+ self .exec_lua (lua_module , self .channel_id )
145+ self ._session ._has_lua = True
146+ return getattr (self .lua , "_pynvim_{}" .format (self .channel_id ))
147+
118148 def request (self , name , * args , ** kwargs ):
119149 r"""Send an API request or notification to nvim.
120150
@@ -253,6 +283,27 @@ def call(self, name, *args, **kwargs):
253283 """Call a vimscript function."""
254284 return self .request ('nvim_call_function' , name , args , ** kwargs )
255285
286+ def exec_lua (self , code , * args , ** kwargs ):
287+ """Execute lua code.
288+
289+ Additional parameters are available as `...` inside the lua chunk.
290+ Only statements are executed. To evaluate an expression, prefix it
291+ with `return`: `return my_function(...)`
292+
293+ There is a shorthand syntax to call lua functions with arguments:
294+
295+ nvim.lua.func(1,2)
296+ nvim.lua.mymod.myfunction(data, async_=True)
297+
298+ is equivalent to
299+
300+ nvim.exec_lua("return func(...)", 1, 2)
301+ nvim.exec_lua("mymod.myfunction(...)", data, async_=True)
302+
303+ Note that with `async_=True` there is no return value.
304+ """
305+ return self .request ('nvim_execute_lua' , code , args , ** kwargs )
306+
256307 def strwidth (self , string ):
257308 """Return the number of display cells `string` occupies.
258309
@@ -467,5 +518,29 @@ def __getattr__(self, name):
467518 return partial (self ._nvim .call , name )
468519
469520
521+ class LuaFuncs (object ):
522+
523+ """Wrapper to allow lua functions to be called like python methods."""
524+
525+ def __init__ (self , nvim , name = "" ):
526+ self ._nvim = nvim
527+ self .name = name
528+
529+ def __getattr__ (self , name ):
530+ """Return wrapper to named api method."""
531+ prefix = self .name + "." if self .name else ""
532+ return LuaFuncs (self ._nvim , prefix + name )
533+
534+ def __call__ (self , * args , ** kwargs ):
535+ # first new function after keyword rename, be a bit noisy
536+ if 'async' in kwargs :
537+ raise ValueError ('"async" argument is not allowed. '
538+ 'Use "async_" instead.' )
539+ async_ = kwargs .get ('async_' , False )
540+ pattern = "return {}(...)" if not async_ else "{}(...)"
541+ code = pattern .format (self .name )
542+ return self ._nvim .exec_lua (code , * args , ** kwargs )
543+
544+
470545class NvimError (Exception ):
471546 pass
0 commit comments