在 day17 我們示範了插件的 Hello World 。顯然複雜一點的插件不會是只有單一的檔案,此外,我們也會希望插件是可以安裝的,所以這篇就要來示範標準插件的作法。
首先要確定 nfnl 插件已經安裝在 Neovim 裡了。
建立專案資料夾,並且切換資料夾。
$ mkdir my-plugin
$ cd my-plugin
echo "{}" > .nfnl.fnl
有了這個設置檔之後,nfnl 的自動編譯功能就可以啟用。詳細說明可參考 nfnl 的 README。
mkdir -p lua/my-plugin fnl/my-plugin
fnl/my-plugin/init.fnl
,檔案內容如下:(fn hi []
(print "Hi World Fennel!"))
(fn setup []
(vim.api.nvim_create_user_command
:HiFennel
hi
{}))
;; 將 setup 函式對外匯出,讓 init.vim 可以呼叫
{: setup}
存檔之後,lua/my-plugin/init.lua
就會自動產生。
如果下 tree 指令的話,應該可以看到:
~$ tree -a
.
├── .nfnl.fnl
├── fnl
│ └── my-plugin
│ └── init.fnl
└── lua
└── my-plugin
└── init.lua
.nfnl.fnl
fnl/my-plugin/init.fnl
lua/my-plugin/init.lua
call plug#begin(stdpath('data') . '/plugged')
Plug '$username/my-plugin'
call plug#end()
將 $username 替換成你的 Github 使用者名稱。
:source %
:PlugInstall
lua require("my-plugin").setup()
這一行是用於對插件做初始化。
:HiFennel
命令了。很多時候,插件裡會分成多幾個模組。這時,要怎麼處理模組的引用呢?
fnl/my-plugin/util.fnl
,檔案內容如下:(fn inc [x]
(+ 1 x))
{: inc}
這邊建立了一個 util 模組,並且它有一個公開的函數叫 inc
。
fnl/my-plugin/init.fnl
,檔案內容如下:(local util (require :my-plugin.util))
(util.inc 15)
(fn hi []
(print "Hi World Fennel!"))
(fn setup []
(vim.api.nvim_create_user_command :HiFennel hi {}))
;; 將 setup 函式對外匯出,讓 init.vim 可以呼叫
{: setup}
在最上方的兩行,引用了 util
模組,並且呼叫了 util.inc
。
我們用 <localleader>ee
去對第一行 (local util (require :my-plugin.util))
求值,結果會得到類似如下的錯誤
; eval (current-form): (local util (require :my-plugi...
; [Runtime] [string "local util = require("my-plugin.util")..."]:1: module 'my-plugin.util' not found:
; no field package.preload['my-plugin.util']
; no file './my-plugin/util.lua'
; no file '/opt/homebrew/share/luajit-2.1/my-plugin/util.lua'
; no file '/usr/local/share/lua/5.1/my-plugin/util.lua'
...
package.path = vim.fn.getcwd() .. "/lua/?.lua;" .. package.path
修正路徑之後,再重新對第一行做 <localleader>ee
就可以順利運作了。
這個錯誤發生是因為Neovim 的 Lua 搜尋路徑 package.path
並不包含你當前專案目錄下的 lua 資料夾。所以,當 require 嘗試載入 my-plugin.util 模組時,它無法在預設的路徑中找到對應的 lua/my-plugin/util.lua
檔案,因此拋出了 module 'my-plugin.util' not found 的錯誤。
package.path = vim.fn.getcwd() .. "/lua/?.lua;" .. package.path
這個指令執行之後,這行指令會將當前工作目錄下的 lua 資料夾,也加入到 Lua 搜尋路徑中。這樣一來,require 就能正確找到並載入 my-plugin.util 這個模組了。
我們也可以把這個修改 Lua 搜尋路徑的部分,透過 Directory local Neovim configuration in Fennel 的方式,直接加到這個專案裡,日後就不用手動下指令調整路徑。此外,當這個 Neovim 插件安裝之後,由於插件的目錄會自動納入 Neovim 的 runtimepath 裡,也不會有這個路徑問題了。
本篇介紹了標準的 Neovim 插件開發、如何安裝、模組的引用,還有開發過程之中,常常會遇到的路徑問題。