Lua 指南

Nvim 的 :help 頁面,從 原始碼 使用 tree-sitter-vimdoc 解析器 產生


在 Nvim 中使用 Lua 的指南

簡介

本指南將介紹在 Nvim 中使用 Lua 的基礎知識。它並非旨在成為所有可用功能的綜合百科全書,也不會詳細介紹所有複雜之處。將其視為一個求生工具包——舒適地開始在 Nvim 中使用 Lua 所需的最基本知識。
需要注意的重要一點是,這不是 Lua 語言本身的指南。相反,這是一份關於如何通過 Lua 語言以及我們提供的輔助函式來配置和修改 Nvim 的指南。如果您想了解更多關於 Lua 本身的資訊,請查看 luareflua-concepts。同樣地,本指南假設您對 Nvim 的基礎知識(命令、選項、映射、自動命令)有一定的熟悉程度,這些內容在 使用者手冊 中有介紹。

關於 API 的一些說明 lua-guide-api

本指南的目的是介紹通過 Lua 與 Nvim 互動的不同方式(即「API」)。此 API 由三個不同的層級組成
1. 從 Vim 繼承的「Vim API」:Ex 命令內建函式,以及 Vimscript 中的 使用者函式。這些可以分別通過 vim.cmd()vim.fn 存取,這將在下面的 lua-guide-vimscript 中討論。
2. 用 C 語言編寫的「Nvim API」,用於遠程外掛程式和 GUI;請參閱 api。這些函式可以通過 vim.api 存取。
3. 用 Lua 編寫且專門用於 Lua 的「Lua API」。這些是通過 vim.* 存取的任何其他未提及的函式;請參閱 lua-stdlib
這種區別很重要,因為 API 函式繼承了其原始層級的行為:例如,即使 Lua 本身允許省略參數(然後將其作為 nil 傳遞),Nvim API 函式始終需要指定所有參數;而即使 Lua 陣列預設從 1 開始索引,Vim API 函式也可以使用從 0 開始的索引。
通過這種方式,任何可能的互動都可以通過 Lua 完成,而無需從頭開始編寫一個全新的 API。因此,除非在功能或效能方面有顯著的好處,否則通常不會在各層級之間重複函式(例如,您可以通過 nvim_create_autocmd() 直接映射 Lua 函式,但不能通過 :autocmd 映射)。如果有實現相同目標的多種方式,本指南僅介紹從 Lua 中使用最方便的方式。
要從 Nvim 命令列執行 Lua 程式碼,請使用 :lua 命令
:lua print("Hello!")
注意:每個 :lua 命令都有自己的作用域,並且使用 local 關鍵字宣告的變數無法在命令外部存取。這將不起作用
:lua local foo = 1
:lua print(foo)
" prints "nil" instead of "1"
您也可以使用 :lua=,它等效於 :lua vim.print(...),以方便地檢查變數或表格的值
:lua =package
若要在外部檔案中執行 Lua 腳本,您可以像對待 Vimscript 檔案一樣使用 :source 命令
:source ~/programs/baz/myluafile.lua
最後,您可以通過將 Lua 程式碼放在 :lua-heredoc 區塊中,將其包含在 Vimscript 檔案中
lua << EOF
  local tbl = {1, 2, 3}
  for k, v in ipairs(tbl) do
    print(v)
  end
EOF

在啟動時使用 Lua 檔案 lua-guide-config

