Python Plugin API¶
Neovim has a new mechanism for defining plugins,
as well as a number of extensions to the python API.
The API extensions are accessible no matter if the traditional :python
interface or the new mechanism is used,
as discussed on Remote (new-style) plugins.
Nvim API methods: vim.api
¶
Exposes Neovim API methods.
For instance to call nvim_strwidth
:
result = vim.api.strwidth("some text")
Note the initial nvim_
is not included.
Also, object methods can be called directly on their object:
buf = vim.current.buffer
length = buf.api.line_count()
calls nvim_buf_line_count
.
Alternatively msgpack requests can be invoked directly:
result = vim.request("nvim_strwith", "some text")
length = vim.request("nvim_buf_line_count", buf)
Both vim.api
and vim.request
can take an async_=True
keyword argument
to instead send a msgpack notification. Nvim will execute the API method the
same way, but python will not wait for it to finish, so the return value is
unavailable.
Vimscript functions: vim.funcs
¶
Exposes vimscript functions (both builtin and global user defined functions) as a python namespace. For instance to set the value of a register:
vim.funcs.setreg('0', ["some", "text"], 'l')
These functions can also take the async_=True
keyword argument, just like API
methods.
Lua integration¶
Python plugins can define and invoke lua code in Nvim’s in-process lua interpreter. This is especially useful in asynchronous contexts, where an async event handler can schedule a complex operation with many api calls to be executed by nvim without interleaved processing of user input or other event sources (unless requested).
The recommended usage is the following pattern. First use vim.exec_lua(code)
to define a module with lua functions:
vim.exec_lua("""
local a = vim.api
local function add(a,b)
return a+b
end
local function buffer_ticks()
local ticks = {}
for _, buf in ipairs(a.nvim_list_bufs()) do
ticks[#ticks+1] = a.nvim_buf_get_changedtick(buf)
end
return ticks
end
_testplugin = {add=add, buffer_ticks=buffer_ticks}
""")
Alternatively, place the code in /lua/testplugin.lua
under your plugin repo
root, and use vim.exec_lua("_testplugin = require('testplugin')")
.
In both cases, replace testplugin
with a unique string based on your plugin
name.
Then, the module can be accessed as vim.lua._testplugin
.
mod = vim.lua._testplugin
mod.add(2,3) # => 5
mod.buffer_ticks() # => list of ticks
These functions can also take the async_=True
keyword argument, just like API
methods.
It is also possible to pass arguments directly to a code block. Using
vim.exec_lua(code, args...)
, the arguments will be available in lua as ...
.
Async calls¶
The API is not thread-safe in general.
However, vim.async_call
allows a spawned thread to schedule code to be executed on the main thread.
This method could also be called from :python
or a synchronous request handler,
to defer some execution that shouldn’t block Neovim:
:python vim.async_call(myfunc, args...)
Note that this code will still block the plugin host if it does long-running computations.
Intensive computations should be done in a separate thread (or process),
and vim.async_call
can be used to send results back to Neovim.
Some methods accept an async_
keyword argument: vim.eval
,
vim.command
, vim.request
as well as the vim.funcs
, vim.api` and
``vim.lua`
wrappers. When async_=True
is passed the client will not wait
for Neovim to complete the request (which also means that the return value is
unavailable).