Neovim supports Python 3 plugins by placing Python files or packages in the rplugin/python3/ directory within a folder in your runtimepath.
To define a plugin, create a class decorated with @pynvim.plugin. The class must accept an nvim instance in its __init__ method. You can then expose functionality using decorators:
@pynvim.function('Name', sync=True): Defines a function callable from Neovim. Use sync=True if the function needs to return a value.@pynvim.command('Name', nargs='*', range=''): Defines a new Neovim command.@pynvim.autocmd('Event', pattern='...', eval='...', sync=True): Defines an autocommand handler.
Important Lifecycle Rules:
- Lazy Initialization: Plugin objects are instantiated only when a request is first made. Do not perform non-trivial side effects or call API methods in the global module scope, as this code runs during
:UpdateRemotePlugins. - Initialization: Initialize your plugin logic inside
__init__ or when a specific command/autocommand is triggered. - Synchronicity: By default, handlers are asynchronous (
sync=False). If a handler is synchronous, other async handlers are blocked to prevent request confusion. To allow an async handler to run even while others are running, use @pynvim.autocmd(..., allow_nested=True) and ensure the handler only makes asynchronous requests (async_=True).
import pynvim
@pynvim.plugin
class TestPlugin(object):
def __init__(self, nvim):
self.nvim = nvim
@pynvim.function('TestFunction', sync=True)
def testfunction(self, args):
return 3
@pynvim.command('TestCommand', nargs='*', range='')
def testcommand(self, args, range):
self.nvim.current.line = ('Command with args: {}, range: {}'
.format(args, range))
@pynvim.autocmd('BufEnter', pattern='*.py', eval='expand("<afile>")', sync=True)
def on_bufenter(self, filename):
self.nvim.api.echo([['testplugin is in ' + filename]], True, {})