Nvim 支援使用 init.viminit.lua 作為組態檔案,但不能同時使用兩者。這應放置在您的 組態 目錄中,該目錄在 Linux、BSD 或 macOS 中通常是 ~/.config/nvim,在 Windows 中是 ~/AppData/Local/nvim/。請注意,您可以在 init.vim 中使用 Lua,並在 init.lua 中使用 Vimscript,這將在下面介紹。
如果您想在 啟動 時自動執行任何其他 Lua 腳本,您可以將其放入 'runtimepath' 中的 plugin/ 中。
如果您想按需載入 Lua 檔案,您可以將其放置在 'runtimepath' 中的 lua/ 目錄中,並使用 require 載入。(這是 Lua 中等效於 Vimscript 的 autoload 機制。)
假設您有以下目錄結構
~/.config/nvim
|-- after/
|-- ftplugin/
|-- lua/
|   |-- myluamodule.lua
|   |-- other_modules/
|       |-- anothermodule.lua
|       |-- init.lua
|-- plugin/
|-- syntax/
|-- init.vim
那麼以下 Lua 程式碼將載入 myluamodule.lua
require("myluamodule")
請注意缺少 .lua 副檔名。
同樣地,載入 other_modules/anothermodule.lua 是通過以下方式完成的
require('other_modules/anothermodule')
-- or
require('other_modules.anothermodule')
請注意,「子模組」只是子目錄;. 等效於路徑分隔符 /(即使在 Windows 上也是如此)。
包含 init.lua 檔案的資料夾可以直接要求,而無需指定檔案的名稱
require('other_modules') -- loads other_modules/init.lua
要求不存在的模組或包含語法錯誤的模組會中止目前正在執行的腳本。可以使用 pcall() 來捕獲此類錯誤。以下範例嘗試載入 module_with_error,並且僅在成功時才呼叫其其中一個函式,否則會列印錯誤訊息
local ok, mymod = pcall(require, 'module_with_error')
if not ok then
  print("Module had an error")
else
  mymod.function()
end
:source 相反,require() 不僅會在 'runtimepath' 下的所有 lua/ 目錄中搜尋,還會在第一次使用時快取模組。因此,第二次呼叫 require() _不會_ 再次執行腳本,而是傳回快取的檔案。若要重新執行檔案,您需要先手動從快取中刪除它
package.loaded['myluamodule'] = nil
require('myluamodule')    -- read and execute the module again from disk

另請參閱

從 Lua 使用 Vim 命令和函式 lua-guide-vimscript

所有 Vim 命令和函式都可以從 Lua 存取。
若要從 Lua 執行任意 Vim 命令,請將其作為字串傳遞給 vim.cmd()
vim.cmd("colorscheme habamax")
請注意,特殊字元需要使用反斜線跳脫
vim.cmd("%s/\\Vfoo/bar/g")
另一種方法是使用以雙括號 [[ ]] 分隔的文字字串(請參閱 lua-literal),如下所示
vim.cmd([[%s/\Vfoo/bar/g]])
使用文字字串的另一個好處是它們可以有多行;這允許您將多個命令傳遞給單次呼叫 vim.cmd()
vim.cmd([[
  highlight Error guibg=red
  highlight link Warning Error
]])
這是 :lua-heredoc 的反向操作,允許您在 init.lua 中包含 Vimscript 程式碼。
如果您想以程式方式建構您的 Vim 命令,則以下形式可能會很有用(所有這些都等效於上面對應的行)
vim.cmd.colorscheme("habamax")
vim.cmd.highlight({ "Error", "guibg=red" })
vim.cmd.highlight({ "link", "Warning", "Error" })

Vimscript 函式 lua-guide-vim-functions

使用 vim.fn 從 Lua 呼叫 Vimscript 函式。Lua 和 Vimscript 之間的資料類型會自動轉換
print(vim.fn.printf('Hello from %s', 'Lua'))
local reversed_list = vim.fn.reverse({ 'a', 'b', 'c' })
vim.print(reversed_list) -- { "c", "b", "a" }
local function print_stdout(chan_id, data, name)
  print(data[1])
