重複

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


重複命令、Vim 腳本與除錯
使用者手冊的第 26 章介紹了重複功能 usr_26.txt

單次重複 single-repeat

.
. 重複上次變更,並將計數替換為 [count]。當 'y' 標誌包含在 'cpoptions' 中時,也會重複貼上 (yank) 命令。不會重複命令列命令。
簡單的變更可以使用 "." 命令重複。若沒有計數,則使用上次變更的計數。如果輸入計數,則會替換上一個計數。v:countv:count1 會被設定。
如果上次變更包含指定一個編號的暫存器,暫存器號碼將會遞增。請參閱 redo-register,查看如何使用此功能的範例。
請注意,當重複使用視覺選取範圍的命令時,會使用相同大小的區域,請參閱 visual-repeat
@:
@: 重複上次命令列 [count] 次。

多次重複 multi-repeat

:g :global E148 :[範圍]g[lobal]/{pattern}/[cmd] 在 [範圍] 內符合 {pattern} 的行上執行 Ex 命令 [cmd] (預設為 ":p")。
:[範圍]g[lobal]!/{pattern}/[cmd] 在 [範圍] 內不符合 {pattern} 的行上執行 Ex 命令 [cmd] (預設為 ":p")。
:v :vglobal :[範圍]v[global]/{pattern}/[cmd] 與 :g! 相同。
範例
:g/^Obsolete/d _
:d 後使用底線可以避免覆蓋暫存器或剪貼簿。這也可以加快速度。
您可以使用任何其他單一位元組字元,而不是包圍 {pattern} 的 '/',但不能使用字母字元、'\'、'"'、'|' 或 '!'。如果您想在搜尋模式或取代字串中包含 '/',這非常有用。
有關模式的定義,請參閱 pattern
注意:[cmd] 可能包含範圍;有關範例,請參閱 collapseedit-paragraph-join
global 命令的工作原理是先掃描 [範圍] 行,並標記每個出現匹配的行 (對於多行模式,只有匹配的開始位置重要)。在第二次掃描中,會針對每個已標記的行執行 [cmd],就好像游標位於該行一樣。對於 ":v" 和 ":g!",則會針對每個未標記的行執行命令。如果刪除某一行,其標記就會消失。[範圍] 的預設值是整個緩衝區 (1,$)。使用 "CTRL-C" 可以中斷命令。如果某一行出現錯誤訊息,則會中止該行的命令,並且 global 命令會繼續處理下一個已標記或未標記的行。E147
當以遞迴方式使用該命令時,它只會在一行上運作。此時不允許指定範圍。這對於查找所有符合某個模式但不符合另一個模式的行非常有用。
:g/found/v/notfound/{cmd}
這首先會查找所有包含 "found" 的行,但只有在沒有 "notfound" 的匹配項時才會執行 {cmd}
可以使用任何 Ex 命令,請參閱 ex-cmd-index。若要執行 Normal 模式命令,您可以使用 :normal 命令。
:g/pat/normal {commands}
請確保 {commands} 以完整命令結尾,否則 Vim 會等待您為每個匹配項輸入剩餘的命令。畫面將不會更新,因此您不知道自己正在做什麼。請參閱 :normal
undo/redo 命令將會一次復原/重做整個 global 命令。上一個上下文標記只會設定一次 (使用 "''" 您可以返回到執行 global 命令之前游標所在的位置)。
global 命令會設定最後使用的搜尋模式和最後使用的取代模式 (這是與 vi 相容的)。這使得全域取代字串變得容易
:g/pat/s//PAT/g
這會將所有出現的 "pat" 取代為 "PAT"。也可以使用以下方式完成
:%s/pat/PAT/g
這會少兩個字元!
在 Ex 模式下使用 "global" 時,一個特殊情況是使用 ":visual" 作為命令。這會移動到匹配的行,然後進入 Normal 模式讓您在那裡執行命令,直到您使用 gQ 返回 Ex 模式。這會針對每個匹配的行重複執行。在執行此操作時,您不能使用 ":global"。若要中止此操作,請輸入 CTRL-C 兩次。

複雜重複 complex-repeat

