pynvim Documentation

repository·master·Indexed 23 days ago

https://github.com/neovim/pynvim

A Python client for Neovim that allows developers to write remote and traditional Python-based plugins and interact with Neovim processes via its msgpack-rpc API. It provides interfaces for buffer and window manipulation, plugin registration via decorators (@plugin, @command, @autocmd, @function), and the ability to embed Neovim into Python applications or connect to running instances via sockets.

Tokens
4.9K
Snippets
15
Records
35
Agent score
82%

What's inside pynvim

  1. Understand the Python Plugin API

    master

    Pynvim provides two ways to write plugins:

    1. Remote Plugins: Uses the language-agnostic rplugin interface. These can handle vimL function calls, define commands and autocommands, and operate asynchronously without blocking Neovim.
    2. Vim Plugins: Uses the :python3 interface.

    When pynvim is installed, Neovim will report support for the +python3 Vim feature.

    Key API Extensions:

    • nvim.funcs: Access builtin and plugin vimL functions.
    • vim.api: Access API functions (also available on objects like buffer.api).
    • vim.exec_lua: Define Lua functions.
    • vim.lua: Call Lua functions.
    • Supports thread-safety and async requests.
  2. Install pynvim

    master

    Pynvim supports Python 3.10 or later. You can install it using uv (recommended) or pipx to ensure it is managed in an isolated environment.

    Using uv (Recommended):

    uv tool install --upgrade pynvim

    Note: Re-run this command whenever you upgrade Neovim to ensure compatibility.

    Using pipx:

    pipx install pynvim

    To upgrade:

    pipx upgrade pynvim
    uv tool install --upgrade pynvim
  3. Use plugin decorators to register Neovim components

    master

    The pynvim.plugin module provides decorators to simplify the registration of Neovim plugin components from Python. Instead of manually calling registration methods, you can use these decorators to define and register your plugin logic directly.

    Available decorators:

    • @plugin: Marks a class or function as a Neovim plugin.
    • @command: Registers a new Neovim command.
    • @autocmd: Registers an autocommand (autocmd).
    • @function: Registers a function that can be called from Neovim (e.g., via :call).
  4. Install pynvim from source

    master

    To install pynvim from the local repository, clone the repo and use your preferred installation method, replacing the package name with ..

    1. Clone the repository:

      git clone https://github.com/neovim/pynvim.git
      cd pynvim
    2. Install:

      • Using uv:
        uv tool install --upgrade .
      • Using pipx:
        pipx install --upgrade .
      • Using a manual virtual environment:
        • Create pynvim-venv as described in the manual installation guide.
        • Unix: pynvim-venv/bin/python -m pip install --upgrade .
        • Windows: pynvim-venv\Scripts\python -m pip install --upgrade .
        • Copy the pynvim-python executable to a directory on your PATH.
    git clone https://github.com/neovim/pynvim.git
    cd pynvim
  5. Define Remote (new-style) Python 3 Plugins

    master

    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, {})
  6. Install pynvim for development

    master

    If you are modifying the pynvim source code, you must reinstall the package for changes to take effect:

    pip3 install .

    Alternatively, you can set the PYTHONPATH environment variable to point to your local source directory before running Neovim:

    PYTHONPATH=/path/to/pynvim nvim

    Note: Using PYTHONPATH is not completely reliable as installed packages may take precedence in the Python search path.

    pip3 install .
  7. Run pynvim tests

    master

    To run the test suite, use pytest. This runs tests in an embedded instance of Neovim.

    Standard test execution:

    python -m pytest

    To test a specific Neovim binary instead of the one in your $PATH, use the NVIM_CHILD_ARGV environment variable:

    NVIM_CHILD_ARGV='["/path/to/nvim", "--clean", "--embed", "--headless"]' pytest

    To inspect the state of Neovim while running tests, you can start Neovim in a separate terminal and point the tests to it:

    export NVIM=/tmp/nvimtest
    xterm -e "nvim --listen $NVIM -u NONE" &
    python -m pytest

    Note: You must restart Neovim every time you run the tests when using this method.

    python -m pytest
  8. Develop Remote Plugins Locally

    master

    To develop a plugin locally without installing it into your global Neovim configuration, you can use an isolated vimrc that appends your current directory to the runtimepath.

    1. Create a vimrc file in your plugin directory:
    cat vimrc <<EOF
    let &runtimepath.=','.escape(expand('<sfile>:p:h'), '\\', ',')
    EOF
    1. Launch Neovim using that configuration:
    nvim -u ./vimrc
    1. Run :UpdateRemotePlugins inside Neovim to activate your plugin.
  9. Integrate with Lua using `vim.exec_lua`

    master

    Python plugins can define and invoke Lua code within Neovim's in-process Lua interpreter. This is useful for offloading complex operations to Lua to avoid interleaving user input with multiple API calls.

    Pattern 1: Defining a module via string

    You can use vim.exec_lua(code) to define a Lua table (module) containing functions. This module is then accessible in Python via vim.lua.<module_name>.

    Pattern 2: Loading from a file

    Place your Lua code in /lua/your_plugin.lua within your plugin directory and load it using vim.exec_lua("_your_plugin = require('your_plugin')").

    Passing arguments

    You can pass arguments to a Lua code block using vim.exec_lua(code, args...). Inside the Lua block, these arguments are accessible via the ... syntax.

  10. Install pynvim in a manual Python virtual environment

    master

    If you prefer not to use uv or pipx, you can manually create a virtual environment. After installation, you must ensure the pynvim-python executable is accessible on your PATH.

    1. Create the environment:

      python3 -m venv pynvim-venv
    2. Install pynvim:

      • Unix:
        pynvim-venv/bin/python -m pip install --upgrade pynvim
      • Windows:
        pynvim-venv\Scripts\python -m pip install --upgrade pynvim
    3. Expose the executable to PATH:

      • Unix (assuming ~/.local/bin is on PATH):
        cp pynvim-venv/bin/pynvim-python ~/.local/bin/pynvim-python
      • Windows (assuming C:\apps is on PATH):
        copy pynvim-venv\Scripts\pynvim-python.exe C:\apps\pynvim-python.exe
    python3 -m venv pynvim-venv
  11. Install pynvim using uv or pipx

    master

    The recommended way to install pynvim for automatic detection by Neovim is to use a tool like uv or pipx. This installs pynvim into a dedicated virtual environment and places the pynvim-python executable on your PATH.

    Requirements:

    • Python 3.7 or later.

    Installation Commands:

    Using uv (recommended):

    uv tool install --upgrade pynvim

    Using pipx:

    pipx install --upgrade pynvim
    uv tool install --upgrade pynvim