end
vim.fn.jobstart('ls', { on_stdout = print_stdout })
這適用於 內建函式使用者函式
請注意,雜湊符號 (#) 不是 Lua 中識別符號的有效字元,因此,例如,autoload 函式必須使用以下語法呼叫
vim.fn['my#autoload#function']()

另請參閱

內建函式:所有 Vimscript 函式的字母列表
函式列表:按主題分組的所有 Vimscript 函式列表
:runtime:在 'runtimepath' 中執行與模式比對的所有 Lua 腳本
package.pathrequire() 搜尋的所有路徑列表
可以使用以下包裝器設定和讀取變數,這些包裝器直接對應於它們的 變數作用域
vim.g:全域變數 (g:)
vim.b:目前緩衝區的變數 (b:)
vim.w:目前視窗的變數 (w:)
vim.t:目前標籤頁的變數 (t:)
vim.v:預定義的 Vim 變數 (v:)
vim.env:在編輯器會話中定義的環境變數
資料類型會自動轉換。例如
vim.g.some_global_variable = {
  key1 = "value",
  key2 = 300
}
vim.print(vim.g.some_global_variable)
--> { key1 = "value", key2 = 300 }
您可以通過索引包裝器來定位特定緩衝區(通過編號)、視窗(通過 視窗 ID)或標籤頁
vim.b[2].myvar = 1               -- set myvar for buffer number 2
vim.w[1005].myothervar = true    -- set myothervar for window ID 1005
某些變數名稱可能包含不能用於 Lua 中識別符號的字元。您仍然可以使用以下語法操作這些變數
vim.g['my#variable'] = 1
請注意,您不能直接變更陣列變數的欄位。這將不起作用
vim.g.some_global_variable.key2 = 400
vim.print(vim.g.some_global_variable)
--> { key1 = "value", key2 = 300 }
相反地,您需要建立一個中間的 Lua 表格並變更它
local temp_table = vim.g.some_global_variable
temp_table.key2 = 400
vim.g.some_global_variable = temp_table
vim.print(vim.g.some_global_variable)
--> { key1 = "value", key2 = 400 }
若要刪除變數,只需將其設定為 nil
vim.g.myvar = nil

另請參閱

通過 Lua 設定 選項 有兩種互補的方式。

vim.opt

init.lua 中設定全域和本機選項最方便的方式是通過 vim.opt 及其相關函式
vim.opt:行為類似於 :set
vim.opt_global:行為類似於 :setglobal
vim.opt_local:行為類似於 :setlocal
例如,Vimscript 命令
set smarttab
set nosmarttab
等效於
vim.opt.smarttab = true
vim.opt.smarttab = false
尤其是,它們允許通過 Lua 表格輕鬆處理類似列表、類似對應表和類似集合的選項:而不是
set wildignore=*.o,*.a,__pycache__
set listchars=space:_,tab:>~
set formatoptions=njt
您可以使用
vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }
vim.opt.listchars = { space = '_', tab = '>~' }
vim.opt.formatoptions = { n = true, j = true, t = true }
這些包裝器還帶有方法,其工作方式與 Vimscript 中對應的 :set+=:set^=:set-= 類似
vim.opt.shortmess:append({ I = true })
vim.opt.wildignore:prepend('*.o')
vim.opt.whichwrap:remove({ 'b', 's' })
需要付出的代價是您不能直接存取選項值,而必須使用 vim.opt:get()
print(vim.opt.smarttab)
--> {...} (big table)
print(vim.opt.smarttab:get())
--> false
vim.print(vim.opt.listchars:get())
--> { space = '_', tab = '>~' }

vim.o

因此,存在一種使用 vim.o 及其相關函式進行更直接的類似變數存取的方式,類似於您如何通過 :echo &number:let &listchars='space:_,tab:>~' 來取得和設定選項
vim.o:行為類似於 :set
vim.go:行為類似於 :setglobal
vim.bo:用於緩衝區範圍的選項
vim.wo:用於視窗範圍的選項(可以雙重索引)
例如
vim.o.smarttab = false -- :set nosmarttab
print(vim.o.smarttab)
--> false
vim.o.listchars = 'space:_,tab:>~' -- :set listchars='space:_,tab:>~'
print(vim.o.listchars)
--> 'space:_,tab:>~'
vim.o.isfname = vim.o.isfname .. ',@-@' -- :set isfname+=@-@
print(vim.o.isfname)
--> '@,48-57,/,.,-,_,+,,,#,$,%,~,=,@-@'
vim.bo.shiftwidth = 4 -- :setlocal shiftwidth=4
print(vim.bo.shiftwidth)
--> 4
就像變數一樣,您可以為緩衝區和視窗選項分別指定緩衝區編號或 視窗 ID。如果沒有指定編號,則會使用目前的緩衝區或視窗。
vim.bo[4].expandtab = true -- sets expandtab to true in buffer 4
vim.wo.number = true       -- sets number to true in current window
vim.wo[0].number = true    -- same as above
vim.wo[0][0].number = true -- sets number to true in current buffer
                           -- in current window only
print(vim.wo[0].number)    --> true

另請參閱

