iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0

在 day17 我們示範了插件的 Hello World 。顯然複雜一點的插件不會是只有單一的檔案,此外,我們也會希望插件是可以安裝的,所以這篇就要來示範標準插件的作法。

插件開發

前置準備

  • 首先要確定 nfnl 插件已經安裝在 Neovim 裡了。

  • 建立專案資料夾,並且切換資料夾。

$ mkdir my-plugin
$ cd my-plugin
  • 在專案目錄下準備 nfnl 的設置檔。

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
  • 將插件發布到你的 GitHub。

安裝

  • 在你的 init.vim 檔中,將你的插件加入到 Plug 區塊:
call plug#begin(stdpath('data') . '/plugged')
Plug '$username/my-plugin'
call plug#end()

將 $username 替換成你的 Github 使用者名稱。

  • 在 Neovim 的 Normal Mode 裡,執行以下的指令:
:source %
:PlugInstall
  • 在 init.vim 檔的 Plug 區塊之下,再加入一行:
lua require("my-plugin").setup()

這一行是用於對插件做初始化。

  • 重啟 Neovim 之後,你就可以在 Neovim 裡使用定義好的 :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'
...
  • 修正路徑問題,下一個 Ex 指令:
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 插件開發、如何安裝、模組的引用,還有開發過程之中,常常會遇到的路徑問題。


上一篇
Neovim 插件開發—Hello World
下一篇
Neovim 插件開發—如何除錯?
系列文
在 Neovim 中探索 Fennel 與函數式編程19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言