Nvim 的 :help
頁面,是透過 產生 自 原始碼,並使用 tree-sitter-vimdoc 解析器。
{"blue": "#0000ff", "red": "#ff0000"} #{blue: "#0000ff", red: "#ff0000"}Blob:二進位大型物件。儲存任何位元組序列。詳情請見 Blob。範例:0zFF00ED015DAF 0z 是一個空的 Blob。
:echo "0100" + 0
:if "foo" :" NOT executed"foo" 會轉換為 0,表示 FALSE。如果字串是以非零數字開頭,則表示 TRUE
:if "8foo" :" executed要測試字串是否為空,請使用 empty()
:if !empty("foo")
:let Fn = function("MyFunc") :echo Fn()
:function dict.init() dict : let self.val = 0 :endfunction字典的鍵可以小寫字母開頭。此處不使用實際的函數名稱。另請參閱 numbered-function。
:call Fn() :call dict.init()可以使用 string() 取得被引用函數的名稱。
:let func = string(Fn)您可以使用 call() 來調用函數參考,並使用列表變數作為參數
:let r = call(Fn, mylist)
let Cb = function('Callback', ['foo'], myDict) call Cb('bar')這將調用該函數,如同使用
call myDict.Callback('foo', 'bar')請注意,當函數是字典的成員時,也會發生將函數綁定到字典的情況
let myDict.myFunction = MyFunction call myDict.myFunction()在這裡,MyFunction() 會將 myDict 作為 "self" 傳遞。當存取 "myFunction" 成員時,會發生這種情況。當將 "myFunction" 指派給 otherDict 並調用它時,它將會綁定到 otherDict
let otherDict.myFunction = myDict.myFunction call otherDict.myFunction()現在,"self" 將會是 "otherDict"。但是,當字典被明確綁定時,就不會發生這種情況
let myDict.myFunction = function(MyFunction, myDict) let otherDict.myFunction = myDict.myFunction call otherDict.myFunction()在這裡,"self" 將會是 "myDict",因為它是被明確綁定的。
:let mylist = [1, two, 3, "four"] :let emptylist = []項目可以是任何表達式。為項目使用列表會建立列表的列表
:let nestlist = [[11, 12], [21, 22], [31, 32]]最後一個項目之後的多餘逗號將被忽略。
:let item = mylist[0] " get the first item: 1 :let item = mylist[2] " get the third item: 3當結果項目為列表時,可以重複此操作
:let item = nestlist[0][1] " get the first list, second item: 12
:let last = mylist[-1] " get the last item: "four"為了避免因無效索引而產生錯誤,請使用 get() 函數。當項目不可用時,它會返回零或您指定的預設值
:echo get(mylist, idx) :echo get(mylist, idx, "NONE")
:let longlist = mylist + [5, 6] :let longlist = [5, 6] + mylist要前置或附加一個項目,請將其放入 [] 中以將其轉換為列表。
:let shortlist = mylist[2:-1] " get List [3, "four"]省略第一個索引與零相似。省略最後一個索引與 -1 相似。
:let endlist = mylist[2:] " from item 2 to the end: [3, "four"] :let shortlist = mylist[2:2] " List with one item: [3] :let otherlist = mylist[:] " make a copy of the List請注意,最後一個索引是包含在內的。如果您偏好使用排除性的索引,請使用 slice() 方法。
:let mylist = [0, 1, 2, 3] :echo mylist[2:8] " result: [2, 3]注意: mylist[s:e] 表示使用變數 "s:e" 作為索引。請注意在 ":" 之前使用單字母變數。在需要時插入空格:mylist[s : e]。
:let aa = [1, 2, 3] :let bb = aa :call add(aa, 4) :echo bb
:let aa = [[1, 'a'], 2, 3] :let bb = copy(aa) :call add(aa, 4) :let aa[0][1] = 'aaa' :echo aa
:echo bb
:let alist = [1, 2, 3] :let blist = [1, 2, 3] :echo alist is blist
:echo alist == blist
echo 4 == "4"
echo [4] == ["4"]
:let a = 5 :let b = "5" :echo a == b
:echo [a] == [b]
:let [var1, var2] = mylist當變數的數量與列表中項目的數量不符時,會產生錯誤。若要處理列表中任何額外的項目,請附加 ";" 和變數名稱。
:let [var1, var2; rest] = mylist這像這樣運作:
:let var1 = mylist[0] :let var2 = mylist[1] :let rest = mylist[2:]但如果只有兩個項目,則不會產生錯誤。"rest" 將會是一個空列表。
:let list[4] = "four" :let listlist[0][3] = item若要變更列表的一部分,您可以指定要修改的第一個和最後一個項目。該值必須至少具有範圍內的項目數量。
:let list[3:5] = [3, 4, 5]若要在列表中就地加入項目,您可以使用 :let+= ( 列表串接)
:let listA = [1, 2] :let listA += [3, 4]
:let listA = [1, 2] :let listB = listA :let listB += [3, 4] :echo listA [1, 2, 3, 4]
:call insert(list, 'a') " prepend item 'a' :call insert(list, 'a', 3) " insert item 'a' before list[3] :call add(list, "new") " append String item :call add(list, [1, 2]) " append a List as one new item :call extend(list, [1, 2]) " extend the list with two more items :let i = remove(list, 3) " remove item 3 :unlet list[3] " idem :let l = remove(list, 3, -1) " remove items 3 to last item :unlet list[3 : ] " idem :call filter(list, 'v:val !~ "x"') " remove items with an 'x'變更列表中項目的順序
:call sort(list) " sort a list alphabetically :call reverse(list) " reverse the order of items :call uniq(sort(list)) " sort and remove duplicates
:for item in mylist : call Doit(item) :endfor這像這樣運作:
:let index = 0 :while index < len(mylist) : let item = mylist[index] : :call Doit(item) : let index = index + 1 :endwhile如果您只想修改列表中的每個項目,則使用 map() 函數會比 for 迴圈更簡單。
:for [lnum, col] in [[1, 3], [2, 8], [3, 0]] : call Doit(lnum, col) :endfor這就像對每個列表項目執行 :let 命令一樣。同樣地,類型必須保持相同,以避免發生錯誤。
:for [i, j; rest] in listlist : call Doit(i, j) : if !empty(rest) : echo "remainder: " .. string(rest) : endif :endfor對於 Blob,則會一次使用一個位元組。
for c in text echo 'This character is ' .. c endfor
:let r = call(funcname, list) " call a function with an argument list :if empty(list) " check if list is empty :let l = len(list) " number of items in list :let big = max(list) " maximum value in list :let small = min(list) " minimum value in list :let xs = count(list, 'x') " count nr of times 'x' appears in list :let i = index(list, 'x') " index of first 'x' in list :let lines = getline(1, 10) " get ten text lines from buffer :call append('$', lines) " append text lines in buffer :let list = split("a b c") " create list from items in a string :let string = join(list, ', ') " create string from list items :let s = string(list) " String representation of list :call map(list, '">> " .. v:val') " prepend ">> " to each item別忘了功能的組合可以讓事情變得簡單。例如,若要將列表中的所有數字加總:
:exe 'let sum = ' .. join(nrlist, '+')
:let mydict = {1: 'one', 2: 'two', 3: 'three'} :let emptydict = {}
:let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3}請注意,此處的 333 是字串 "333"。#{} 不允許使用空的鍵。
:let nestdict = {1: {11: 'a', 12: 'b'}, 2: {21: 'c'}}最後一個項目之後的額外逗號會被忽略。
:let val = mydict["one"] :let mydict["four"] = 4您可以使用這種方式將新項目新增至現有的字典,這與列表不同。
:let val = mydict.one :let mydict.four = 4由於項目可以是任何類型,包括列表和字典,因此可以重複索引和鍵查找。
:echo dict.key[idx].key
:for key in keys(mydict) : echo key .. ': ' .. mydict[key] :endfor鍵列表是未排序的。您可能想要先排序它們:
:for key in sort(keys(mydict))若要對值進行迴圈,請使用 values() 函數:
:for v in values(mydict) : echo "value: " .. v :endfor如果您同時需要鍵和值,請使用 items() 函數。它會傳回一個列表,其中每個項目都是一個包含兩個項目的列表,即鍵和值。
:for [key, value] in items(mydict) : echo key .. ': ' .. value :endfor
:let onedict = {'a': 1, 'b': 2} :let adict = onedict :let adict['a'] = 11 :echo onedict['a'] 11如果所有鍵值對都相等,則兩個字典會被視為相等。如需更多資訊,請參閱 列表識別。
:let dict[4] = "four" :let dict['one'] = item從字典中移除項目是透過 remove() 或 :unlet 完成的。以下三種方法可以從字典中移除鍵為 "aaa" 的項目:
:let i = remove(dict, 'aaa') :unlet dict.aaa :unlet dict['aaa']將字典與另一個字典合併是透過 extend() 完成的:
:call extend(adict, bdict)這會將 bdict 中的所有項目擴充至 adict。重複的鍵會導致 adict 中的項目被覆寫。可選的第三個引數可以變更此行為。請注意,字典中項目的順序無關緊要,因此不要期望 ":echo adict" 會在 adict 中的舊項目之後顯示 bdict 中的項目。
:call filter(dict, 'v:val =~ "x"')這會從 "dict" 中移除所有值與 'x' 不符的項目。這也可以用來移除所有項目:
call filter(dict, 0)
:function Mylen() dict : return len(self.data) :endfunction :let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")} :echo mydict.len()這就像物件導向程式設計中的方法一樣。字典中的項目是 Funcref。局部變數 "self" 指的是從中調用函數的字典。
:let mydict = {'data': [0, 1, 2, 3]} :function mydict.len() : return len(self.data) :endfunction :echo mydict.len()然後函數會取得一個數字,而 dict.len 的值會是一個 Funcref,指向此函數。該函數只能透過 Funcref 使用。當沒有任何 Funcref 指向它時,它會自動刪除。
:function g:42
:if has_key(dict, 'foo') " TRUE if dict has entry with key "foo" :if empty(dict) " TRUE if dict is empty :let l = len(dict) " number of items in dict :let big = max(dict) " maximum value in dict :let small = min(dict) " minimum value in dict :let xs = count(dict, 'x') " count nr of times 'x' appears in dict :let s = string(dict) " String representation of dict :call map(dict, '">> " .. v:val') " prepend ">> " to each item
:let b = 0zFF00ED015DAF為了提高可讀性,可以在位元組之間(成對的十六進位字元)插入點號,它們不會變更值:
:let b = 0zFF00.ED01.5DAF可以使用 readfile() 從檔案讀取 blob,例如,將
{type}
引數設定為 "B"::let b = readfile('image.png', 'B')
:let myblob = 0z00112233 :let byte = myblob[0] " get the first byte: 0x00 :let byte = myblob[2] " get the third byte: 0x22負索引從末尾開始計算。索引 -1 指的是 Blob 中的最後一個位元組,-2 指的是倒數第二個位元組,依此類推。
:let last = myblob[-1] " get the last byte: 0x33若要避免無效索引的錯誤,請使用 get() 函數。當項目不可用時,它會傳回 -1 或您指定的預設值:
:echo get(myblob, idx) :echo get(myblob, idx, 999)
:for byte in 0z112233 : call Doit(byte) :endfor這會使用 0x11、0x22 和 0x33 呼叫 Doit()。
:let longblob = myblob + 0z4455 :let longblob = 0z4455 + myblob
:let myblob += 0z6677
:let myblob = 0z00112233 :let shortblob = myblob[1:2] " get 0z1122 :let shortblob = myblob[2:-1] " get 0z2233省略第一個索引與零相似。省略最後一個索引與 -1 相似。
:let endblob = myblob[2:] " from item 2 to the end: 0z2233 :let shortblob = myblob[2:2] " Blob with one byte: 0z22 :let otherblob = myblob[:] " make a copy of the Blob如果第一個索引超出 Blob 的最後一個位元組,或者第二個索引在第一個索引之前,則結果為空的 Blob。沒有錯誤訊息。
:echo myblob[2:8] " result: 0z2233
:let blob[4] = 0x44當索引剛好超出 Blob 的末尾一個時,則會附加它。任何更高的索引都會產生錯誤。
let blob[1:3] = 0z445566取代的位元組長度必須與提供的值完全相同。E972
:let blob[3:5] = 0z334455若要就地將項目新增至 Blob,您可以使用 :let+= (blob 連接)
:let blobA = 0z1122 :let blobA += 0z3344
:let blobA = 0z1122 :let blobB = blobA :let blobB += 0z3344 :echo blobA 0z11223344
if blob == 0z001122以及是否具有相同的識別
if blob is otherblob
:let blob = 0z112233 :let blob2 = blob :echo blob == blob2
:echo blob is blob2
:let blob3 = blob[:] :echo blob == blob3
:echo blob is blob3
'字串'
字串常數,' 加倍 [expr1, ...] List {expr1: expr1, ...}
Dictionary #{key: expr1, ...} Dictionary &選項 選項值 (expr1) 巢狀表達式 變數 內部變數 va{ria}ble 帶有大括號的內部變數 $VAR 環境變數 @r 暫存器 "r" 的內容 function(expr1, ...) 函式呼叫 func{ti}on(expr1, ...) 帶有大括號的函式呼叫 {args -> expr1}
lambda 表達式&nu || &list && &shell == "csh"同一層級內的所有表達式都會從左到右解析。
:echo lnum == 1 ? "top" : lnum由於第一個表達式是 "expr2",因此它不能包含另一個 ?:。其他兩個表達式可以,因此允許遞迴使用 ?:。範例
:echo lnum == 1 ? "top" : lnum == 1000 ? "last" : lnum為了保持可讀性,建議使用 行接續
:echo lnum == 1 :\ ? "top" :\ : lnum == 1000 :\ ? "last" :\ : lnum您應該始終在 ':' 前面放置一個空格,否則可能會誤認為是用於變數(例如 "a:1")中。
echo theList ?? 'list is empty' echo GetName() ?? 'unknown'這些相似,但不相等
expr2 ?? expr1 expr2 ? expr2 : expr1在第二行中,"expr2" 會被評估兩次。
&nu || &list && &shell == "csh"請注意,"&&" 的優先順序高於 "||",因此這表示
&nu || (&list && &shell == "csh")一旦結果已知,表達式就會「短路」,也就是說,不會評估其他引數。這就像 C 中發生的情況一樣。例如
let a = 1 echo a || b即使沒有名為 "b" 的變數,這也是有效的,因為 "a" 是 TRUE,因此結果必須是 TRUE。類似地,如下
echo exists("b") && b == "yes"無論是否已定義 "b",這都是有效的。只有在已定義 "b" 的情況下才會評估第二個子句。
{cmp}
expr5if get(Part1, 'name') == get(Part2, 'name') " Part1 and Part2 refer to the same function將 "是" 或 "不是" 用於 列表、字典 或 Blob 會檢查表達式是否指向相同的 列表、字典 或 Blob 實例。列表的副本與原始 列表 不同。當在未使用 列表、字典 或 Blob 的情況下使用 "是" 時,它等同於使用 "等於",使用 "不是" 等同於使用 "不等於"。但不同的類型表示值不同
echo 4 == '4' 1 echo 4 is '4' 0 echo 0 is [] 0"is#"/ "isnot#" 和 "is?"/ "isnot?" 可用於匹配並忽略大小寫。
echo 0 == 'x' 1因為 'x' 轉換為數字是零。然而
echo [0] == ['x'] 0在列表或字典中,不會使用此轉換。
1 . 90 + 90.0作為
(1 . 90) + 90.0這有效,因為字串 "190" 會自動轉換為數字 190,可以將其加到浮點數 90.0。然而
1 . 90 * 90.0應讀取為
1 . (90 * 90.0)因為 '.' 的優先順序低於 "*"。這不起作用,因為這嘗試將浮點數和字串連接。
byteidx()
以取得替代方法,或者使用 split()
將字串轉換為字元列表。範例,取得游標下的位元組:let c = getline(".")[col(".") - 1]索引零會提供第一個位元組。這類似於 C 中的工作方式。請注意:文字欄位數字從一開始!範例,取得游標下的位元組
:let c = getline(".")[col(".") - 1]索引零會提供第一個位元組。請注意:文字欄位數字從一開始!
:let item = mylist[-1] " get last item通常,如果 列表索引等於或高於 列表的長度,或者比 列表的長度更負,則會產生錯誤。
:let c = name[-1:] " last byte of a string :let c = name[0:-1] " the whole string :let c = name[-2:-2] " last but one byte of a string :let s = line(".")[4:] " from the fifth byte to the end :let s = s[:-3] " remove last two bytes
:let l = mylist[:3] " first four items :let l = mylist[4:4] " List with one item :let l = mylist[:] " shallow copy of a List如果 expr8 是 Blob,則結果會是一個新的 Blob,其中包含索引 expr1a 和 expr1b 中的位元組(包含)。範例
:let b = 0zDEADBEEF :let bs = b[1:2] " 0zADBE :let bs = b[] " copy of 0zDEADBEEF在 函式參照上使用 expr8[expr1] 或 expr8[expr1a : expr1b] 會產生錯誤。
mylist[n:] " uses variable n mylist[s:] " uses namespace s:, error!expr8.name 在字典中的條目 expr-entry
:let dict = {"one": 1, 2: "two"} :echo dict.one " shows "1" :echo dict.2 " shows "two" :echo dict .2 " error because of space before the dot請注意,點號也用於字串串接。為避免混淆,請始終在字串串接的點號周圍加上空格。
mylist->filter(filterexpr)->map(mapexpr)->sort()->join()
GetPercentage()->{x -> x * 100}()->printf('%d%%')
mylist \ ->filter(filterexpr) \ ->map(mapexpr) \ ->sort() \ ->join()當使用 lambda 形式時,} 和之間不得有空白字元
{N}
和 {M}
是數字。{N}
和 {M}
都必須存在,且只能包含數字。[-+] 表示有一個可選的正負號。{exp}
是指數,即 10 的冪次方。只接受小數點,不接受逗號。無論目前的地區設定是什麼。{M}
1e40 缺少 .{M}:let pi = 3.14159265359 :let e = 2.71828182846或者,如果您不想將它們寫成浮點字面值,您也可以使用函式,如下所示
:let pi = acos(-1.0) :let e = exp(1.0)
:echo printf('%.15e', atan(1))
<BS>
\e 跳脫 <Esc>
\f 換頁 0x0C \n 換行 <NL>
\r 返回 <CR>
\t 跳格 <Tab>
\\ 反斜線 \" 雙引號 \<xxx> 名為 "xxx" 的特殊鍵。例如,CTRL-W
的 "\<C-W>"。這用於對應中,0x80 位元組會被跳脫。要使用雙引號字符,必須將其跳脫: "<M-\">"。請勿使用 <Char-xxxx>
來取得 UTF-8 字符,請使用如上所述的 \uxxxx。\<*xxx> 與 \<xxx> 類似,但會加上修飾符,而不是將其包含在字符中。例如,"\<C-w>" 是一個字符 0x17,而 "\<*C-w>" 是四個位元組:3 個用於 CTRL 修飾符,然後是字符 "W"。:let b = 0zFF00ED015DAF
if a =~ "\\s*" if a =~ '\s*'
let your_name = input("What's your name? ")
echo echo $"Hello, {your_name}!"
echo $"The square root of {{9}} is {sqrt(9)}"
{9}
的平方根是 3.0echo "tabstop is " .. &tabstop if &expandtab此處可以使用任何選項名稱。請參閱 選項。當使用局部值且沒有緩衝區局部值或視窗局部值時,仍會使用全域值。
getenv()
和 setenv()
也可以使用,並且適用於具有非字母數字名稱的環境變數。函式 environ()
可用於取得包含所有環境變數的字典。:echo $shell :echo expand("$shell")第一個可能不會 echo 任何東西,第二個會 echo $shell 變數(如果您的 shell 支援)。
:let F = {arg1, arg2 -> arg1 - arg2} :echo F(5, 2)
:let F = {-> 'error function'} :echo F('ignored')
:function Foo(arg) : let i = 3 : return {x -> x + i - a:arg} :endfunction :let Bar = Foo(4) :echo Bar(6)
if has('lambda')將 Lambda 表達式與 sort()、map() 和 filter() 一起使用的範例
:echo map([1, 2, 3], {idx, val -> val + 1})
:echo sort([3,7,2,1,4], {a, b -> a - b})
:let timer = timer_start(500, \ {-> execute("echo 'Handler called'", "")}, \ {'repeat': 3})
function Function() let x = 0 let F = {-> x} endfunction閉包使用函式範圍中的 "x",而同一個範圍中的 "F" 引用閉包。這種循環會導致記憶體無法釋放。建議:不要這樣做。
<lambda>
42' 的內部名稱。如果您的 Lambda 表達式發生錯誤,您可以使用以下命令找出它是什麼:function <lambda>42另請參閱:numbered-function
:for k in keys(s:) : unlet s:[k] :endfor
:if my_changedtick != b:changedtick : let my_changedtick = b:changedtick : call My_Update() :endif
let s:counter = 0 function MyCounter() let s:counter = s:counter + 1 echo s:counter endfunction command Tick call MyCounter()您現在可以從任何腳本中調用 "Tick",該腳本中的 "s:counter" 變數不會變更,只會使用定義 "Tick" 的腳本中的 "s:counter"。
let s:counter = 0 command Tick let s:counter = s:counter + 1 | echo s:counter當呼叫函式並調用使用者定義命令時,腳本變數的內容會設定為定義函式或命令的腳本。
let s:counter = 0 function StartCounting(incr) if a:incr function MyCounter() let s:counter = s:counter + 1 endfunction else function MyCounter() let s:counter = s:counter - 1 endfunction endif endfunction這會在呼叫 StartCounting() 時,定義用於向上計數或向下計數的 MyCounter() 函式。從何處呼叫 StartCounting() 並不重要,s:counter 變數在 MyCounter() 中是可存取的。
if !exists("s:counter") let s:counter = 1 echo "script executed for the first time" else let s:counter = s:counter + 1 echo "script executed " .. s:counter .. " times now" endif請注意,這表示檔案類型外掛程式不會為每個緩衝區取得不同的腳本變數集。請改用區域緩衝區變數 b:var。
my_{adjective}_variable當 Vim 遇到此情況時,它會評估大括號內的表達式,將其放置在表達式的位置,然後將整個內容重新解讀為變數名稱。因此,在上面的範例中,如果變數 "adjective" 設定為 "noisy",則參考將會是 "my_noisy_variable",而如果 "adjective" 設定為 "quiet",則參考將會是 "my_quiet_variable"。
echo my_{&background}_message會根據 'background' 的目前值,輸出 "my_dark_message" 或 "my_light_message" 的內容。
echo my_{adverb}_{adjective}_message..甚至可以巢狀它們
echo my_{ad{end_of_word}}_message其中 "end_of_word" 是 "verb" 或 "jective"。
:let foo='a + b' :echo c{foo}d.. 因為展開的結果是 "ca + bd",這不是一個變數名稱。
:let func_end='whizz' :call my_func_{func_end}(parameter)這會呼叫函數 "my_func_whizz(parameter)"。
:let i = 3 :let @{i} = '' " error :echo @{i} " error
{var-name}
= {expr1}
:let E18 將內部變數 {var-name}
設定為表達式 {expr1}
的結果。變數將從 {expr}
取得類型。如果 {var-name}
尚不存在,則會建立它。{var-name}
[{idx}
] = {expr1}
E689{expr1}
的結果。{var-name}
必須參照到一個列表,並且 {idx}
必須是該列表中有效的索引。對於巢狀列表,可以重複使用索引。這不能用於將項目新增至 列表。這不能用於設定字串中的位元組。您可以這樣做::let var = var[0:2] .. 'X' .. var[4:]
{var-name}
[{idx1}
:{idx2}
] = {expr1}
E708 E709 E710 將 列表中的一系列項目設定為表達式 {expr1}
的結果,此表達式必須是一個具有正確項目數的列表。{idx1}
可以省略,改用零。{idx2}
可以省略,表示列表的結尾。當選取的項目範圍部分超過列表的結尾時,將會新增項目。{var}
+= {expr1}
類似於 ":let {var}
= {var}
+ {expr1}
"。 :let {var}
-= {expr1}
類似於 ":let {var}
= {var}
- {expr1}
"。 :let {var} *= {expr1}
類似於 ":let {var}
= {var}
* {expr1}
"。 :let {var}
/= {expr1}
類似於 ":let {var}
= {var}
/ {expr1}
"。 :let {var}
%= {expr1}
類似於 ":let {var}
= {var}
% {expr1}
"。 :let {var}
.= {expr1}
類似於 ":let {var}
= {var}
. {expr1}
"。 :let {var}
..= {expr1}
類似於 ":let {var}
= {var}
.. {expr1}
"。如果 {var}
尚未設定,且 {var}
和 {expr1}
的類型不符合運算符,這些操作將會失敗。+=
會就地修改 列表或 Blob,而不是建立新的。{expr1}
:let-environment :let-$ 將環境變數 {env-name}
設定為表達式 {expr1}
的結果。類型始終為字串。 :let ${env-name} .= {expr1}
將 {expr1}
附加到環境變數 {env-name}
。如果環境變數尚不存在,則此操作的作用類似於 "="。{expr1}
:let-register :let-@ 將表達式 {expr1}
的結果寫入暫存器 {reg-name}
。{reg-name}
必須是單個字母,並且必須是可寫入暫存器的名稱(請參閱 registers)。"@@" 可以用於未命名的暫存器,"@@/" 用於搜尋模式。如果 {expr1}
的結果以 <CR>
或 <NL>
結尾,則暫存器將會是行式,否則將會設定為字元式。這可用於清除最後的搜尋模式。:let @/ = ""
{expr1}
將 {expr1}
附加到暫存器 {reg-name}
。如果暫存器為空,則其作用類似於將其設定為 {expr1}
。{expr1}
:let-option :let-& 將選項 {option-name}
設定為表達式 {expr1}
的結果。字串或數字值始終會轉換為選項的類型。對於視窗或緩衝區本機的選項,其效果與使用 :set 指令相同:本機值和全域值都會變更。範例::let &path = &path .. ',/usr/local/include':let &{option-name} .=
{expr1}
對於字串選項:將 {expr1}
附加到值。不會像 :set+= 一樣插入逗號。{expr1}
:let &{option-name} -= {expr1}
對於數字或布林選項:加或減 {expr1}
。{expr1}
:let &l:{option-name} .= {expr1}
:let &l:{option-name} += {expr1}
:let &l:{option-name} -= {expr1}
與上述相同,但僅設定選項的本機值(如果有的話)。作用類似於 :setlocal。{expr1}
:let &g:{option-name} .= {expr1}
:let &g:{option-name} += {expr1}
:let &g:{option-name} -= {expr1}
與上述相同,但僅設定選項的全域值(如果有的話)。作用類似於 :setglobal。{name1}
, {name2}
, ...] = {expr1}
:let-unpack E687 E688 {expr1}
的計算結果必須為 列表。列表中的第一個項目會指派給 {name1}
,第二個項目指派給 {name2}
,依此類推。名稱的數量必須與 列表中的項目數量相符。每個名稱可以是上述 ":let" 指令的項目之一。範例::let [s, item] = GetItem(s)
{expr1}
,然後依序執行指派。如果 {name2}
依賴於 {name1}
,這點很重要。範例::let x = [0, 1] :let i = 0 :let [i, x[i]] = [1, 2] :echo x
{name1}
, {name2}
, ...] .= {expr1}
:let [{name1}
, {name2}
, ...] += {expr1}
:let [{name1}
, {name2}
, ...] -= {expr1}
與上述相同,但為每個 列表項目附加/加/減該值。{name}
, ..., ; {lastname}
] = {expr1}
E452{lastname}
。如果沒有剩餘項目,則 {lastname}
會設定為空列表。範例::let [a, b; rest] = ["aval", "bval", 3, 4]
{name}
, ..., ; {lastname}
] .= {expr1}
:let [{name}
, ..., ; {lastname}
] += {expr1}
:let [{name}
, ..., ; {lastname}
] -= {expr1}
與上述相同,但為每個 列表項目附加/加/減該值。{var-name}
=<< [trim] [eval] {endmarker}
text... text... {endmarker}
將內部變數 {var-name}
設定為 列表,其中包含由字串 {endmarker}
界定的文字行。{expr}
形式的 Vim 表達式,並且結果會取代該表達式,類似於使用 interpolated-string。以下範例會展開 $HOME:let lines =<< trim eval END some text See the file {$HOME}/.vimrc more text END
{endmarker}
不得包含空白字元。{endmarker}
不能以小寫字元開頭。最後一行應僅以 {endmarker}
字串結尾,而沒有任何其他字元。請注意 {endmarker}
後面的空白!{endmarker}
之前指定了 "trim",則會移除縮排,因此您可以執行let text =<< trim END if ok echo 'done' endif END
["if ok", " echo 'done'", "endif"]
標記必須與 "let" 對齊,並且會從所有文字行中移除第一行的縮排。具體來說:會從輸入行中移除所有與第一個非空白文字行開頭縮排完全符合的前導縮排。會從包含 {endmarker}
的行中移除與 `let` 前面的前導縮排完全符合的所有前導縮排。請注意,這裡空格和 Tab 鍵之間的差異很重要。{var-name}
尚不存在,則會建立它。後面不能接其他指令,但是可以接註解。set cpo+=C let var =<< END \ leading backslash END set cpo-=C
let var1 =<< END Sample text 1 Sample text 2 Sample text 3 END let data =<< trim DATA 1 2 3 4 5 6 7 8 DATA let code =<< trim eval CODE let v = {10 + 20} let h = "{$HOME}" let s = "{Str1()} abc {Str2()}" let n = {MyFunc(3, 4)} CODE
{var-name}
.. 列出變數 {var-name}
的值。可以給定多個變數名稱。此處識別的特殊名稱:E738<nothing>
字串 # 數字 * Funcref{name}
... :unlet :unl E108 E795 移除內部變數 {name}
。可以給定數個變數名稱,它們都會被移除。名稱也可以是 列表或 字典項目。使用 [!],如果變數不存在,則不會給出錯誤訊息。可以移除 列表中的一或多個項目。:unlet list[3] " remove fourth item :unlet list[3:] " remove fourth item to last
:unlet dict['two'] :unlet dict.two
{env-name}
。可以在一個 :unlet 指令中混用 {name}
和 ${env-name}。對於不存在的變數,不會給出錯誤訊息,即使沒有 ! 也一樣。如果系統不支援刪除環境變數,則會將其設為空。{var-name}
= {expr1}
:cons[t] [{name1}
, {name2}
, ...] = {expr1}
:cons[t] [{name}
, ..., ; {lastname}
] = {expr1}
:cons[t] {var-name}
=<< [trim] [eval] {marker}
text... text... {marker}
類似於 :let,但額外會在設定值後鎖定變數。這等同於在 :let 之後立即使用 :lockvar 鎖定變數,因此:const x = 1
:let x = 1 :lockvar! x
const ll = [1, 2, 3] let ll[1] = 5 " Error!
let lvar = ['a'] const lconst = [0, lvar] let lconst[0] = 2 " Error! let lconst[1][0] = 'b' " OK
{name}
... :lockvar :lockv 鎖定內部變數 {name}
。鎖定表示它不能再被更改(直到它被解除鎖定)。已鎖定的變數可以被刪除:lockvar v :let v = 'asdf' " fails! :unlet v " works
{name}
」。如果您嘗試鎖定或解除鎖定內建變數,會收到錯誤訊息:「E940: Cannot lock or unlock variable {name}
」。{name}
,但不鎖定其值。1 鎖定 列表 或 字典 本身,無法新增或移除項目,但仍然可以變更其值。2 也鎖定值,無法變更項目。如果某個項目是 列表 或 字典,則無法新增或移除項目,但仍然可以變更其值。3 與 2 類似,但針對 列表 / 字典 中的 列表 / 字典,再深入一層。預設的 [depth] 是 2,因此當 {name}
是 列表 或 字典 時,其值無法被變更。let mylist = [1, 2, 3] lockvar 0 mylist let mylist[0] = 77 " OK call add(mylist, 4) " OK let mylist = [7, 8, 9] " Error!
:let l = [0, 1, 2, 3] :let cl = l :lockvar l :let cl[1] = 99 " won't work!
{name}
不存在,則不會給出錯誤訊息。{expr1}
:if :end :endif :en E171 E579 E580 :en[dif] 如果 {expr1}
的計算結果為非零值,則執行指令直到下一個匹配的 :else
或 :endif
。雖然可以使用簡短形式,但建議始終使用 :endif
以避免混淆,並使自動縮排正常工作。:if
和 :endif
之間的每個 Ex 指令都會被忽略。這兩個指令只是為了以向後相容的方式允許未來的擴展。允許巢狀結構。請注意,任何 :else
或 :elseif
都會被忽略,else
部分也不會被執行。:if version >= 500 : version-5-specific-commands :endif
endif
。有時,舊版本的 Vim 會遇到新指令的問題。例如,:silent
被識別為 :substitute
指令。在這種情況下,:execute
可以避免問題:if version >= 600 : execute "silent 1,$delete" :endif
:append
和 :insert
指令在 :if
和 :endif
之間無法正常工作。{expr1}
:while :endwhile :wh :endw E170 E585 E588 E733 :endw[hile] 重複執行 :while
和 :endwhile
之間的指令,只要 {expr1}
的計算結果為非零值。當在迴圈內的指令中偵測到錯誤時,執行會繼續在 endwhile
之後。範例:let lnum = 1 :while lnum <= line("$") :call FixLine(lnum) :let lnum = lnum + 1 :endwhile
:append
和 :insert
指令在 :while
和 :for
迴圈內無法正常工作。{var}
in {object}
:for E690 E732 :endfo[r] :endfo :endfor 對於 {object}
中的每個項目,重複執行 :for
和 :endfor
之間的指令。{object}
可以是 列表、Blob 或 字串。{var}
設定為每個項目的值。endfor
之後。在迴圈內更改 {object}
會影響使用的項目。如果不需要這樣,請建立副本:for item in copy(mylist)
{object}
是 列表 且未建立副本時,Vim 會在執行具有目前項目的指令之前,儲存對 列表 中下一個項目的參考。因此,可以移除目前項目而不會產生影響。移除任何後續項目意味著不會找到它。因此,以下範例有效(一種效率低下的清空 列表 的方法)for item in mylist call remove(mylist, 0) endfor
{object}
是 字串 時,每個項目都是一個包含一個字元的字串,外加任何組合字元。{var1}
, {var2}
, ...] in {listlist}
:endfo[r] 與上面的 :for
類似,但 {listlist}
中的每個項目都必須是一個列表,其中每個項目都會被指派給 {var1}
、{var2}
等。範例:for [lnum, col] in [[1, 3], [2, 5], [3, 8]] :echo getline(lnum)[col] :endfor
:try
之後,但在匹配的 :finally
之前(如果存在)使用,則會先執行 :finally
之後直到匹配的 :endtry
的指令。此過程適用於迴圈內的所有巢狀 :try
。最外層的 :endtry
然後跳回迴圈的開頭。:while
或 :for
迴圈內使用時,會跳到匹配的 :endwhile
或 :endfor
之後的指令。如果在迴圈內的 :try
之後,但在匹配的 :finally
之前(如果存在)使用,則會先執行 :finally
之後直到匹配的 :endtry
的指令。此過程適用於迴圈內的所有巢狀 :try
。最外層的 :endtry
然後跳到迴圈之後的指令。:try
和 :endtry
之間的指令的錯誤處理,包括跨 :source
指令、函式呼叫或自動指令調用的所有執行動作。:finally
指令時,執行會繼續在 :finally
之後。否則,或當之後到達 :endtry
時,會檢查下一個(動態)周圍的 :try
是否有對應的 :finally
等。然後腳本處理會終止。函式定義是否具有「abort」參數並不重要。範例try | call Unknown() | finally | echomsg "cleanup" | endtry echomsg "not reached"
:try
和 :endtry
內(動態)的錯誤或中斷會轉換為例外。它可以像被 :throw
指令拋出一樣被捕獲(請參閱 :catch
)。在這種情況下,腳本處理不會終止。{command}
):{errmsg}」形式的值,其他錯誤會轉換為「Vim:{errmsg}」形式的值。{command}
是完整的指令名稱,而 {errmsg}
是如果未捕獲錯誤例外時顯示的訊息,始終以錯誤編號開頭。範例try | sleep 100 | catch /^Vim:Interrupt$/ | endtry try | edit | catch /^Vim(edit):E\d\+/ | echo "error" | endtry
{pattern}
的例外,並且尚未被先前的 :catch
捕獲時,會執行以下指令,直到與 :catch
屬於同一個 :try
的下一個 :catch
、:finally
或 :endtry
。否則,這些指令會被跳過。當省略 {pattern}
時,會捕獲所有錯誤。範例:catch /^Vim:Interrupt$/ " catch interrupts (CTRL-C) :catch /^Vim\%((\a\+)\)\=:E/ " catch all Vim errors :catch /^Vim\%((\a\+)\)\=:/ " catch errors and interrupts :catch /^Vim(write):/ " catch all errors in :write :catch /^Vim\%((\a\+)\)\=:E123:/ " catch error E123 :catch /my-exception/ " catch user exception :catch /.*/ " catch everything :catch " same as /.*/
{pattern}
周圍的 /,只要它沒有特殊含義(例如「|」或「"」)且不會出現在 {pattern}
內部。關於例外的資訊,請參閱 v:exception。另請參閱 throw-variables。 注意: 「:catch」錯誤訊息的文字並不可靠,因為它在不同的地區設定中可能會有所不同。:try
和 :finally
之間的部分離開時,就會執行直到符合的 :endtry
為止的以下命令:無論是直接執行到 :finally
,或是透過 :continue
、:break
、:finish
或 :return
,或透過錯誤、中斷或例外(請參閱 :throw
)。{expr1}
會評估 {expr1}
並將其擲出為例外。如果 :throw
是在 :try
之後但在第一個對應的 :catch
之前使用,則會略過命令,直到到達第一個符合 {expr1}
的 :catch
為止。如果沒有這樣的 :catch
,或如果 :throw
是在 :catch
之後但在 :finally
之前使用,則會執行 :finally
(如果存在)之後直到符合的 :endtry
為止的命令。如果 :throw
是在 :finally
之後,則會略過直到 :endtry
為止的命令。在 :endtry
時,這個程序會針對下一個動態包圍的 :try
再次套用(可能會在呼叫函數或來源指令碼中找到),直到找到符合的 :catch
為止。如果未捕獲例外,則會終止命令處理。範例:try | throw "oops" | catch /^oo/ | echo "caught" | endtry
{expr1}
.. 顯示每個 {expr1}
,中間以空格分隔。第一個 {expr1}
從新的一行開始。另請參閱 :comment。使用「\n」開始新的一行。使用「\r」將游標移動到第一欄。使用 :echohl
命令設定的醒目提示。後面不能接註解。範例:echo "the value of 'shell' is" &shell
:echo
之前的命令導致之後重新繪製(重新繪製通常會延後到您輸入內容),請使用 :redraw
命令強制重新繪製。範例:new | redraw | echo "there is a new window"
:let l = [] :call add(l, l) :let l2 = [] :call add(l2, [l2]) :echo l l2
{expr1}
.. 顯示每個 {expr1}
,不新增任何內容。另請參閱 :comment。使用 :echohl
命令設定的醒目提示。後面不能接註解。範例:echon "the value of 'shell' is " &shell
:echo
(Vim 命令) 和 :!echo
(外部 Shell 命令) 之間的不同:!echo % --> filename
:!echo "%" --> filename or "filename"
:echo % --> nothing
:echo "%" --> %
:echo expand("%") --> filename
{name}
對於接下來的 :echo
、:echon
和 :echomsg
命令,使用醒目提示群組 {name}
。也用於 input()
提示。範例:echohl WarningMsg | echo "Don't panic!" | echohl None
{expr1}
.. 以真實訊息的方式顯示運算式,將訊息儲存在 message-history 中。如同 :echo
命令,引數之間會放置空格。但是會顯示不可列印的字元,而不是解譯。剖析的運作方式與 :echo
略有不同,比較像是 :execute
。所有運算式都會先評估並串連,然後才會顯示任何內容。如果運算式未評估為數字或字串,則會使用 string() 將其轉換為字串。使用 :echohl
命令設定的醒目提示。範例:echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see."
{expr1}
.. 以錯誤訊息的方式顯示運算式,將訊息儲存在 message-history 中。在指令碼或函數中使用時,會新增行號。如同 :echomsg
命令,引數之間會放置空格。在 try 條件式內使用時,會改為引發訊息作為錯誤例外(請參閱 try-echoerr)。範例:echoerr "This script just failed!"
:echohl
。而若要發出嗶聲:exe "normal \<Esc>"
append()
呼叫會將具有文字的 List 附加到緩衝區。這與 :call
類似,但適用於任何運算式。:ev
或 :eva
,但這些很難辨識,因此不應使用。{expr1}
.. 將評估 {expr1}
所產生的字串當作 Ex 命令執行。多個引數會串連,中間以空格分隔。若要避免額外的空格,請使用「..」運算子將字串串連成一個引數。{expr1}
會當作已處理的命令使用,不辨識命令列編輯索引鍵。後面不能接註解。範例:execute "buffer" nextbuf :execute "normal" count .. "w"
:execute '!ls' | echo "theend"
:execute "normal ixxx\<Esc>"
<Esc>
字元,請參閱 expr-string。:execute "e " .. fnameescape(filename) :execute "!ls " .. shellescape(filename, 1)
:if 0 : execute 'while i > 5' : echo "test" : endwhile :endif
:execute 'while i < 5 | echo i | let i = i + 1 | endwhile'
:echo "foo" | "this is a comment
:try : ... : ... TRY BLOCK : ... :catch /{pattern}/ : ... : ... CATCH CLAUSE : ... :catch /{pattern}/ : ... : ... CATCH CLAUSE : ... :finally : ... : ... FINALLY CLAUSE : ... :endtrytry 條件式允許觀察程式碼中的例外,並採取適當的動作。可以捕獲 try 區塊中的例外。try 區塊以及 catch 子句中的例外可能會導致清除動作。當 try 區塊執行期間未擲出任何例外時,控制會轉移到 finally 子句(如果存在)。執行後,指令碼會從「:endtry」後面的行繼續。當 try 區塊執行期間發生例外時,會略過 try 區塊中剩餘的行。例外會與指定為「:catch」命令引數的模式比對。會採用第一個符合的「:catch」之後的 catch 子句,而不會執行其他 catch 子句。當到達下一個「:catch」、「:finally」或「:endtry」命令時,catch 子句會結束,無論哪一個先到。然後,會執行 finally 子句(如果存在)。當到達「:endtry」時,指令碼會像平常一樣在下一行繼續執行。當在 try 區塊中擲出不符合「:catch」命令所指定之任何模式的例外時,該例外不會被該 try 條件式捕獲,也不會執行任何 catch 子句。只會採用 finally 子句(如果存在)。例外會在執行 finally 子句期間擱置。它會在「:endtry」處恢復,以便不會執行「:endtry」之後的命令,而且可能會在其他地方捕獲例外,請參閱 try-nesting。當在執行 catch 子句期間擲出另一個例外時,不會執行該 catch 子句中剩餘的行。新的例外不會與相同 try 條件式之任何「:catch」命令中的模式比對,也不會採用其任何 catch 子句。但是,如果存在 finally 子句,則會執行該子句,並且例外會在執行期間擱置。不會執行「:endtry」之後的命令。但是,可能會在其他地方捕獲新的例外,請參閱 try-nesting。當在執行 finally 子句(如果存在)期間擲出例外時,會略過 finally 子句中剩餘的行。如果 finally 子句是因為 try 區塊或其中一個 catch 子句的例外而採用,則會捨棄原始(擱置)的例外。不會執行「:endtry」之後的命令,而且會傳播 finally 子句中的例外,並可以在其他地方捕獲,請參閱 try-nesting。
:throw 4711 :throw "string"
:throw 4705 + strlen("string") :throw strpart("strings", 0, 6)在評估 ":throw" 命令的引數期間,可能會拋出例外。除非在那裡捕獲例外,否則會放棄運算式評估。然後,":throw" 命令不會拋出新的例外。範例
:function! Foo(arg) : try : throw a:arg : catch /foo/ : endtry : return 1 :endfunction : :function! Bar() : echo "in Bar" : return 4710 :endfunction : :throw Foo("arrgh") + Bar()這會拋出 "arrgh",並且不會顯示 "in Bar",因為 Bar() 不會被執行。
:throw Foo("foo") + Bar()但是會顯示 "in Bar" 並拋出 4711。
:if Foo("arrgh") : echo "then" :else : echo "else" :endif這裡 "then" 或 "else" 都沒有顯示。
:function! Foo(value) : try : throw a:value : catch /^\d\+$/ : echo "Number thrown" : catch /.*/ : echo "String thrown" : endtry :endfunction : :call Foo(0x1267) :call Foo('string')第一次呼叫 Foo() 會顯示 "Number thrown",第二次會顯示 "String thrown"。例外會按照指定的順序與 ":catch" 命令比對。只有第一個相符項目會被計算。因此,您應該將更具體的 ":catch" 放在前面。以下順序沒有意義
: catch /.*/ : echo "String thrown" : catch /^\d\+$/ : echo "Number thrown"這裡的第一個 ":catch" 永遠匹配,因此永遠不會採用第二個 catch 子句。
: catch /^\d\+$/ : echo "Number thrown. Value is" v:exception您可能也會對拋出例外的位置感興趣。這會儲存在 v:throwpoint 中。請注意,只要例外未完成,"v:exception" 和 "v:throwpoint" 對於最近捕獲的例外都是有效的。範例
:function! Caught() : if v:exception != "" : echo 'Caught "' .. v:exception .. '" in ' .. v:throwpoint : else : echo 'Nothing caught' : endif :endfunction : :function! Foo() : try : try : try : throw 4711 : finally : call Caught() : endtry : catch /.*/ : call Caught() : throw "oops" : endtry : catch /.*/ : call Caught() : finally : call Caught() : endtry :endfunction : :call Foo()這會顯示
Nothing caught Caught "4711" in function Foo, line 4 Caught "oops" in function Foo, line 10 Nothing caught一個實際範例:以下命令 ":LineNumber" 會顯示已使用它的腳本或函式中的行號
:function! LineNumber() : return substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "") :endfunction :command! LineNumber try | throw "" | catch | echo LineNumber() | endtry
:try : try : throw "foo" : catch /foobar/ : echo "foobar" : finally : echo "inner finally" : endtry :catch /foo/ : echo "foo" :endtry內部的 try 條件不會捕獲例外,只會執行其 finally 子句。然後,例外會被外部的 try 條件捕獲。範例會顯示 "inner finally",然後顯示 "foo"。
:function! Foo() : throw "foo" :endfunction : :function! Bar() : try : call Foo() : catch /foo/ : echo "Caught foo, throw bar" : throw "bar" : endtry :endfunction : :try : call Bar() :catch /.*/ : echo "Caught" v:exception :endtry這會顯示 "Caught foo, throw bar",然後顯示 "Caught bar"。
:function! Bar() : try : call Foo() : catch /.*/ : echo "Rethrow" v:exception : throw v:exception : endtry :endfunction
:try : try : asdf : catch /.*/ : echoerr v:exception : endtry :catch /.*/ : echo v:exception :endtry此程式碼會顯示
CTRL-C
中斷腳本,則設定會保持不一致的狀態。當發生錯誤,或者您明確拋出例外而未捕獲例外時,在腳本的開發階段,您也可能會發生這種情況。您可以使用帶有 finally 子句的 try 條件來解決這些問題,以便還原設定。它保證在正常控制流程、發生錯誤、明確的 ":throw" 和中斷時執行。(請注意,來自 try 條件內部的錯誤和中斷會轉換為例外。如果沒有捕獲例外,它們會在執行 finally 子句後終止腳本。)範例:try : let s:saved_ts = &ts : set ts=17 : : " Do the hard work here. : :finally : let &ts = s:saved_ts : unlet s:saved_ts :endtry每當函式或腳本的一部分變更全域設定時,都應該在本地使用此方法,這些設定需要在該函式或腳本部分的失敗或正常結束時還原。
:let first = 1 :while 1 : try : if first : echo "first" : let first = 0 : continue : else : throw "second" : endif : catch /.*/ : echo v:exception : break : finally : echo "cleanup" : endtry : echo "still in while" :endwhile :echo "end"這會顯示 "first"、"cleanup"、"second"、"cleanup" 和 "end"。
:function! Foo() : try : return 4711 : finally : echo "cleanup\n" : endtry : echo "Foo still active" :endfunction : :echo Foo() "returned by Foo"這會顯示 "cleanup" 和 "4711 returned by Foo"。您不需要在 finally 子句中新增額外的 ":return"。(最重要的是,這會覆蓋傳回值。)
:try : try : echo "Press CTRL-C for interrupt" : while 1 : endwhile : finally : unlet novar : endtry :catch /novar/ :endtry :echo "Script still running" :sleep 1如果您需要在 finally 子句中放入可能會失敗的命令,您應該考慮捕獲或忽略這些命令中的錯誤,請參閱 catch-errors 和 ignore-errors。
Vim({cmdname}):{errmsg}或
Vim:{errmsg}
{cmdname}
是失敗的命令的名稱;當命令名稱未知時,會使用第二種形式。{errmsg}
是通常在 try 條件之外發生錯誤時產生的錯誤訊息。它始終以大寫的 "E" 開頭,後接一個二或三位數的錯誤編號、一個冒號和一個空格。:unlet novar通常會產生錯誤訊息
E108: No such variable: "novar"這在 try 條件內會轉換為例外
Vim(unlet):E108: No such variable: "novar"命令
:dwim通常會產生錯誤訊息
E492: Not an editor command: dwim這在 try 條件內會轉換為例外
Vim:E492: Not an editor command: dwim您可以透過以下方式捕獲所有 ":unlet" 錯誤
:catch /^Vim(unlet):/或透過以下方式捕獲所有拼寫錯誤的命令名稱的錯誤
:catch /^Vim:E492:/某些錯誤訊息可能會由不同的命令產生
:function nofunc和
:delfunction nofunc都會產生錯誤訊息
E128: Function name must start with a capital: nofunc這在 try 條件內會轉換為例外
Vim(function):E128: Function name must start with a capital: nofunc或
Vim(delfunction):E128: Function name must start with a capital: nofunc分別。如果您使用以下模式,您可以透過錯誤編號捕獲錯誤,而不考慮導致錯誤的命令
:catch /^Vim(\a\+):E128:/某些命令(如)
:let x = novar會產生多個錯誤訊息,在此範例中是
E121: Undefined variable: novar E15: Invalid expression: novar只有第一個會用於例外值,因為它是最明確的一個(請參閱 except-several-errors)。因此,您可以使用
:catch /^Vim(\a\+):E121:/您可以透過以下方式捕獲與名稱 "nofunc" 相關的所有錯誤
:catch /\<nofunc\>/您可以透過以下方式捕獲 ":write" 和 ":read" 命令中的所有 Vim 錯誤
:catch /^Vim(\(write\|read\)):E\d\+:/您可以使用模式捕獲所有 Vim 錯誤
:catch /^Vim\((\a\+)\)\=:E\d\+:/
:catch /No such variable/只在英文地區設定中有效,但是當使用者透過 :language 命令選擇不同的語言時無效。但是,在註解中引用訊息文字很有幫助
:catch /^Vim(\a\+):E108:/ " No such variable
:try : write :catch :endtry但是,強烈建議您不要使用這種簡單的形式,因為它可能會捕獲超出您想要的範圍。使用 ":write" 命令時,可能會執行某些自動命令並導致與寫入無關的錯誤,例如
:au BufWritePre * unlet novar即使是身為腳本撰寫者的您不需負責的錯誤也可能發生:您的腳本使用者可能已定義了自動指令。這樣您就會對使用者隱藏錯誤。最好使用
:try : write :catch /^Vim(write):/ :endtry只捕捉真正的寫入錯誤。因此,只捕捉您想故意忽略的錯誤。
:silent! nunmap k當 try 條件式處於啟用狀態時,此方法也有效。
CTRL-C
) 會被轉換為 "Vim:Interrupt" 例外。您可以像捕捉其他例外一樣捕捉它。然後,腳本不會終止。範例:function! TASK1() : sleep 10 :endfunction :function! TASK2() : sleep 20 :endfunction :while 1 : let command = input("Type a command: ") : try : if command == "" : continue : elseif command == "END" : break : elseif command == "TASK1" : call TASK1() : elseif command == "TASK2" : call TASK2() : else : echo "\nIllegal command:" command : continue : endif : catch /^Vim:Interrupt$/ : echo "\nCommand interrupted" : " Caught the interrupt. Continue with next prompt. : endtry :endwhile您可以在此處按
CTRL-C
來中斷任務;然後,腳本會要求新的指令。如果您在提示符號處按 CTRL-C
,腳本將會終止。:catch /.*/ :catch // :catch會捕捉所有例外,包括錯誤例外、中斷例外以及由 :throw 指令明確拋出的例外。這在腳本的頂層級中很有用,可以捕捉未預期的狀況。範例
:try : : " do the hard work here : :catch /MyException/ : : " handle known problem : :catch /^Vim:Interrupt$/ : echo "Script interrupted" :catch /.*/ : echo "Internal error (" .. v:exception .. ")" : echo " - occurred at " .. v:throwpoint :endtry :" end of script注意: 捕捉所有例外可能會捕捉到比您預期的更多的東西。因此,強烈建議您僅針對您可以透過在「:catch」中指定模式引數來真正處理的問題進行捕捉。範例:捕捉所有例外可能會使您幾乎無法透過按
CTRL-C
來中斷腳本。:while 1 : try : sleep 1 : catch : endtry :endwhile
:autocmd User x try :autocmd User x throw "Oops!" :autocmd User x catch :autocmd User x echo v:exception :autocmd User x endtry :autocmd User x throw "Arrgh!" :autocmd User x echo "Should not be displayed" : :try : doautocmd User x :catch : echo v:exception :endtry這會顯示「Oops!」和「Arrgh!」。
:autocmd BufWritePre * throw "FAIL" :autocmd BufWritePre * echo "Should not be displayed" : :try : write :catch : echo "Caught:" v:exception "from" v:throwpoint :endtry在此,「:write」指令不會寫入目前正在編輯的檔案(您可以透過檢查 'modified' 來確認),因為來自 BufWritePre 自動指令的例外會放棄「:write」。然後,例外會被捕捉,並且腳本會顯示
Caught: FAIL from BufWrite Auto commands for "*"
:autocmd BufWritePost * echo "File successfully written!" : :try : write /i/m/p/o/s/s/i/b/l/e :catch : echo v:exception :endtry這只會顯示
Vim(write):E212: Can't open file for writing (/i/m/p/o/s/s/i/b/l/e)如果您真的需要即使在主要動作失敗時也執行自動指令,請從 catch 子句觸發事件。範例
:autocmd BufWritePre * set noreadonly :autocmd BufWritePost * set readonly : :try : write /i/m/p/o/s/s/i/b/l/e :catch : doautocmd BufWritePost /i/m/p/o/s/s/i/b/l/e :endtry
:let x = "ok" :let v:errmsg = "" :autocmd BufWritePost * if v:errmsg != "" :autocmd BufWritePost * let x = "after fail" :autocmd BufWritePost * endif :try : silent! write /i/m/p/o/s/s/i/b/l/e :catch :endtry :echo x這會顯示「after fail」。
:autocmd BufWritePost * throw ":-(" :autocmd BufWritePost * echo "Should not be displayed" : :try : write :catch : echo v:exception :endtry
:if !exists("cnt") : let cnt = 0 : : autocmd BufWriteCmd * if &modified : autocmd BufWriteCmd * let cnt = cnt + 1 : autocmd BufWriteCmd * if cnt % 3 == 2 : autocmd BufWriteCmd * throw "BufWriteCmdError" : autocmd BufWriteCmd * endif : autocmd BufWriteCmd * write | set nomodified : autocmd BufWriteCmd * if cnt % 3 == 0 : autocmd BufWriteCmd * throw "BufWriteCmdError" : autocmd BufWriteCmd * endif : autocmd BufWriteCmd * echo "File successfully written!" : autocmd BufWriteCmd * endif :endif : :try : write :catch /^BufWriteCmdError$/ : if &modified : echo "Error on writing (file contents not changed)" : else : echo "Error after writing" : endif :catch /^Vim(write):/ : echo "Error on writing" :endtry當此腳本在進行變更後多次執行時,會先顯示
File successfully written!然後
Error on writing (file contents not changed)然後
Error after writing等等。
:autocmd BufWritePre * try : :autocmd BufWritePost * catch :autocmd BufWritePost * echo v:exception :autocmd BufWritePost * endtry : :write
:function! CheckRange(a, func) : if a:a < 0 : throw "EXCEPT:MATHERR:RANGE(" .. a:func .. ")" : endif :endfunction : :function! Add(a, b) : call CheckRange(a:a, "Add") : call CheckRange(a:b, "Add") : let c = a:a + a:b : if c < 0 : throw "EXCEPT:MATHERR:OVERFLOW" : endif : return c :endfunction : :function! Div(a, b) : call CheckRange(a:a, "Div") : call CheckRange(a:b, "Div") : if (a:b == 0) : throw "EXCEPT:MATHERR:ZERODIV" : endif : return a:a / a:b :endfunction : :function! Write(file) : try : execute "write" fnameescape(a:file) : catch /^Vim(write):/ : throw "EXCEPT:IO(" .. getcwd() .. ", " .. a:file .. "):WRITEERR" : endtry :endfunction : :try : : " something with arithmetic and I/O : :catch /^EXCEPT:MATHERR:RANGE/ : let function = substitute(v:exception, '.*(\(\a\+\)).*', '\1', "") : echo "Range error in" function : :catch /^EXCEPT:MATHERR/ " catches OVERFLOW and ZERODIV : echo "Math error" : :catch /^EXCEPT:IO/ : let dir = substitute(v:exception, '.*(\(.\+\),\s*.\+).*', '\1', "") : let file = substitute(v:exception, '.*(.\+,\s*\(.\+\)).*', '\1', "") : if file !~ '^/' : let file = dir .. "/" .. file : endif : echo 'I/O error for "' .. file .. '"' : :catch /^EXCEPT/ : echo "Unspecified error" : :endtryVim 本身引發的例外(在發生錯誤或按下
CTRL-C
時)使用扁平階層:它們都在「Vim」類別中。您無法自行拋出帶有「Vim」前置詞的例外;它們是保留給 Vim 使用的。如果知道的話,Vim 錯誤例外會以失敗的指令名稱進行參數化。請參閱 catch-errors。:try : try : throw 4711 : catch /\(/ : echo "in catch with syntax error" : catch : echo "inner catch-all" : finally : echo "inner finally" : endtry :catch : echo 'outer catch-all caught "' .. v:exception .. '"' : finally : echo "outer finally" :endtry這會顯示
inner finally outer catch-all caught "Vim(catch):E54: Unmatched \(" outer finally原始例外會被捨棄,並且會改為引發錯誤例外。
:try | unlet! foo # | catch | endtry會針對「:unlet!」引數後的尾隨字元引發錯誤例外,但不會看到「:catch」和「:endtry」指令,因此錯誤例外會被捨棄,並且會顯示「E488: Trailing characters」訊息。
echo novar會導致
E121: Undefined variable: novar E15: Invalid expression: novartry 條件式內錯誤例外的值為
Vim(echo):E121: Undefined variable: novar
unlet novar #會導致
E108: No such variable: "novar" E488: Trailing characterstry 條件式內錯誤例外的值為
Vim(unlet):E488: Trailing characters這樣做的原因是語法錯誤可能會以使用者不希望的方式變更執行路徑。範例
try try | unlet novar # | catch | echo v:exception | endtry catch /.*/ echo "outer catch:" v:exception endtry這會顯示「outer catch: Vim(unlet):E488: Trailing characters」,然後會顯示「E600: Missing :endtry」錯誤訊息,請參閱 except-single-line。
:" The function Nr2Bin() returns the binary string representation of a number. :func Nr2Bin(nr) : let n = a:nr : let r = "" : while n : let r = '01'[n % 2] .. r : let n = n / 2 : endwhile : return r :endfunc :" The function String2Bin() converts each character in a string to a :" binary string, separated with dashes. :func String2Bin(str) : let out = '' : for ix in range(strlen(a:str)) : let out = out .. '-' .. Nr2Bin(char2nr(a:str[ix])) : endfor : return out[1:] :endfunc其使用範例
:echo Nr2Bin(32)結果:「100000」
:echo String2Bin("32")結果:「110011-110010」
:func SortBuffer() : let lines = getline(1, '$') : call sort(lines, function("Strcmp")) : call setline(1, lines) :endfunction作為單行程式碼
:call setline(1, sort(getline(1, '$'), function("Strcmp")))
:" Set up the match bit :let mx='\(\f\+\),\s*\(\d\+\),\s*\(\d\+\)' :"get the part matching the whole expression :let l = matchstr(line, mx) :"get each item out of the match :let file = substitute(l, mx, '\1', '') :let lnum = substitute(l, mx, '\2', '') :let col = substitute(l, mx, '\3', '')輸入在變數「line」中,結果在變數「file」、「lnum」和「col」中。(來自 Michael Geddes 的想法)
:scriptnames
指令來取得已來源的所有腳本檔案的清單。還有 getscriptinfo()
函式,但傳回的資訊並不完全相同。如果您需要操作 scriptnames
的輸出,可以使用此程式碼" Get the output of ":scriptnames" in the scriptnames_output variable. let scriptnames_output = '' redir => scriptnames_output silent scriptnames redir END " Split the output into lines and parse each line. Add an entry to the " "scripts" dictionary. let scripts = {} for line in split(scriptnames_output, "\n") " Only do non-blank lines. if line =~ '\S' " Get the first number in the line. let nr = matchstr(line, '\d\+') " Get the file name, remove the script number " 123: ". let name = substitute(line, '.\+:\s*', '', '') " Add an item to the Dictionary let scripts[nr] = name endif endfor unlet scriptnames_output
CTRL-R
= 時,也會使用它。沙箱也用於 :sandbox 指令。Error
的 NvimInvalid 來取代任何非 Nvim 前綴的群組,並且存在一些其他的中間群組。=
hl-NvimAugmentedAssignment NvimAssignment 通用,+=
/`-=`/`.=` hl-NvimAssignmentWithAddition NvimAugmentedAssignment :let+= 中的 +=
hl-NvimAssignmentWithSubtraction NvimAugmentedAssignment :let-= 中的 -=
hl-NvimAssignmentWithConcatenation NvimAugmentedAssignment :let.= 中的 .=
#
/`?` hl-NvimBinaryPlus NvimBinaryOperator expr-+ hl-NvimBinaryMinus NvimBinaryOperator expr-- hl-NvimConcat NvimBinaryOperator expr-. hl-NvimConcatOrSubscript NvimConcat expr-. 或 expr-entry hl-NvimOr NvimBinaryOperator expr-barbar hl-NvimAnd NvimBinaryOperator expr-&& hl-NvimMultiplication NvimBinaryOperator expr-star hl-NvimDivision NvimBinaryOperator expr-/ hl-NvimMod NvimBinaryOperator expr-%{
/`}` hl-NvimNestingParenthesis NvimParenthesis expr-nesting 中的 (
/`)` hl-NvimCallingParenthesis NvimParenthesis expr-function 中的 (
/`)`[
/`]` hl-NvimSubscriptColon NvimSubscript expr-[:] 中的 :
hl-NvimCurly NvimSubscript curly-braces-names 中的 {
/`}`{
/`}` hl-NvimList NvimContainer list 字面值中的 [
/`]`:
前的字母 hl-NvimIdentifierScopeDelimiter NvimIdentifier 命名空間字母後的 :
hl-NvimIdentifierName NvimIdentifier 識別符號的其餘部分 hl-NvimIdentifierKey NvimIdentifier expr-entry 後的識別符號:
hl-NvimComma 分隔符號 dict 或 list 字面值或 expr-function 中的 ,
hl-NvimArrow 分隔符號 lambda 中的 ->
0
、十六進位數 的 0x
、二進位數 的 0b
hl-NvimFloat NvimNumber 浮點數&
hl-NvimOptionScope NvimIdentifierScope 選項範圍 (如果有) hl-NvimOptionScopeDelimiter NvimIdentifierScopeDelimiter 選項範圍後的 :
hl-NvimOptionName NvimIdentifier 選項名稱'
hl-NvimSingleQuotedBody NvimStringBody expr-' 字串主體的文字部分 hl-NvimSingleQuotedQuote NvimStringSpecial expr-' 字串主體內的 ''
"
hl-NvimDoubleQuotedBody NvimStringBody expr-quote 主體的文字部分 hl-NvimDoubleQuotedEscape NvimStringSpecial 有效的 expr-quote 跳脫序列 hl-NvimDoubleQuotedUnknownEscape NvimInvalidValue 無法辨識的 expr-quote 跳脫序列