您可以將 Vim 命令或 Lua 函數映射到按鍵序列。
可以使用 vim.keymap.set() 來建立映射。此函數接受三個強制參數
{mode} 是一個字串或字串表格,其中包含映射生效的模式前綴。前綴是 :map-modes 中列出的那些,或是 ! 代表 :map!,或是空字串代表 :map
{lhs} 是一個字串,其中包含應觸發映射的按鍵序列。
{rhs} 可以是一個包含 Vim 命令的字串,或是當輸入 {lhs} 時應執行的 Lua 函數。空字串等同於 <Nop>,它會停用按鍵。
範例
-- Normal mode mapping for Vim command
vim.keymap.set('n', '<Leader>ex1', '<cmd>echo "Example 1"<cr>')
-- Normal and Command-line mode mapping for Vim command
vim.keymap.set({'n', 'c'}, '<Leader>ex2', '<cmd>echo "Example 2"<cr>')
-- Normal mode mapping for Lua function
vim.keymap.set('n', '<Leader>ex3', vim.treesitter.start)
-- Normal mode mapping for Lua function with arguments
vim.keymap.set('n', '<Leader>ex4', function() print('Example 4') end)
您可以透過以下方式映射 Lua 模組中的函數
vim.keymap.set('n', '<Leader>pl1', require('plugin').action)
請注意,這會在定義映射時載入外掛程式。如果您想將載入延遲到執行映射時(如同 autoload 函數),請將它包在 function() end 中。
vim.keymap.set('n', '<Leader>pl2', function() require('plugin').action() end)
第四個可選的參數是一個表格,其中包含修改映射行為的鍵,例如來自 :map-arguments 的那些。以下是最有用的選項
buffer:如果指定,則僅為具有指定編號的緩衝區設定映射;0true 表示目前的緩衝區。
-- set mapping for the current buffer
vim.keymap.set('n', '<Leader>pl1', require('plugin').action, { buffer = true })
-- set mapping for the buffer number 4
vim.keymap.set('n', '<Leader>pl1', require('plugin').action, { buffer = 4 })
silent:如果設定為 true,則會抑制輸出,例如錯誤訊息。
vim.keymap.set('n', '<Leader>pl1', require('plugin').action, { silent = true })
expr:如果設定為 true,則不會執行 {rhs},而是使用傳回值作為輸入。特殊的 按鍵代碼 會自動轉換。例如,以下映射僅在彈出式選單中將 <down> 替換為 <c-n>
vim.keymap.set('c', '<down>', function()
  if vim.fn.pumvisible() == 1 then return '<c-n>' end
  return '<down>'
end, { expr = true })
desc:一個字串,當使用例如 :map 列出映射時顯示。這很有用,因為 Lua 函數作為 {rhs} 否則只會列為 Lua: <number> <source file>:<line>。因此,外掛程式應該始終將此用於它們建立的映射。
vim.keymap.set('n', '<Leader>pl1', require('plugin').action,
  { desc = 'Execute action from plugin' })
remap:預設情況下,所有映射都是非遞迴的(即 vim.keymap.set() 的行為類似於 :noremap)。如果 {rhs} 本身是一個應執行的映射,請設定 remap = true
vim.keymap.set('n', '<Leader>ex1', '<cmd>echo "Example 1"<cr>')
-- add a shorter mapping
vim.keymap.set('n', 'e', '<Leader>ex1', { remap = true })
注意: 即使使用預設的 remap = false<Plug> 映射也始終會展開。
vim.keymap.set('n', '[%', '<Plug>(MatchitNormalMultiBackward)')
可以使用 vim.keymap.del() 來移除特定的映射。
vim.keymap.del('n', '<Leader>ex1')
vim.keymap.del({'n', 'c'}, '<Leader>ex2', {buffer = true})

另請參閱

vim.api.nvim_get_keymap():傳回所有全域映射
vim.api.nvim_buf_get_keymap():傳回緩衝區的所有映射
自動指令 是 Vim 命令或 Lua 函數,每當觸發一個或多個 事件 時會自動執行,例如,當讀取或寫入檔案時,或是當建立視窗時。這些可以透過 Nvim API 從 Lua 存取。

建立自動指令 lua-guide-autocommand-create

