在 vim 中 viml 是第一公民,很多插件都是使用 viml 進行開發(fā)的,而在 neovim 中,lua 成為了主要的腳本語言,幾乎現(xiàn)在 95%以上的 neovim 都是采用 lua 進行開發(fā)的。
插件目錄結構
開發(fā)一款插件,我們首先要明確插件的目錄結構,雖然這個結構不是必須固定的,但是遵守一定的規(guī)則可以讓我們的插件變得更容易被修改,更容易進行擴展。
插件目錄一般為一個 plugin 文件夾放入我們的主文件,lua 文件夾放入代碼庫。
浮動窗口
在 neovim 中,增加了浮動窗口的功能,這樣我們顯示一些信息非常的方便,我們可以使用 neovim 提供的關于浮動窗口的 api 進行插件的編寫。
編寫插件的時候,我們一般都會首先定義一些變量,這樣方便我們后續(xù)的使用。定義好變量之后,我們接下來會根據(jù)需求定義我們的函數(shù),一般情況下都是一個功能定義一個函數(shù),每個函數(shù)完成一個指定的功能。

此外,需要注意的一點就是,一般插件都是會有一些默認配置的,我們可以定義一些配置默認值,這樣用戶可以在零配置的情況下就使用我們的插件。
簡單的代碼如下:
local api = vim.apilocal buf, win
local function open_window() buf = api.nvim_create_buf(false, true) -- create new emtpy buffer
api.nvim_buf_set_option(buf, 'bufhidden', 'wipe')
-- get dimensions local width = api.nvim_get_option("columns") local height = api.nvim_get_option("lines")
-- calculate our floating window size local win_height = math.ceil(height * 0.8 - 4) local win_width = math.ceil(width * 0.8)
-- and its starting position local row = math.ceil((height - win_height) / 2 - 1) local col = math.ceil((width - win_width) / 2)
-- set some options local opts = { style = "minimal", relative = "editor", width = win_width, height = win_height, row = row, col = col }
-- and finally create it with buffer attached win = api.nvim_open_win(buf, true, opts)end
視圖更新
幾乎所有的插件最后都要更新渲染視圖,我們可以根據(jù)指定的內容進行視圖的更新,一般都是根據(jù)執(zhí)行的一些命令結果來更新視圖,在 neovim 中,可以通過vim.fn.systemlist函數(shù)獲取命令執(zhí)行結果,然后通過函數(shù)api.nvim_buf_set_lines將結果渲染到視圖上。
local function update_view()
-- we will use vim systemlist function which run shell
-- command and return result as list
local result = vim.fn.systemlist('git diff-tree --no-commit-id --name-only -r HEAD')
-- with small indentation results will look better
for k,v in pairs(result) do
result[k] = ' '..result[k]
end
api.nvim_buf_set_lines(buf, 0, -1, false, result)
end
插件交互
很多時候我們的插件是需要和用戶進行交互的,也就是用戶輸入一些命令之后,我們要能夠響應用戶的輸入,然后來調整我們插件的輸出。

在 neovim 中,我們可以通過api.nvim_buf_set_keymap來進行輸入按鍵的功能綁定。
函數(shù)導出
最后,我們可以將我們的插件中的函數(shù)進行導出,也就是讓它們可以被執(zhí)行。最后再在主函數(shù)中調用它們即可,這樣我們的插件就編寫完成了。
local function my_plugin()
position = 0 -- if you want to preserve last displayed state just omit this line
open_window()
set_mappings()
update_view(0)
api.nvim_win_set_cursor(win, {4, 0}) -- set cursor on first list entry
end
return {
my_plugin = my_plugin,
update_view = update_view,
open_file = open_file,
move_cursor = move_cursor,
close_window = close_window
}