q recording q{0-9a-zA-Z"} 將輸入的字元記錄到暫存器 {0-9a-zA-Z"} 中 (大寫字母表示附加)。執行暫存器時,'q' 命令會停用,並且它在映射和 :normal 內不起作用。
注意: 如果用於記錄的暫存器也用於 yp,則結果很可能與預期的不同,因為貼上會貼上錄製的巨集,而貼上 (yank) 會覆寫錄製的巨集。
注意: 錄製發生在您輸入時,重播暫存器的方式就好像按鍵來自映射一樣。這很重要,例如,對於復原來說,它只會在輸入命令時同步。
q 停止錄製。實作說明:停止錄製的 'q' 不會儲存在暫存器中,除非它是映射的結果
@
@{0-9a-z".=*+} 執行暫存器 {0-9a-z".=*+} 的內容 [count] 次。請注意,不能使用暫存器 '%' (目前檔案的名稱) 和 '#' (替代檔案的名稱)。暫存器的執行方式類似於映射,這表示 'wildchar''wildcharm' 之間的差異適用,而且復原可能不會以相同方式同步。對於 "@=",系統會提示您輸入一個運算式。然後執行運算式的結果。另請參閱 @:
@@ E748 @@ 重複上一個 @{0-9a-z":*} [count] 次。
v_@-預設值
{Visual}@{0-9a-z".=*+} 在行向視覺模式下,針對每個選定的行執行 {Visual}@@ 暫存器的內容。請參閱 visual-repeatdefault-mappings
Q
Q 重複上次錄製的暫存器 [count] 次。請參閱 reg_recorded()
v_Q-預設值
{Visual}Q 在行向視覺模式下,針對每個選定的行重複上次錄製的暫存器。請參閱 visual-repeatdefault-mappings
:@
:[addr]@{0-9a-z".=*+} 將暫存器 {0-9a-z".=*+} 的內容作為 Ex 命令執行。首先將游標設定在 [addr] 行 (預設為目前行)。如果暫存器中的最後一行沒有 <CR>,則當 'cpoptions' 中存在 'e' 標誌時,會自動新增。對於 ":@=",會使用最後使用的運算式。執行運算式的結果會作為 Ex 命令執行。這些命令中無法辨識映射。當行向暫存器中的一行的開頭存在 行接續 字元 (\) 時,則會將它與上一行合併。這對於貼上 (yank) 和執行 Vim 腳本的部分內容非常有用。
:@:
:[addr]@: 重複上次命令列。首先將游標設定在 [addr] 行 (預設為目前行)。
:[addr]@ :@@
:[addr]@@ 重複上一個 :@{register}。首先將游標設定在 [addr] 行 (預設為目前行)。

使用 Vim 腳本 using-scripts

若要撰寫 Vim 腳本,請參閱使用者手冊的第 41 章 usr_41.txt
:so :source load-vim-script :[範圍]so[urce] [檔案] 從 [檔案] 執行 Ex 命令 或 Lua 程式碼 (".lua" 檔案)。如果沒有 [檔案],則會使用目前的緩衝區,並且如果 'filetype' 為 "lua" 或其檔名以 ".lua" 結尾,則會將其視為 Lua 程式碼。觸發 SourcePre 自動命令。:source!
:[範圍]so[urce]! {檔案}{檔案} 執行 Normal 模式 命令。當在 :global:argdo:windo:bufdo 之後,在迴圈中或在另一個命令跟隨時使用,執行命令時將不會更新顯示畫面。
:ru :runtime :ru[ntime][!] [where] {檔案} ...'runtimepath' 和/或 'packpath' 所提供的每個目錄中,讀取 {檔案} (相對路徑) 並執行其中的 Ex 命令或 Lua 程式碼 (".lua" 檔案)。忽略不存在的檔案。
範例
:runtime syntax/c.vim
:runtime syntax/c.lua
可以有多個以空格分隔的 {檔案} 引數。會在 'runtimepath' 中的第一個目錄中搜尋每個 {檔案},然後在第二個目錄中搜尋,依此類推。
當包含 [!] 時,會執行所有找到的檔案。否則只會執行第一個找到的檔案。
當省略 [where] 時,只會使用 'runtimepath'。其他值:START 只在 'packpath' 中的 "start" 下搜尋 OPT 只在 'packpath' 中的 "opt" 下搜尋 PACK'packpath' 中的 "start" 和 "opt" 下搜尋 ALL 先使用 'runtimepath',然後在 'packpath' 中的 "start" 和 "opt" 下搜尋
{檔案} 包含萬用字元時,它會展開為所有符合的檔案。範例
:runtime! plugin/**/*.{vim,lua}
這就是 Nvim 在啟動時用來載入外掛程式檔案的方式。這個類似的命令
:runtime plugin/**/*.{vim,lua}
只會執行第一個檔案。
對於每個 {file} 樣式,如果兩個 .vim.lua 檔案名稱匹配且僅擴展名不同,則會先載入 .vim 檔案。
'verbose' 值為 1 或更高時,如果找不到任何檔案,則會顯示訊息。當 'verbose' 值為 2 或更高時,則會顯示關於每個搜尋檔案的訊息。
:pa :packadd E919 :pa[ckadd][!] {name}'packpath' 中搜尋可選的外掛程式目錄,並載入找到的任何外掛程式檔案。目錄必須符合
pack/*/opt/{name}
如果該目錄尚未存在於 'runtimepath' 中,則會將其加入。如果目錄 pack/*/opt/{name}/after 存在,則會將其加入到 'runtimepath' 的末尾。
如果略過了從 "pack/*/start" 載入套件,則會優先搜尋此目錄
pack/*/start/{name}
請注意,{name} 是目錄名稱,而不是 .vim 檔案的名稱。所有符合以下樣式的檔案
pack/*/opt/{name}/plugin/**/*.vim
pack/*/opt/{name}/plugin/**/*.lua
都會被載入。這允許使用 "plugin" 下的子目錄,就像 'runtimepath' 中的外掛程式一樣。
如果已啟用檔案類型偵測(通常是在您的 vimrc 中使用 syntax enablefiletype on 命令,或者在 初始化 期間自動啟用),並且在 "pack/*/opt/{name}" 中找到該套件,此命令也會尋找 "{name}/ftdetect/*.vim" 檔案。
當加入可選的 ! 時,不會載入任何外掛程式檔案或 ftdetect 腳本,只會將符合的目錄加入到 'runtimepath' 中。這在您的 init.vim 中很有用。外掛程式將在 初始化 期間載入,請參閱 load-plugins(請注意,載入順序將會反轉,因為每個目錄都會插入到其他目錄之前)。在這種情況下,ftdetect 腳本將在 初始化 期間載入,在 load-plugins 步驟之前。
另請參閱 pack-add
:packl :packloadall :packl[oadall][!] 載入 'packpath' 中每個條目下的 "start" 目錄中的所有套件。
首先,將找到的所有目錄加入到 'runtimepath' 中,然後載入目錄中找到的外掛程式。這允許一個外掛程式依賴於另一個外掛程式的東西,例如 "autoload" 目錄。有關這如何有用的資訊,請參閱 packload-two-steps
這通常會在啟動期間,在載入您的 vimrc 檔案後自動完成。使用此命令,可以更早完成此操作。
套件只會載入一次。第二次使用 :packloadall 不會有任何效果。當加入可選的 ! 時,即使之前完成過,此命令也會載入套件。
請注意,當在 vimrc 檔案中使用 :packloadall 時,'runtimepath' 選項會被更新,之後 'runtimepath' 中的所有外掛程式都會被載入,這表示它們會被再次載入。預期外掛程式會處理這種情況。
錯誤只會導致中止載入發生錯誤的腳本,後續的外掛程式仍會被載入。請參閱 packages
:scripte[ncoding] [encoding] :scripte :scriptencoding E167 指定腳本中使用的字元編碼。如果與 'encoding' 選項的值不同,則會將以下行從 [encoding] 轉換為該值。範例
scriptencoding iso-8859-5
scriptencoding cp932
當 [encoding] 為空時,不會進行轉換。這可以用於將轉換限制為一系列行
scriptencoding euc-jp
... lines to be converted ...
scriptencoding
... not converted ...
當系統不支援轉換時,不會出現錯誤訊息,也不會進行轉換。當無法轉換某行時,不會出現錯誤,並保留原始行。
請勿使用 "ucs-2" 或 "ucs-4",腳本不能使用這些編碼(它們會包含 NUL 位元組)。當載入的腳本以 utf-8 格式的 BOM(位元組順序標記)開始時,Vim 會識別它,因此不需要使用 ":scriptencoding utf-8"。
:scr :scriptnames :scr[iptnames] 列出所有已載入的腳本名稱,依它們第一次載入的順序排列。該數字用於腳本 ID <SID>。另請參閱 getscriptinfo()
:scr[iptnames][!] {scriptId} :script
編輯腳本 {scriptId}。雖然 ":scriptnames name" 有效,但建議使用 ":script name"。當目前的緩衝區無法被 放棄 且不存在 ! 時,命令會失敗。
:fini :finish E168 :fini[sh] 停止載入腳本。只能在 Vim 腳本檔案中使用。這是跳過檔案其餘部分的快速方法。如果它在 :try 之後但在匹配的 :finally 之前使用(如果存在),則會先執行 ":finally" 後的命令,直到匹配的 :endtry。此過程適用於腳本中的所有巢狀 ":try"。最外層的 ":endtry" 然後停止載入腳本。
所有命令和命令序列都可以透過將它們放入已命名的暫存器中然後執行它來重複執行。有兩種方法可以將命令放入暫存器中
使用錄製命令 "q"。您輸入命令一次,並且在執行這些命令時,它們會儲存在暫存器中。這很簡單,因為您可以查看您正在執行的操作。如果您犯了錯誤,請將暫存器 "p" 放入檔案中,編輯命令序列,然後將其再次刪除到暫存器中。您可以透過附加到暫存器來繼續錄製(使用大寫字母)。
刪除或複製命令序列到暫存器中。
經常使用的命令序列可以使用 ':map' 命令放入功能鍵下。
另一種方法是將命令放入檔案中,並使用 ':source!' 命令執行它們。這對於長命令序列很有用。可以與 ':map' 命令結合使用,將複雜的命令放入功能鍵下。
':source' 命令從檔案逐行讀取 Ex 命令。您必須輸入任何需要的鍵盤輸入。':source!' 命令從腳本檔案逐字元讀取,並將每個字元解釋為您輸入的字元。
範例:當您輸入 ":!ls" 命令時,您會收到 按下 Enter 的提示。如果您 ':source' 一個包含 "!ls" 行的檔案,您必須自己輸入 <Enter>。但是,如果您 ':source!' 一個包含 ":!ls" 行的檔案,則會從該檔案讀取下一個字元,直到找到 <CR>。您不必自己輸入 <CR>,除非 ":!ls" 是檔案中的最後一行。
可以在腳本檔案中放入 ':source[!]' 命令,因此您可以建立腳本檔案的由上而下的階層結構。':source' 命令可以巢狀到一次可以開啟的檔案數量(約 15 個)。':source!' 命令可以巢狀到最多 15 層。
您可以在載入的檔案內使用 "<sfile>" 字串(字面意思,這不是特殊鍵),在預期檔案名稱的地方。它將被替換為載入檔案的檔案名稱。例如,如果您的 init.vim 檔案所在目錄中有一個 "other.vimrc" 檔案,您可以使用此命令從您的 init.vim 檔案中載入它
:source <sfile>:h/other.vimrc
在腳本檔案中,與終端機相關的鍵碼由與終端機無關的兩個字元代碼表示。這表示它們可以在不同類型的終端機上以相同的方式使用。鍵碼的第一個字元是 0x80 或 128,在螢幕上顯示為 "~@"。第二個字元可以在 鍵盤符號 清單中找到。任何這些代碼也可以透過 CTRL-V 後跟三位數十進制代碼輸入。
:source_crnl W15 Windows:使用 ":source" 讀取的檔案通常具有 <CR><NL> <EOL>。這些總是有效。如果您使用的是具有 <NL> <EOL> 的檔案(例如,在 Unix 上建立的檔案),如果 'fileformats' 不為空且第一行沒有以 <CR> 結尾,則會識別它。如果第一行有類似 ":map <F1> :help^M" 的內容,其中 "^M" 是 <CR>,則會失敗。如果第一行以 <CR> 結尾,但後續的行沒有,您會收到錯誤訊息,因為第一行的 <CR> 會遺失。
在其他系統上,Vim 期望 ":source" 的檔案以 <NL> 結尾。這些總是有效。如果您使用的是具有 <CR><NL> <EOL> 的檔案(例如,在 MS-Windows 上建立的檔案),所有行都會有一個尾隨的 <CR>。這可能會導致某些命令(例如,映射)出現問題。沒有自動 <EOL> 偵測,因為通常會從定義以 <CR> 結尾的映射的行開始,這會使自動機混淆。
行接續
":source" 的 Ex 命令腳本檔案中的長行可以透過在下一行的開頭插入行接續符號 "\"(反斜線)來分割。反斜線之前可以有空格,這些空格會被忽略。
範例:以下幾行
:set comments=sr:/*,mb:*,el:*/,
             \://,
             \b:#,
             \:%,
             \n:>,
             \fb:-
會被解釋為好像它們是在一行中給出的
:set comments=sr:/*,mb:*,el:*/,://,b:#,:%,n:>,fb:-
會忽略反斜線之前一行中的所有前導空白字元。但請注意,反斜線之前一行中的尾隨空白字元不能隨意插入;這取決於命令被分割的位置是否允許額外的空白字元。
當需要空格時,最好將其放在反斜線之後。行尾的空格很難看到,可能會不小心被刪除。
:syn match Comment
        \ "very long regexp"
        \ keepend
":append" 和 ":insert" 命令存在問題
:1append
\asdf
.
反斜線會被視為行接續符號,因此會產生以下命令
:1appendasdf
.
若要避免此問題,請將 'C' 旗標新增至 'cpoptions' 選項
:set cpo+=C
:1append
\asdf
.
:set cpo-=C
請注意,當命令位於函數內部時,您需要在定義函數時新增 'C' 旗標,執行時則無關。
:set cpo+=C
:function Foo()
:1append
\asdf
.
:endfunction
:set cpo-=C
行接續註解
若要在行之間新增註解,請以 '"\ ' 開頭。請注意反斜線後面的空格。範例
let array = [
        "\ first entry comment
        \ 'first',
        "\ second entry comment
        \ 'second',
        \ ]
原理:大多數程式都使用尾隨反斜線來表示行接續。在 Vim 中使用此方法會導致與 Vi 不相容。例如,對於此 Vi 映射
:map xx  asdf\
因此,使用不常見的前導反斜線。
在接續行中開始註解會導致所有後續的接續行成為註解的一部分。由於這種情況已經存在很長時間,當可以新增註解到接續行序列的中間時,無法使用 \", 因為這是一個有效的接續行。使用 '"\ ' 最接近,儘管它看起來可能有點奇怪。要求反斜線後面的空格是為了使其不太可能成為普通的註解行。

使用 Vim 套件 套件

Vim「套件」是一個包含 外掛程式 的目錄。與一般外掛程式相比,套件可以...
下載為封存檔並在其自己的目錄中解壓縮,因此檔案不會與其他外掛程式的檔案混合。
成為 git、mercurial 等儲存庫,因此易於更新。
包含多個彼此依賴的外掛程式。
包含在啟動時自動載入的插件(「start」套件,位於「pack/*/start/*」中)以及僅在需要時透過 :packadd 載入的插件(「opt」套件,位於「pack/*/opt/*」中)。
runtime-search-path(執行時搜尋路徑)
Nvim 會在以下位置搜尋 :runtime 檔案:1. 'runtimepath' 中的所有路徑。2. 所有「pack/*/start/*」目錄。
請注意,「pack/*/start/*」路徑不會明確包含在 'runtimepath' 中,因此它們不會由「:set rtp」或「echo &rtp」回報。腳本可以使用 nvim_list_runtime_paths() 來列出所有已使用的目錄,並使用 nvim_get_runtime_file() 來查詢執行時路徑中特定的檔案或子資料夾。範例:
" List all runtime dirs and packages with Lua paths.
:echo nvim_get_runtime_file("lua/", v:true)
使用套件並自動載入
假設您的 Nvim 檔案位於「~/.local/share/nvim/site」,而您想要從 zip 封存檔「/tmp/foopack.zip」新增一個套件。
% mkdir -p ~/.local/share/nvim/site/pack/foo
% cd ~/.local/share/nvim/site/pack/foo
% unzip /tmp/foopack.zip
目錄名稱「foo」是任意的,您可以選擇任何您喜歡的名稱。
您現在將在 ~/.local/share/nvim/site 下擁有這些檔案:pack/foo/README.txt pack/foo/start/foobar/plugin/foo.vim pack/foo/start/foobar/syntax/some.vim pack/foo/opt/foodebug/plugin/debugger.vim
在處理完您的 設定檔 後啟動時,Nvim 會掃描 'packpath' 中的所有目錄,以尋找「pack/*/start/*」中的插件,然後載入這些插件。
為了在剖析您的 vimrc 時允許呼叫套件功能,:colorschemeautoload 都會自動在 'packpath''runtimepath' 下搜尋。請參閱每個功能的說明文件以了解詳細資訊。
在範例中,Nvim 會找到「pack/foo/start/foobar/plugin/foo.vim」並載入它。
如果「foobar」插件啟動並將 'filetype' 設定為「some」,Nvim 會找到 syntax/some.vim 檔案,因為它的目錄位於執行時搜尋路徑中。
如果有的話,Nvim 也會載入 ftdetect 檔案。
請注意,「pack/foo/opt」下的檔案不會自動載入,只有「pack/foo/start」下的檔案才會載入。請參閱下方的 pack-add 以了解「opt」目錄的使用方式。
如果停用了插件載入,則不會自動載入套件,請參閱 load-plugins
若要較早載入套件,以便讀取 plugin/ 檔案,請使用::packloadall。即使停用插件載入,此命令也有效。自動載入只會發生一次。
如果套件具有「after」目錄,則該目錄會加入到 'runtimepath' 的結尾,以便其中的任何內容稍後載入。
使用單一插件並自動載入
如果您沒有套件,而只有單一插件,您需要建立額外的目錄層級
% mkdir -p ~/.local/share/nvim/site/pack/foo/start/foobar
% cd ~/.local/share/nvim/site/pack/foo/start/foobar
% unzip /tmp/someplugin.zip
您現在將擁有這些檔案:pack/foo/start/foobar/plugin/foo.vim pack/foo/start/foobar/syntax/some.vim
從這裡開始,它的運作方式與上述相同。
可選插件
pack-add
若要從套件載入可選插件,請使用 :packadd 命令
:packadd foodebug
這會在 'packpath' 中搜尋「pack/*/opt/foodebug」,並找到 ~/.local/share/nvim/site/pack/foo/opt/foodebug/plugin/debugger.vim 並讀取它。
如果滿足某些條件,則可以執行此操作。例如,根據 Nvim 是否支援某個功能或缺少相依性。
您也可以在啟動時載入可選插件,方法是將此命令放入您的 設定檔 中:
:packadd! foodebug
額外的「!」是為了避免如果 Nvim 是以 --noplugin 啟動,則不會載入插件。
一個套件只在「opt」目錄中有檔案是完全正常的。然後您需要在您想要使用每個插件時載入它們。
要放置什麼在哪裡
由於以 :colorscheme 載入的色彩配置會在「pack/*/start」和「pack/*/opt」下找到,您可以將它們放置在任何位置。我們建議您將它們放置在「pack/*/opt」下,例如「~/.config/nvim/pack/mycolors/opt/dark/colors/very_dark.vim」。
檔案類型插件應放置在「pack/*/start」下,以便始終可以找到它們。除非您有多個適用於檔案類型的插件,並且想要使用 :packadd 選擇要載入哪個插件。例如,根據編譯器版本。
if foo_compiler_version > 34
  packadd foo_new
else
  packadd foo_old
endif
「after」目錄在套件中很可能沒有用處。儘管它並未被禁止使用。

建立 Vim 套件 package-create

假設您撰寫了一個或多個以套件形式散佈的插件。
如果您有兩個不相關的插件,您將使用兩個套件,以便 Vim 使用者可以選擇他們包含或不包含的內容。或者,您可以決定使用一個包含可選插件的套件,並告訴使用者使用 :packadd 新增偏好的插件。
決定您要如何散佈套件。您可以建立封存檔,也可以使用儲存庫。封存檔可以被更多使用者使用,但更新到新版本會比較困難。儲存庫通常可以輕鬆地保持最新,但需要像「git」這樣的程式才能使用。您可以同時執行這兩種操作,github 可以自動為發佈建立封存檔。
您的目錄配置如下:start/foobar/plugin/foo.vim " 始終載入,定義命令 start/foobar/plugin/bar.vim " 始終載入,定義命令 start/foobar/autoload/foo.vim " 在使用 foo 命令時載入 start/foobar/doc/foo.txt " foo.vim 的說明 start/foobar/doc/tags " 說明標籤 opt/fooextra/plugin/extra.vim " 可選插件,定義命令 opt/fooextra/autoload/extra.vim " 在使用 extra 命令時載入 opt/fooextra/doc/extra.txt " extra.vim 的說明 opt/fooextra/doc/tags " 說明標籤
這允許使用者執行以下操作:
mkdir ~/.local/share/nvim/site/pack
cd ~/.local/share/nvim/site/pack
git clone https://github.com/you/foobar.git myfoobar
這裡的「myfoobar」是使用者可以選擇的名稱,唯一的條件是它與其他套件不同。
在您的說明文件中,您會說明插件的作用,並告訴使用者如何載入可選插件
:packadd! fooextra
您可以將此 packadd 命令新增到您的其中一個插件中,以便在需要可選插件時執行。
執行 :helptags 命令以產生 doc/tags 檔案。在套件中包含此產生的檔案表示使用者可以將套件放入 pack 目錄中,並且說明命令可以立即運作。在變更插件說明後,不要忘記重新執行命令
:helptags path/start/foobar/doc
:helptags path/opt/fooextra/doc
插件之間的相依性
packload-two-steps
假設您有兩個插件都依賴相同的功能。您可以將通用功能放入 autoload 目錄中,以便自動找到它。您的套件將具有這些檔案
pack/foo/start/one/plugin/one.vim
call foolib#getit()
pack/foo/start/two/plugin/two.vim
call foolib#getit()
pack/foo/start/lib/autoload/foolib.vim
func foolib#getit()
這可以運作,因為在讀取插件時,將會搜尋 start 套件中的 autoload 檔案。

偵錯腳本 debug-scripts

除了您可以在腳本中新增以找出它們正在做什麼的明顯訊息外,Vim 還提供偵錯模式。這允許您逐步執行讀取的檔案或使用者函式,並設定中斷點。
注意:偵錯模式遠非完美。偵錯會對 Vim 的運作方式產生副作用。您無法使用它來偵錯所有內容。例如,顯示會因偵錯訊息而變得混亂。
偵錯模式的替代方案是設定 'verbose' 選項。數字越大,它會提供更多關於 Vim 正在做什麼的詳細訊息。

啟動偵錯模式 debug-mode

若要進入偵錯模式,請使用以下方法之一:1. 使用 -D 引數啟動 Vim
vim -D file.txt
偵錯會在讀取第一個 vimrc 檔案後立即開始。這對於找出 Vim 啟動時發生的事情很有用。一個副作用是 Vim 會在初始化完成之前切換終端機模式,導致不可預測的結果。對於僅限 GUI 的版本 (Windows),偵錯會在 GUI 視窗開啟後立即開始。若要使其儘早發生,請在 vimrc 檔案中新增「:gui」命令。 :debug
2. 使用「:debug」前置詞執行命令。偵錯只會在執行此命令時完成。對於偵錯特定腳本或使用者函式很有用。並且適用於 autocommand 使用的腳本和函式。範例:
:debug edit test.txt.gz
3. 在讀取的檔案或使用者函式中設定中斷點。您可以在命令列中執行此操作:
vim -c "breakadd file */explorer.vim" .
這將會執行 Vim,並在「explorer.vim」腳本的第一行停止。也可以在偵錯模式中設定中斷點。
在偵錯模式中,每個已執行的命令都會在執行之前顯示。註解行、空白行和未執行的行會略過。當一行包含兩個以「|」分隔的命令時,每個命令都會單獨顯示。

偵錯模式

進入偵錯模式後,可以使用一般的 Ex 命令。例如,若要檢查變數的值
echo idx
在使用者函式內,這將會印出區域變數「idx」的值。在前面加上「g:」可取得全域變數的值:
echo g:idx
所有命令都在目前函式或腳本的內容中執行。您也可以設定選項,例如設定或重設 'verbose' 會顯示發生的事情,但您可能想要在執行您感興趣的行之前設定它
:set verbose=20
應避免需要更新螢幕的命令,因為它們的效果只有在離開偵錯模式後才會注意到。例如:
:help
不會很有幫助。
偵錯模式有一個單獨的命令列歷程記錄。
函式行的行號相對於函式的開頭。如果您無法確定您在哪裡,請在另一個 Vim 中編輯定義函式的檔案,搜尋函式的開頭,並執行「99j」。將「99」取代為行號。
此外,可以使用以下命令:>cont
cont 繼續執行,直到遇到下一個中斷點。>quit
quit 中止執行。這類似於使用 CTRL-C,某些項目可能仍然會執行,不會中止所有項目。仍然會在下一個中斷點停止。>next
next 執行命令,並在完成後返回偵錯模式。這會跳過使用者函式呼叫和讀取的檔案。>step
step 執行命令,並針對下一個命令返回偵錯模式。這會逐步進入呼叫的使用者函式和讀取的檔案。>interrupt
interrupt 這類似於使用 CTRL-C,但與「>quit」不同,它會在下一個執行的命令返回偵錯模式。對於測試中斷例外狀況的 :finally:catch 很有用。>finish
finish 結束當前腳本或使用者函數,並返回到除錯模式,以便對呼叫或引用它的指令之後的指令進行除錯。 >bt
>backtrace
>where
backtrace 顯示當前除錯會話的呼叫堆疊追蹤。bt where >frame
frame N 跳到第 N 層回溯。+ 和 - 號表示相對移動。例如,「:frame +3」會向上移動三層。 >up
up 從呼叫堆疊追蹤中往上一層。 >down
down 從呼叫堆疊追蹤中往下一層。
關於除錯模式中的額外指令
它們沒有指令列自動完成功能,您只能取得一般 Ex 指令的自動完成功能。
您可以縮短它們,縮短到只剩一個字元,除非有多個指令以相同字母開頭。「f」代表「finish」,使用「fr」代表「frame」。
按下 <CR> 會重複前一個指令。當執行另一個指令時,此行為會重置(因為不清楚您想要重複哪個指令)。
當您想要使用同名的 Ex 指令時,請在前面加上冒號:「:cont」、「:next」、「:finish」(或更短)。
回溯顯示函數呼叫的層級結構,例如:
>bt
3 function One[3]
2 Two[3]
->1 Three[3]
0 Four
line 1: let four = 4
「->」指向目前的框架。使用「up」、「down」和「frame N」來選擇另一個框架。
在目前框架中,您可以評估局部函數變數。目前還無法查看目前行的指令。

定義中斷點

:breaka :breakadd :breaka[dd] func [lnum] {name} 在函數中設定中斷點。範例
:breakadd func Explore
不會檢查有效的函數名稱,因此可以在定義函數之前設定中斷點。
:breaka[dd] file [lnum] {name} 在載入的檔案中設定中斷點。範例
:breakadd file 43 init.vim
:breaka[dd] here 在目前檔案的目前行設定中斷點。如同執行
:breakadd file <cursor-line> <current-file>
請注意,這僅適用於載入檔案時執行的指令,不適用於在該檔案中定義的函數。
:breaka[dd] expr {expression} 設定一個中斷點,當 {expression} 的評估結果變為不同值時,就會中斷。範例
:breakadd expr g:lnum
當全域變數 lnum 變更時,就會中斷。
評估中的錯誤會被抑制,您可以使用尚未存在的變數名稱。這也表示如果表達式有錯誤,您將不會注意到任何事情。
請注意,如果您監看 腳本變數,這會在切換腳本時中斷,因為腳本變數僅在定義它的腳本中有效,如果該腳本是從其他幾個腳本呼叫的,則每次該特定變數可見或再次無法存取時,都會停止。
[lnum] 是中斷點的行號。Vim 將會在這一行或之後停止。如果省略,則會使用第 1 行。
:debug-name
{name} 是一個與檔案或函數名稱相符的樣式。此樣式與自動指令所使用的樣式相同。必須完全匹配(就像樣式以「^」開頭並以「$」結尾一樣)。「*」比對任何字元序列。'ignorecase' 不會使用,但可以在樣式中使用「\c」來忽略大小寫 /\c。函數名稱不要包含 ()!
針對載入的腳本的比對是根據完整的檔案名稱完成的。如果未指定路徑,則會使用目前目錄。範例
breakadd file explorer.vim
比對目前目錄中的「explorer.vim」。
breakadd file *explorer.vim
比對「.../plugin/explorer.vim」、「.../plugin/iexplorer.vim」等等。
breakadd file */explorer.vim
比對「.../plugin/explorer.vim」和任何其他目錄中的「explorer.vim」。
針對函數的比對是根據「:function」輸出中顯示的名稱完成的。對於局部函數,這表示會附加類似「<SNR>99_」的內容。
請注意,函數會先載入,然後再執行。載入時,會檢查「file」中斷點,執行時,會檢查「func」中斷點。

刪除中斷點

:breakd :breakdel E161 :breakd[el] {nr} 刪除中斷點 {nr}。使用 :breaklist 查看每個中斷點的編號。
:breakd[el] * 刪除所有中斷點。
:breakd[el] func [lnum] {name} 刪除函數中的中斷點。
:breakd[el] file [lnum] {name} 刪除已載入檔案中的中斷點。
:breakd[el] here 刪除目前檔案目前行的中斷點。
如果省略 [lnum],則會刪除函數或檔案中的第一個中斷點。{name} 必須與為「:breakadd」指令輸入的內容完全相同。「explorer」、「*explorer.vim」和「*explorer*」是不同的。

列出中斷點

:breakl :breaklist :breakl[ist] 列出所有中斷點。

不明確

:debugg :debuggreedy :debugg[reedy] 從正常輸入流讀取除錯模式指令,而不是直接從使用者取得。僅適用於測試腳本。範例
echo 'q^Mq' | vim -e -s -c debuggreedy -c 'breakadd file script.vim' -S script.vim
:0debugg[reedy] 還原「:debuggreedy」:直接從使用者取得除錯模式指令,不要將輸入預先輸入以用於除錯指令。

效能分析 profile profiling

效能分析表示 Vim 會測量執行函數和/或腳本所花費的時間。
您也可以使用 reltime() 函數來測量時間。
如需分析語法突顯,請參閱 :syntime
例如,分析 one_script.vim 腳本檔案
:profile start /tmp/one_script_profile
:profile file one_script.vim
:source one_script.vim
:exit
:prof[ile] start {fname} :prof :profile E750 開始分析,在結束時或當呼叫 :profile stop:profile dump 指令時,將輸出寫入 {fname}。「~/」和 {fname} 中的環境變數將會展開。如果 {fname} 已存在,則會以無訊息方式覆寫。變數 v:profiling 會設定為 1。
:prof[ile] stop 將收集的效能分析資訊寫入記錄檔,並停止效能分析。您可以使用 :profile start 指令來清除效能分析統計資料並重新開始效能分析。
:prof[ile] pause 停止效能分析,直到下一個 :profile continue 指令。在執行不應計算在內的操作(例如,外部指令)時可以使用。不會巢狀。
:prof[ile] continue 在 :profile pause 之後繼續效能分析。
:prof[ile] func {pattern} 分析符合樣式 {pattern} 的函數。如需有關如何使用 {pattern} 的資訊,請參閱 :debug-name
:prof[ile][!] file {pattern} 分析符合樣式 {pattern} 的腳本檔案。如需有關如何使用 {pattern} 的資訊,請參閱 :debug-name。這只會分析腳本本身,不會分析其中定義的函數。當加入 [!] 時,也會分析腳本中定義的所有函數。請注意,只有在指令之後載入腳本時,才會開始分析。腳本本身的 :profile 指令將不起作用。
:prof[ile] dump 立即將效能分析的目前狀態寫入記錄檔。執行此指令後,Vim 會繼續收集效能分析統計資料。
:profd[el] ... :profd :profdel 停止為指定的引數進行效能分析。如需引數的資訊,請參閱 :breakdel。範例
profdel func MyFunc
profdel file MyScript.vim
profdel here
您必須始終以「:profile start fname」指令開始。當 Vim 結束時,會寫入產生的檔案。例如,分析一個特定的函數
profile start /tmp/vimprofile
profile func MyFunc
以下是一個輸出範例,前面加上行號以進行說明
1 FUNCTION Test2()
2 Called 1 time
3 Total time: 0.155251
4 Self time: 0.002006
5
6 count total (s) self (s)
7 9 0.000096 for i in range(8)
8 8 0.153655 0.000410 call Test3()
9 8 0.000070 endfor
10 " Ask a question
11 1 0.001341 echo input("give me an answer: ")
標頭(第 1-4 行)提供整個函數的時間。「Total」時間是函數執行時經過的時間。「Self」時間是「Total」時間減去花費在以下的時間:
其他使用者定義的函數
載入的腳本
執行的自動指令
外部(shell)指令
第 7-11 行顯示在每條執行行中花費的時間。未執行的行不會計算。因此,註解行永遠不會計算。
Count 資料行顯示一行執行的次數。請注意,第 7 行中的「for」指令會比後續的行多執行一次。這是因為也執行該行來偵測迴圈的結束。
Vim 等待使用者輸入的時間根本不會計算在內。因此,您回應 input() 提示的時間長短無關緊要。
效能分析應能很好地指出時間花費在哪裡,但請記住,有些事情可能會破壞結果
測量的是實際經過的時間,如果其他處理程序處於忙碌狀態,則可能會在無法預測的時刻造成延遲。您可能想要多次執行效能分析並使用最低的結果。
如果您在一行中有數個指令,則只會取得一個時間。分割該行以查看個別指令的時間。
加總的行時間通常少於整個函數的時間。在兩者之間有一些額外負荷。
在 Vim 結束之前刪除的函數將不會產生效能分析資訊。如果需要,您可以檢查 v:profiling 變數
:if !v:profiling
:   delfunc MyFunc
:endif
當睡眠模式啟動或處理器頻率降低以節省電力時,效能分析在多處理器系統上可能會產生奇怪的結果。
當函數以遞迴方式使用時,「self」時間會錯誤。
編輯器狀態由「內容」概念表示。這包括目前的 跳躍清單暫存器的值,以及更多如下所述的內容。
內容類型
支援下列內容項目:「jumps」跳躍清單、「regs」暫存器、「bufs」緩衝區清單、「gvars」全域變數、「sfuncs」腳本局部函數、「funcs」全域和 腳本局部函數
內容字典
內容物件是具有下列鍵值組的字典
「jumps」、「regs」、「bufs」、「gvars」:對應 msgpack 物件的 readfile() 樣式 清單表示法(請參閱 msgpackdump()msgpackparse())。
「funcs」(包含script-local 函式):List:function 定義。
context-stack
由 ctx 系列函式維護一個初始為空的內部 Context 堆疊(參見ctx-functions)。
主要
指令索引
快速參考