自動指令是使用 vim.api.nvim_create_autocmd() 建立的,它接受兩個強制參數
{event}:一個字串或字串表格,其中包含應觸發命令或函數的事件。
{opts}:一個表格,其中包含控制觸發事件時應發生情況的鍵。
最重要的選項是
pattern:一個字串或字串表格,其中包含 autocmd-pattern 注意: 像是 $HOME~ 的環境變數不會自動展開;您需要明確使用 vim.fn.expand() 來做到這一點。
command:一個包含 Vim 命令的字串。
callback:一個 Lua 函數。
您必須指定 commandcallback 其中一個,且只能指定一個。如果省略 pattern,則預設為 pattern = '*'。範例
vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
  pattern = {"*.c", "*.h"},
  command = "echo 'Entering a C or C++ file'",
})
-- Same autocommand written with a Lua function instead
vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
  pattern = {"*.c", "*.h"},
  callback = function() print("Entering a C or C++ file") end,
})
-- User event triggered by MyPlugin
vim.api.nvim_create_autocmd("User", {
  pattern = "MyPlugin",
  callback = function() print("My Plugin Works!") end,
})
Nvim 總是會使用一個包含觸發自動指令相關資訊的單一表格來呼叫 Lua 函數。最有用的鍵是
match:一個符合 pattern 的字串(請參閱 <amatch>
buf:觸發事件的緩衝區編號(請參閱 <abuf>
file:觸發事件的緩衝區的檔案名稱(請參閱 <afile>
data:一個包含某些事件傳遞的其他相關資料的表格
例如,這允許您為某些檔案類型設定緩衝區本機的映射
vim.api.nvim_create_autocmd("FileType", {
  pattern = "lua",
  callback = function(args)
    vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = args.buf })
  end
})
這表示如果您的回呼本身接受一個(甚至是可選的)參數,您必須將其包在 function() end 中以避免錯誤
vim.api.nvim_create_autocmd('TextYankPost', {
  callback = function() vim.hl.on_yank() end
})
(由於未使用的參數可以在 Lua 函數定義中省略,這等同於 function(args) ... end。)
您可以使用 buffer 而不是使用模式來建立緩衝區本機的自動指令(請參閱 autocmd-buflocal);在這種情況下,無法使用 pattern
-- set autocommand for current buffer
vim.api.nvim_create_autocmd("CursorHold", {
  buffer = 0,
  callback = function() print("hold") end,
})
-- set autocommand for buffer number 33
vim.api.nvim_create_autocmd("CursorHold", {
  buffer = 33,
  callback = function() print("hold") end,
})
類似於映射,您可以使用 desc 來新增說明(而且應該新增)。
vim.api.nvim_create_autocmd('TextYankPost', {
  callback = function() vim.hl.on_yank() end,
  desc = "Briefly highlight yanked text"
})
最後,您可以使用 group 鍵來群組自動指令;這將在下一節中詳細介紹。

群組自動指令 lua-guide-autocommands-group

自動指令群組可用於將相關的自動指令群組在一起;請參閱 autocmd-groups。這對於組織自動指令非常有用,尤其對於防止自動指令被多次設定。
可以使用 vim.api.nvim_create_augroup() 建立群組。此函數接受兩個強制參數:一個包含群組名稱的字串和一個表格,用於判斷如果群組已存在,是否應清除該群組(即移除所有已分組的自動指令)。該函數會傳回一個數字,它是群組的內部識別碼。群組可以透過此識別碼或名稱指定(但前提是必須先建立群組)。
例如,在可能會重新載入的檔案中定義自動指令的常見 Vimscript 模式是
augroup vimrc
  " Remove all vimrc autocommands
  autocmd!
  au BufNewFile,BufRead *.html set shiftwidth=4
  au BufNewFile,BufRead *.html set expandtab
augroup END
這等同於以下 Lua 程式碼
local mygroup = vim.api.nvim_create_augroup('vimrc', { clear = true })
vim.api.nvim_create_autocmd({ 'BufNewFile', 'BufRead' }, {
  pattern = '*.html',
  group = mygroup,
  command = 'set shiftwidth=4',
})
vim.api.nvim_create_autocmd({ 'BufNewFile', 'BufRead' }, {
  pattern = '*.html',
  group = 'vimrc',  -- equivalent to group=mygroup
  command = 'set expandtab',
})
自動指令群組對於給定的名稱是唯一的,因此您可以重複使用它們,例如,在不同的檔案中
local mygroup = vim.api.nvim_create_augroup('vimrc', { clear = false })
vim.api.nvim_create_autocmd({ 'BufNewFile', 'BufRead' }, {
  pattern = '*.c',
  group = mygroup,
  command = 'set noexpandtab',
})
您可以使用 vim.api.nvim_clear_autocmds() 來移除自動指令。此函數接受單一強制參數,它是描述要移除的自動指令的鍵的表格
-- Delete all BufEnter and InsertLeave autocommands
vim.api.nvim_clear_autocmds({event = {"BufEnter", "InsertLeave"}})
-- Delete all autocommands that uses "*.py" pattern
vim.api.nvim_clear_autocmds({pattern = "*.py"})
-- Delete all autocommands in group "scala"
vim.api.nvim_clear_autocmds({group = "scala"})
-- Delete all ColorScheme autocommands in current buffer
vim.api.nvim_clear_autocmds({event = "ColorScheme", buffer = 0 })
注意:只有在指定了 group 鍵的情況下,才會移除群組中的自動指令,即使另一個選項符合它也是如此。

另請參閱

nvim_get_autocmds():傳回所有相符的自動指令
nvim_exec_autocmds():執行所有相符的自動指令

使用者命令 lua-guide-commands

使用者命令 是自訂的 Vim 命令,它們會呼叫 Vimscript 或 Lua 函數。就像內建命令一樣,它們可以有參數、作用於範圍,或是自訂參數的完成。由於這些對於外掛程式最有用,我們將只介紹這個進階主題的基本知識。

建立使用者命令 lua-guide-commands-create

可以使用 nvim_create_user_command() 來建立使用者命令。此函數接受三個強制參數
一個字串,它是命令的名稱(必須以大寫字母開頭,以便與內建命令區分);
一個包含 Vim 命令的字串,或是一個在呼叫命令時執行的 Lua 函數;
一個包含 command-attributes 的表格;此外,它還可以包含鍵 desc(描述命令的字串);force(設定為 false 以避免替換同名的現有命令)和 preview(用於 :command-preview 的 Lua 函數)。
範例
vim.api.nvim_create_user_command('Test', 'echo "It works!"', {})
vim.cmd.Test()
--> It works!
(請注意,即使未提供任何屬性,第三個參數也是強制性的。)
Lua 函數會使用包含參數和修飾符的單一表格參數來呼叫。最重要的是
name:一個包含命令名稱的字串
fargs:一個表格,其中包含以空白分隔的命令參數(請參閱 <f-args>
bang:如果命令是以 ! 修飾符執行的,則為 true(請參閱 <bang>
line1:命令範圍的起始行號(請參閱 <line1>
line2:命令範圍的結束行號(請參閱 <line2>
range:命令範圍中的項目數:0、1 或 2(請參閱 <range>
count:任何提供的計數(請參閱 <count>
smods:一個包含命令修飾符的表格(請參閱 <mods>
例如
vim.api.nvim_create_user_command('Upper',
  function(opts)
    print(string.upper(opts.fargs[1]))
  end,
  { nargs = 1 })
vim.cmd.Upper('foo')
--> FOO
除了 :command-complete 中列出的屬性之外,complete 屬性還可以採用 Lua 函數。
vim.api.nvim_create_user_command('Upper',
  function(opts)
    print(string.upper(opts.fargs[1]))
  end,
  { nargs = 1,
    complete = function(ArgLead, CmdLine, CursorPos)
      -- return completion candidates as a list-like table
      return { "foo", "bar", "baz" }
    end,
})
使用 vim.api.nvim_buf_create_user_command() 建立緩衝區本機的使用者命令。此處第一個參數是緩衝區編號(0 表示目前的緩衝區);其餘參數與 nvim_create_user_command() 的參數相同。
vim.api.nvim_buf_create_user_command(0, 'Upper',
  function(opts)
    print(string.upper(opts.fargs[1]))
  end,
  { nargs = 1 })

刪除使用者命令 lua-guide-commands-delete

可以使用 vim.api.nvim_del_user_command() 來刪除使用者命令。唯一的參數是命令的名稱
vim.api.nvim_del_user_command('Upper')
若要刪除緩衝區本機的使用者命令,請使用 vim.api.nvim_buf_del_user_command()。此處第一個參數是緩衝區編號(0 表示目前的緩衝區),第二個參數是命令名稱
vim.api.nvim_buf_del_user_command(4, 'Upper')

鳴謝 lua-guide-credits

本指南很大一部分取自 nanotee 的 Lua 指南:https://github.com/nanotee/nvim-lua-guide
感謝 @nanotee!
主要
命令索引
快速參考