Neovim plugin in Python
The Vimwiki plugin is quite useful, but I only use a small subset of its features, primarily the daily notes and checking off of todo lists. See my Vimwiki page in my Working with Vim guide.
However, the daily notes don't organize how I want them to, I want to store them
in YYYY/MM/note.md
. The plugin has limited customization so I figured I could
write my own plugin. I call it Neojot.
Initially I started writing the plugin in Lua, which I don't know at all. Plus looks like no batteries are included with Lua, the standard library is thin. Anorexic.
So why not Python.
The documentation for writing a Neovim plugin in Python is a bit limited, but once the plugin is stubbed out, relatively straight forward to follow the rest of the Neovim API documentation.
So here is what I figured out on how to stub out a plugin, hopefully it gets you further faster.
Directory Structure
I used the remote plugin interface and pynvim client using the following directory structure.
In the lua
directory, I created a plugin file neojot.lua
that creates my
keybindings, and creates a hook for Python to grab the setup config.
In the rplugin/python3
directory, I created a Python file neojot.py
that
creates the individual functions that does all the voodoo.
Example Plugin
Here is a minimal example plugin with this structure. The example maps
<Leader>i
to a function in the Python code that echoes a configuration value
to the command line in Vim.
In example_plugin/lua/example_plugin.lua
local config = {}
local function setup(cfg)
config = cfg
-- add keymaps here
vim.keymap.set('n', '<Leader>i', ':call ExPlugEcho()<CR>', { silent = true })
end
-- Used in Python to get config
local function getConfig()
return config
end
return { setup=setup, getConfig=getConfig }
In example_plugin/rplugin/python3/example_plugin.py
import pynvim
@pynvim.plugin
class ExPlugin(object):
def __init__(self, nvim):
self.nvim = nvim
self.cfg = nvim.exec_lua('return require("example_plugin").getConfig()')
@pynvim.function("ExPlugEcho", sync=True)
def echo(self, args):
self.nvim.command(f"echomsg 'From config: {self.cfg['path']}'")
That is all that is needed for plugin code.
Install plugin using vim-plug
to refer to directory ~/src/example_plugin
location.
Config plugin using:
require("example_plugin").setup({
path = "/home/mkaz/Documents",
})
Relaunch Neovim and run :UpdateRemotePlugin
Open a buffer and type <Leader>i
to see message.
Development Tips
While developing, when updating the Python files Neovim needs to be quit and restarted to have the changes take effect.
Run :UpdateRemotePlugin
when making changes to Lua file that loads keymaps.
See my Neojot repo for the plugin I built. The plugin is rather basic but shows a few features and commands.
Read the Neovim API documentation to figure out what can be done.
The Pynvim documentation is barely useful.