Eval

Nvim の :help ページは、生成されたもので、ソースtree-sitter-vimdocパーサーを使用して作成されています。


式の使用については、ユーザーマニュアルの第41章 usr_41.txt で紹介されています。

1. 変数 variables

1.1 変数の型
E712 E896 E897 E899 変数には7つの型があります。
Number Integer 数値: 32ビットまたは64ビットの符号付き数値。expr-number ビット数は v:numbersize で確認できます。例: -123 0x10 0177 0o177 0b1011
浮動小数点数: 浮動小数点数。floating-point-format Float 例: 123.456 1.15e-6 -1.1e3
文字列: 8ビット符号なし文字 (バイト) のNUL終端文字列。expr-string 例: "ab\txx\"--" 'x-z''a,c'
関数参照: 関数への参照 Funcref。例: function("strlen") これは辞書と引数にバインドすることができ、Partial のように動作します。例: function("Callback", [arg], myDict)
リスト: 順序付きの項目のシーケンス。詳細については List を参照してください。例: [1, 2, ['a', 'b']]
辞書: 連想型の順序なし配列。各エントリにはキーと値があります。Dictionary
{"blue": "#0000ff", "red": "#ff0000"}
#{blue: "#0000ff", red: "#ff0000"}
Blob: バイナリラージオブジェクト。任意のバイトシーケンスを格納します。詳細については Blob を参照してください。例: 0zFF00ED015DAF 0z は空のBlobです。
数値型と文字列型は、使用方法に応じて自動的に変換されます。
数値から文字列への変換は、数値のASCII表現を作成することによって行われます。例
数値 123 --> 文字列 "123"
数値 0 --> 文字列 "0"
数値 -1 --> 文字列 "-1"
8進数
文字列から数値への変換は、最初の数字を数値に変換することによって行われます。16進数の "0xf9"、8進数の "017" または "0o17"、および2進数の "0b10" が認識されます。文字列が数字で始まらない場合、結果はゼロになります。例
文字列 "456" --> 数値 456
文字列 "6bar" --> 数値 6
文字列 "foo" --> 数値 0
文字列 "0xf1" --> 数値 241
文字列 "0100" --> 数値 64
文字列 "0o100" --> 数値 64
文字列 "0b101" --> 数値 5
文字列 "-8" --> 数値 -8
文字列 "+8" --> 数値 0
文字列から数値への変換を強制するには、ゼロを加算します。
:echo "0100" + 0
64
先頭のゼロが8進数変換を引き起こすのを防ぐ場合や、別の基数を使用する場合は、str2nr() を使用してください。
TRUE FALSE Boolean ブール演算子の場合、数値が使用されます。ゼロは FALSE、ゼロ以外は TRUE です。v:falsev:true を使用することもできます。関数から TRUE が返される場合は数値の1、FALSE は数値のゼロです。
コマンドでは
:if "foo"
:" NOT executed
"foo" は 0 に変換され、これは FALSE を意味します。文字列がゼロ以外の数値で始まる場合は TRUE を意味します。
:if "8foo"
:" executed
空でない文字列をテストするには、empty() を使用します。
:if !empty("foo")
falsy truthy 式は条件として使用でき、型を無視して、値が「やや真」か「やや偽」のどちらであるかのみを使用します。偽となる値は次のとおりです。数値のゼロ 空の文字列、blob、リスト、または辞書。その他の値は真となります。例: 0 偽 1 真 -1 真 0.0 偽 0.1 真 '' 偽 'x' 真 [] 偽 [0] 真 {} 偽 #{x: 1} 真 0z 偽 0z00 真
ゼロ以外の引数
関数の引数は、TRUE と若干異なる動作をすることがあります。引数が存在し、ゼロ以外の数値、v:true、または空でない文字列として評価される場合、その値は TRUE と見なされます。" " と "0" も空でない文字列であるため、TRUE と見なされることに注意してください。リスト、辞書、または浮動小数点数は数値でも文字列でもないため、FALSE として評価されます。
E745 E728 E703 E729 E730 E731 E974 E975 E976 ListDictionaryFuncref、および Blob 型は自動的に変換されません。
E805 E806 E808 数値と浮動小数点数を混合すると、数値は浮動小数点数に変換されます。それ以外の場合、浮動小数点数の自動変換はありません。文字列から浮動小数点数には str2float() を、浮動小数点数から文字列には printf() を、浮動小数点数から数値には float2nr() を使用できます。
E362 E891 E892 E893 E894 E907 浮動小数点数が期待される場合、数値も使用できますが、それ以外は使用できません。
型チェックなし
変数の型を変更しようとしてもエラーは発生しません。
1.2 関数参照
Funcref E695 E718 E1192 関数参照変数 は、function() 関数、funcref() 関数、またはラムダ式 expr-lambda で作成されます。これは、関数名 の代わりに、引数を囲む括弧の前にある式で使用して、参照先の関数を呼び出すことができます。例
:let Fn = function("MyFunc")
:echo Fn()
E704 E705 E707 関数参照変数は、大文字、"s:"、"w:"、"t:" または "b:" で始まる必要があります。"g:" を使用できますが、次の名前は大文字で始まる必要があります。関数参照変数と関数に同じ名前を付けることはできません。
特殊なケースとして、関数の定義と、その関数参照を直接辞書のエントリに割り当てる場合です。例
:function dict.init() dict
:   let self.val = 0
:endfunction
辞書のキーは小文字で始めることができます。実際の関数名はここでは使用されません。numbered-function も参照してください。
関数参照は :call コマンドでも使用できます。
:call Fn()
:call dict.init()
参照されている関数の名前は string() で取得できます。
:let func = string(Fn)
関数参照を呼び出し、引数にリスト変数を使用するには call() を使用できます。
:let r = call(Fn, mylist)
Partial
関数参照は、オプションで辞書および/または引数をバインドします。これは Partial とも呼ばれます。これは、辞書および/または引数を function() または funcref() に渡すことによって作成されます。関数を呼び出すと、辞書および/または引数が関数に渡されます。例
let Cb = function('Callback', ['foo'], myDict)
call Cb('bar')
これは、次のように使用した場合と同じように関数を呼び出します
call myDict.Callback('foo', 'bar')
関数が辞書のメンバーである場合にも、関数を辞書にバインドすることが発生することに注意してください。
let myDict.myFunction = MyFunction
call myDict.myFunction()
ここで、MyFunction() は "self" として myDict を渡されます。これは、"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" になります。これは、明示的にバインドされたためです。
1.3 リスト
list List Lists E686 リストは、項目の順序付きシーケンスです。項目は任意の型にできます。項目は、そのインデックス番号でアクセスできます。項目は、シーケンスの任意の位置で追加および削除できます。
リストの作成
E696 E697 リストは、角かっこ内のコンマ区切りの項目リストで作成されます。例
:let mylist = [1, two, 3, "four"]
:let emptylist = []
項目は任意の式にできます。項目にリストを使用すると、リストのリストが作成されます。
:let nestlist = [[11, 12], [21, 22], [31, 32]]
最後の項目の後の余分なコンマは無視されます。
リストのインデックス
list-index E684 リスト内の項目には、リストの後ろに角かっこで囲んだインデックスを付けることでアクセスできます。インデックスはゼロベースであるため、最初の項目のインデックスはゼロです。
: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
負のインデックスは末尾から数えます。インデックス -1 はリストの最後の項目を指し、-2 は最後から2番目の項目などを指します。
:let last = mylist[-1]                " get the last item: "four"
無効なインデックスでエラーが発生するのを防ぐには、get() 関数を使用します。項目が利用できない場合は、ゼロまたは指定したデフォルト値を返します。
:echo get(mylist, idx)
:echo get(mylist, idx, "NONE")
リストの連結
list-concatenation
2つのリストは "+" 演算子で連結できます。
:let longlist = mylist + [5, 6]
:let longlist = [5, 6] + mylist
項目を先頭に追加または末尾に追加するには、[] で囲んでリストに変換します。
リストは :let+= または extend() を使用して、別のリストとインプレースで連結できます。
:let mylist += [7, 8]
:call extend(mylist, [7, 8])
リストのインプレースでの変更の詳細については、以下の list-modification を参照してください。
サブリスト
サブリスト
リストの一部は、角かっこで囲んだコロンで区切られた最初と最後のインデックスを指定することで取得できます。
: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()メソッドを使用してください。
最初のインデックスがリストの最後の項目を超えている場合、または2番目の項目が最初の項目の前にある場合、結果は空のリストになります。エラーメッセージは表示されません。
2番目のインデックスがリストの長さ以上の場合、長さから1を引いたものが使用されます。
:let mylist = [0, 1, 2, 3]
:echo mylist[2:8]                " result: [2, 3]
注意: mylist[s:e] は、変数 "s:e" をインデックスとして使用することを意味します。「:」の前に単一の文字変数を使用する場合は注意してください。必要に応じてスペースを挿入してください: mylist[s : e]。
リストの同一性
リストの同一性
変数 "aa" がリストで、それを別の変数 "bb" に代入すると、両方の変数が同じリストを参照します。したがって、リスト "aa" を変更すると、"bb" も変更されます。
:let aa = [1, 2, 3]
:let bb = aa
:call add(aa, 4)
:echo bb
[1, 2, 3, 4]
リストのコピーを作成するには、copy()関数を使用します。[ : ] を使用する方法も上記で説明したように機能します。これにより、リストの浅いコピーが作成されます。リスト内のリスト項目を変更すると、コピーされたリスト内の項目も変更されます。
:let aa = [[1, 'a'], 2, 3]
:let bb = copy(aa)
:call add(aa, 4)
:let aa[0][1] = 'aaa'
:echo aa
[[1, aaa], 2, 3, 4]
:echo bb
[[1, aaa], 2, 3]
完全に独立したリストを作成するには、deepcopy()を使用します。これにより、リスト内の値も再帰的にコピーされます。最大100レベルの深さまで。
演算子 "is" を使用して、2つの変数が同じリストを参照しているかどうかを確認できます。"isnot" は反対を行います。対照的に、"==" は2つのリストが同じ値を持っているかどうかを比較します。
:let alist = [1, 2, 3]
:let blist = [1, 2, 3]
:echo alist is blist
0
:echo alist == blist
1
リストの比較に関する注意点:2つのリストは、長さが同じであり、すべての項目が "==" を使用した場合と同じように等しいと見なされる場合に等しいと見なされます。1つ例外があります。数値と文字列を比較する場合、それらは異なると見なされます。変数で "==" を使用した場合のように、自動的な型変換はありません。例
echo 4 == "4"
1
echo [4] == ["4"]
0
したがって、リストの比較は、数値や文字列の比較よりも厳密です。簡単な値をリストに入れて比較することもできます。
:let a = 5
:let b = "5"
:echo a == b
1
:echo [a] == [b]
0
リストのアンパック
リスト内の項目を個々の変数にアンパックするには、リスト項目のように、変数を角かっこで囲みます。
:let [var1, var2] = mylist
変数の数がリスト内の項目の数と一致しない場合、エラーが発生します。リストからの追加の項目を処理するには、";" と変数名を追加します。
:let [var1, var2; rest] = mylist
これは次のように機能します。
:let var1 = mylist[0]
:let var2 = mylist[1]
:let rest = mylist[2:]
ただし、項目が2つしかない場合はエラーが発生しません。"rest" は空のリストになります。
リストの変更
リストの変更
リストの特定の項目を変更するには、:let を次のように使用します。
: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]
2つの変数が同じリストを参照している場合、1つのリストをインプレースで変更すると、参照されているリストもインプレースで変更されます。
: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 ループ
:for ループは、リスト文字列、または Blob の各項目に対してコマンドを実行します。変数は各項目に順に設定されます。リストを使用した例
: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
リスト内の各項目を変更するだけでよい場合は、for ループよりも map() 関数の方が簡単な方法です。
:let コマンドと同様に、: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 の場合は、一度に1バイトずつ使用されます。
文字列の場合は、構成文字を含む1文字が文字列として使用されます。例
for c in text
  echo 'This character is ' .. c
endfor
リスト関数
E714
リストで役立つ関数
: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, '+')
1.4 辞書
Dict dict 辞書 辞書 辞書は連想配列です。各エントリにはキーと値があります。エントリはキーを使用して検索できます。エントリは特定の順序なしで格納されます。
辞書の作成
E720 E721 E722 E723 辞書は、中かっこで囲まれたコンマ区切りのエントリのリストで作成されます。各エントリには、コロンで区切られたキーと値があります。各キーは1回しか出現できません。例
:let mydict = {1: 'one', 2: 'two', 3: 'three'}
:let emptydict = {}
E713 E716 E717 キーは常に文字列です。数値を使用できます。数値は自動的に文字列に変換されます。したがって、文字列 '4' と数値 4 は同じエントリを検索します。文字列 '04' と数値 04 は異なることに注意してください。数値は文字列 '4' に変換されるため、先頭のゼロは削除されます。空の文字列もキーとして使用できます。リテラル辞書 #{} すべてのキーを引用符で囲む必要がないように、#{} 形式を使用できます。これには、キーが ASCII 文字、数字、'-'、および '_' のみで構成されている必要があります。例
: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
リストとは異なり、この方法で既存の辞書に新しいエントリを追加できます。
文字、数字、およびアンダースコアのみで構成されるキーの場合は、次の形式を使用できます expr-entry
:let val = mydict.one
:let mydict.four = 4
エントリには任意の型(リストや辞書も含む)を使用できるため、インデックス作成とキー検索を繰り返すことができます。
:echo dict.key[idx].key
辞書からリストへの変換
辞書内のエントリをループしたい場合があります。このためには、辞書をリストに変換して :for に渡す必要があります。
ほとんどの場合、keys() 関数を使用してキーをループ処理します。
: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() 関数を使用します。キーと値の2つの項目を含むリストである各項目を含むリストを返します。
:for [key, value] in items(mydict)
:   echo key .. ': ' .. value
:endfor
辞書の同一性
辞書の同一性
リストと同様に、辞書のコピーを作成するには、copy()deepcopy() を使用する必要があります。それ以外の場合、代入すると同じ辞書を参照することになります。
:let onedict = {'a': 1, 'b': 2}
:let adict = onedict
:let adict['a'] = 11
:echo onedict['a']
11
すべてのキーと値のペアが等しいと見なされる場合、2つの辞書は等しいと見なされます。詳細については、リストの同一性を参照してください。
辞書の変更
辞書の変更
辞書の既存のエントリを変更したり、新しいエントリを追加したりするには、:let を次のように使用します。
:let dict[4] = "four"
:let dict['one'] = item
辞書からエントリを削除するには、remove() または :unlet を使用します。dict からキー "aaa" を持つエントリを削除する3つの方法
:let i = remove(dict, 'aaa')
:unlet dict.aaa
:unlet dict['aaa']
辞書を別の辞書とマージするには、extend() を使用します。
:call extend(adict, bdict)
これにより、adict は bdict のすべてのエントリで拡張されます。キーが重複すると、adict のエントリが上書きされます。オプションの3番目の引数でこれを変更できます。辞書内のエントリの順序は無関係であるため、":echo adict" が adict の古いエントリの後に bdict の項目を表示することを期待しないでください。
辞書からエントリを削除するには、filter() を使用できます。
:call filter(dict, 'v:val =~ "x"')
これにより、値が 'x' と一致しない "dict" からすべてのエントリが削除されます。これを使用してすべてのエントリを削除することもできます。
call filter(dict, 0)
辞書関数
辞書関数 self E725 E862 関数が "dict" 属性で定義されている場合、辞書で特別な方法で使用できます。例
:function Mylen() dict
:   return len(self.data)
:endfunction
:let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
:echo mydict.len()
これは、オブジェクト指向プログラミングのメソッドのようなものです。辞書内のエントリは Funcref です。ローカル変数 "self" は、関数が呼び出された辞書を参照します。
"dict" 属性のない関数を 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 が残っていない場合は、自動的に削除されます。
番号付き関数に "dict" 属性を使用する必要はありません。
番号付き関数でエラーが発生した場合、トリックを使用して何であるかを見つけることができます。関数が 42 であると仮定すると、コマンドは次のようになります。
:function g:42
辞書の関数
E715
辞書で使用できる関数
: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
1.5 Blob
blob Blob Blobs E978 Blobはバイナリオブジェクトです。例えば、ファイルから画像を読み込んでチャネル経由で送信するために使用できます。
Blobは主に、0から255までの8ビットのバイト値を持つ数値のリストのように動作します。
Blobの作成
Blobはblobリテラルで作成できます。
:let b = 0zFF00ED015DAF
可読性のため、バイト(16進数のペア)の間にドットを挿入できます。これらは値を変更しません。
:let b = 0zFF00.ED01.5DAF
Blobは、例えば、{type}引数を "B" に設定してreadfile()でファイルから読み込むことができます。
:let b = readfile('image.png', 'B')
Blobのインデックス
blob-index E979 Blob内のバイトには、Blobの後に角括弧で囲んでインデックスを指定することでアクセスできます。インデックスはゼロベースで、最初のバイトのインデックスはゼロです。
:let myblob = 0z00112233
:let byte = myblob[0]                " get the first byte: 0x00
:let byte = myblob[2]                " get the third byte: 0x22
負のインデックスは末尾から数えます。インデックス-1はBlobの最後のバイト、-2は最後から2番目のバイトなどを指します。
:let last = myblob[-1]                " get the last byte: 0x33
無効なインデックスによるエラーを避けるには、get()関数を使用します。項目がない場合は-1または指定したデフォルト値を返します。
:echo get(myblob, idx)
:echo get(myblob, idx, 999)
Blobの反復処理
:forループは、Blobの各バイトに対してコマンドを実行します。ループ変数はBlob内の各バイトに設定されます。例:
:for byte in 0z112233
:   call Doit(byte)
:endfor
これは、0x11、0x22、および0x33でDoit()を呼び出します。
Blobの連結
blob連結
2つのBlobは"+"演算子で連結できます。
:let longblob = myblob + 0z4455
:let longblob = 0z4455 + myblob
Blobは:let+=を使用して、別のBlobとインプレースで連結できます。
:let myblob += 0z6677
Blobのインプレースでの変更の詳細については、以下のblobの変更を参照してください。
Blobの一部
Blobの一部は、最初のインデックスと最後のインデックスを角括弧でコロンで区切って指定することで取得できます。
: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の最後のバイトを超えている場合、または2番目のインデックスが最初のインデックスの前にある場合、結果は空のBlobになります。エラーメッセージはありません。
2番目のインデックスがBlobの長さ以上の場合、長さから1を引いたものが使用されます。
:echo myblob[2:8]                " result: 0z2233
Blobの変更
blobの変更
Blobの特定のバイトを変更するには、:letを次のように使用します。
:let blob[4] = 0x44
インデックスがBlobの末尾の直後の場合、追加されます。それより大きいインデックスはエラーです。
バイトのシーケンスを変更するには、[:]表記を使用できます。
let blob[1:3] = 0z445566
置換されるバイトの長さは、提供される値とまったく同じである必要があります。E972
Blobの一部を変更するには、変更する最初のバイトと最後のバイトを指定できます。値は範囲内のバイト数と同じバイト数を持つ必要があります。
:let blob[3:5] = 0z334455
Blobにインプレースで項目を追加するには、:let+= (blob連結) を使用できます。
:let blobA = 0z1122
:let blobA += 0z3344
2つの変数が同じBlobを参照している場合、一方のBlobをインプレースで変更すると、参照されているBlobがインプレースで変更されます。
:let blobA = 0z1122
:let blobB = blobA
:let blobB += 0z3344
:echo blobA
0z11223344
関数add()remove()、およびinsert()も使用できます。
Blobの同一性
Blobは等価性を比較できます。
if blob == 0z001122
また、同一性も比較できます。
if blob is otherblob
blob-identity E977 変数 "aa" がBlobで、別の変数 "bb" に代入すると、両方の変数は同じBlobを参照します。この場合、"is" 演算子はtrueを返します。
[:]またはcopy()を使用してコピーを作成すると、値は同じですが、同一性は異なります。
:let blob = 0z112233
:let blob2 = blob
:echo blob == blob2
1
:echo blob is blob2
1
:let blob3 = blob[:]
:echo blob == blob3
1
:echo blob is blob3
0
Blobのコピーを作成するには、copy()関数を使用します。上記のように、[:]を使用することもできます。
1.6 変数について
変数について
変数または式の型を知る必要がある場合は、type()関数を使用します。
'shada'オプションに '!' フラグが含まれている場合、大文字で始まり、小文字を含まないグローバル変数は、シャダファイル シャダファイルに保存されます。
'sessionoptions'オプションに "global" が含まれている場合、大文字で始まり、少なくとも1つの小文字を含むグローバル変数は、セッションファイル セッションファイルに保存されます。
変数名が保存される場所
my_var_6 (セッションファイル) My_Var_6 (セッションファイル) MY_VAR_6 (シャダファイル)
中括弧を使用して変数名を形成することができます。 中括弧の名前を参照してください。

2. 式の構文 式の構文

式の構文の概要(重要度の低い順)
expr1 expr2 expr2 ? expr1 : expr1 (if-then-else)
expr2 expr3 expr3 || expr3 ... (論理OR)
expr3 expr4 expr4 && expr4 ... (論理AND)
expr4 expr5 expr5 == expr5 (等しい) expr5 != expr5 (等しくない) expr5 > expr5 (より大きい) expr5 >= expr5 (以上) expr5 < expr5 (より小さい) expr5 <= expr5 (以下) expr5 =~ expr5 (正規表現が一致) expr5 !~ expr5 (正規表現が一致しない)
expr5 ==? expr5 (等しい、大文字小文字を無視) expr5 ==# expr5 (等しい、大文字小文字を区別) など。上記と同様に、大文字小文字を無視する場合は?を、大文字小文字を区別する場合は#を追加します。
expr5 is expr5 (同じリスト辞書またはBlobインスタンス) expr5 isnot expr5 (異なるリスト辞書またはBlobインスタンス)
expr5 expr6 expr6 + expr6 ... (数値の加算、リストまたはBlobの連結) expr6 - expr6 ... (数値の減算) expr6 . expr6 ... (文字列連結) expr6 .. expr6 ... (文字列連結)
expr6 expr7 expr7 * expr7 ... (数値の乗算) expr7 / expr7 ... (数値の除算) expr7 % expr7 ... (数値の剰余)
expr7 expr8 ! expr7 (論理NOT)
expr7 (単項マイナス) + expr7 (単項プラス)
expr8 expr9 expr8[expr1] (文字列のバイトまたはリストの項目) expr8[expr1 : expr1] (文字列のサブストリングまたはリストのサブリスト) expr8.name (辞書のエントリ) expr8(expr1, ...) (Funcref変数を使用した関数呼び出し) expr8->name(expr1, ...) (メソッド呼び出し)
expr9 (数値定数) "string" (文字列定数、バックスラッシュは特殊文字) 'string' (文字列定数、'は二重化) [expr1, ...] (リスト) {expr1: expr1, ...} (辞書) #{key: expr1, ...} (辞書) &option (オプション値) (expr1) (ネストされた式) (変数) (内部変数) va{ria}ble (中括弧を使用した内部変数) $VAR (環境変数) @r (レジスタ "r" の内容) function(expr1, ...) (関数呼び出し) func{ti}on(expr1, ...) (中括弧を使用した関数呼び出し) {args -> expr1} (ラムダ式)
"..." は、このレベルの操作を連結できることを示します。例:
&nu || &list && &shell == "csh"
1つのレベル内のすべての式は、左から右に解析されます。
式のネストは、スタックが不足してクラッシュするのを避けるため、1000レベルの深さに制限されています(MSVCでビルドした場合は300)。E1169
三項演算子:expr2 ? expr1 : expr1 falsy演算子:expr2 ?? expr1
三項演算子
'?' の前の式は数値に評価されます。 TRUEと評価された場合、結果は '?' と ':' の間の式の値になり、それ以外の場合、結果は ':' の後の式の値になります。例:
:echo lnum == 1 ? "top" : lnum
最初の式は「expr2」であるため、別の?:を含めることはできません。他の2つの式は含めることができるため、?:の再帰的な使用が可能です。例:
:echo lnum == 1 ? "top" : lnum == 1000 ? "last" : lnum
これを読みやすくするには、行継続を使用することをお勧めします。
:echo lnum == 1
:\        ? "top"
:\        : lnum == 1000
:\                ? "last"
:\                : lnum
':' の前には必ずスペースを配置する必要があります。そうしないと、「a:1」などの変数での使用と間違われる可能性があります。
Falsy演算子
これは「null合体演算子」とも呼ばれますが、複雑すぎるため、ここではfalsy演算子と呼びます。
'??' の前の式が評価されます。truthyと評価された場合、これが結果として使用されます。それ以外の場合、'??' の後の式が評価され、結果として使用されます。これは、ゼロまたは空になる可能性のある式のデフォルト値を持つ場合に最も役立ちます。
echo theList ?? 'list is empty'
echo GetName() ?? 'unknown'
これらは似ていますが、等しくはありません。
expr2 ?? expr1
expr2 ? expr2 : expr1
2行目では、"expr2" が2回評価されます。

expr2とexpr3 expr2 expr3

expr3 || expr3 .. (論理OR) expr-barbar
expr4 && expr4 .. (論理AND) expr-&&
"||" および "&&" 演算子は、両側に1つの引数を取ります。引数は数値(に変換)されます。結果は次のとおりです。
入力 出力
n1 n2 n1 || n2 n1 && n2
FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE TRUE FALSE TRUE FALSE TRUE TRUE TRUE TRUE
演算子は連結できます。例:
&nu || &list && &shell == "csh"
"&&" は "||" よりも優先順位が高いため、これは次のような意味になります。
&nu || (&list && &shell == "csh")
結果が分かると、式は「ショートサーキット」します。つまり、それ以上の引数は評価されません。これはCで発生することに似ています。例:
let a = 1
echo a || b
"a" が TRUEなので結果は TRUE である必要があるため、"b" という変数がなくてもこれは有効です。同様に以下:
echo exists("b") && b == "yes"
これは、"b" が定義されているかどうかに関係なく有効です。2番目の句は、"b" が定義されている場合にのみ評価されます。

expr4 expr4

expr5 {cmp} expr5
2つのexpr5式を比較し、falseと評価された場合は0、trueと評価された場合は1を返します。
expr-== expr-!= expr-> expr->=
expr-< expr-<= expr-=~ expr-!~ expr-==# expr-!=# expr-># expr->=# expr-<# expr-<=# expr-=~# expr-!~# expr-==? expr-!=? expr->? expr->=? expr-<? expr-<=? expr-=~? expr-!~? expr-is expr-isnot expr-is# expr-isnot# expr-is? expr-isnot?
'ignorecase'オプションを使用すると、大文字と小文字を区別しないマッチングが行われます。
等しい == ==# ==? 等しくない != !=# !=? より大きい > ># >? 以上 >= >=# >=? より小さい < <# <? 以下 <= <=# <=? 正規表現にマッチする =~ =~# =~? 正規表現にマッチしない !~ !~# !~? 同じインスタンス is is# is? 異なるインスタンス isnot isnot# isnot?
例: "abc" ==# "Abc" は 0 と評価されます。"abc" ==? "Abc" は 1 と評価されます。"abc" == "Abc" は、'ignorecase' が設定されている場合は 1 と評価され、それ以外の場合は 0 と評価されます。
E691 E692 ListList とのみ比較でき、"equal"、"not equal"、"is"、"isnot" のみが使用できます。これは、リストの値を再帰的に比較します。大文字と小文字を区別しないということは、項目の値を比較するときに大文字と小文字が区別されないことを意味します。
E735 E736 DictionaryDictionary とのみ比較でき、"equal"、"not equal"、"is"、"isnot" のみが使用できます。これは、Dictionary のキー/値を再帰的に比較します。大文字と小文字を区別しないということは、項目の値を比較するときに大文字と小文字が区別されないことを意味します。
E694
FuncrefFuncref とのみ比較でき、"equal"、"not equal"、"is"、"isnot" のみが使用できます。大文字と小文字が区別されることはありません。引数または Dictionary が (部分的に) バインドされているかどうかは重要です。Dictionary も等しく (または "is" の場合は同じで) あり、引数も等しく (または同じ) である必要があります。
バインドされた Dictionary と引数を無視して、Funcref が同じ関数を参照しているかどうかを確認するには、get() を使用して関数名を取得します。
if get(Part1, 'name') == get(Part2, 'name')
   " Part1 and Part2 refer to the same function
ListDictionary、または Blob で "is" または "isnot" を使用すると、式が同じ ListDictionary、または Blob インスタンスを参照しているかどうかがチェックされます。List のコピーは、元の List とは異なります。ListDictionary、または Blob なしで "is" を使用すると、"equal" を使用する場合と同じになり、"isnot" を使用すると "not equal" を使用する場合と同じになります。ただし、異なる型は値が異なることを意味します。
echo 4 == '4'
1
echo 4 is '4'
0
echo 0 is []
0
"is#"/"isnot#" と "is?"/"isnot?" は、大文字と小文字を区別して、または無視してマッチングするために使用できます。
String を Number と比較する場合、String は Number に変換され、Number で比較が行われます。つまり、
echo 0 == 'x'
1
'x' が Number に変換されると 0 になるためです。しかし
echo [0] == ['x']
0
List または Dictionary 内では、この変換は使用されません。
2 つの String を比較する場合、これは strcmp() または stricmp() で行われます。これにより、(バイト値を比較する) 数学的な差が生じ、必ずしもローカル言語でのアルファベットの差が生じるわけではありません。
末尾に '#' を持つ演算子、または短縮バージョンを使用し、'ignorecase' がオフの場合、比較は strcmp() で行われます: 大文字と小文字は区別されます。
末尾に '?' を持つ演算子、または短縮バージョンを使用し、'ignorecase' が設定されている場合、比較は stricmp() で行われます: 大文字と小文字は無視されます。
'smartcase' は使用されません。
"=~" および "!~" 演算子は、左側の引数を右側の引数 (パターンとして使用) とマッチングさせます。パターンとは何かについては、pattern を参照してください。このマッチングは、常に 'magic' が設定され、'cpoptions' が空の場合のように行われます。これは、'magic' または 'cpoptions' の実際の値に関係なく、スクリプトをポータブルにします。正規表現パターンでバックスラッシュが二重にならないようにするには、シングルクォートの文字列を使用してください (「literal-string」を参照)。文字列は単一行と見なされるため、複数行のパターン ( \n、バックスラッシュ-n を含む) は一致しません。ただし、リテラルの NL 文字は通常の文字のようにマッチングできます。例: "foo\nbar" =~ "\n" は 1 と評価されます。"foo\nbar" =~ "\\n" は 0 と評価されます。

expr5 および expr6 expr5 expr6

expr6 + expr6 Number 加算、List または Blob 連結 expr-+ expr6 - expr6 Number 減算 expr--
expr6 . expr6 String 連結 expr-.
expr6 .. expr6 String 連結 expr-..
Lists の場合、"+" のみが可能であり、両方の expr6 はリストである必要があります。結果は、2 つのリストが連結された新しいリストになります。
String 連結の場合、"." は Dict メンバーアクセスや浮動小数点数にも使用されるため、曖昧であるため、".." が推奨されます。
expr7 * expr7 Number 乗算 expr-star
expr7 / expr7 Number 除算 expr-/
expr7 % expr7 Number モジュロ expr-%
"." および ".." を除くすべての場合、String は Number に変換されます。ビット単位演算子については、and()or()、および xor() を参照してください。
"+" と "." の違いに注意してください: "123" + "456" = 579 "123" . "456" = "123456"
'.' は '+' や '-' と同じ優先順位を持つため、次のように読み取る必要があります。
1 . 90 + 90.0
以下のように
(1 . 90) + 90.0
String "190" は自動的に Number 190 に変換され、Float 90.0 に加算できるため、これは機能します。ただし
1 . 90 * 90.0
以下のように読み取る必要があります。
1 . (90 * 90.0)
'.' は '*' よりも優先順位が低いためです。これは、Float と String を連結しようとするため、機能しません。
Number をゼロで除算すると、結果は値によって異なります: 0 / 0 = -0x80000000 (Float の NaN のようなもの) >0 / 0 = 0x7fffffff (正の無限大のようなもの) <0 / 0 = -0x7fffffff (負の無限大のようなもの) (Vim 7.2 より前は常に 0x7fffffff でした)
64 ビット Number サポートが有効になっている場合: 0 / 0 = -0x8000000000000000 (Float の NaN のようなもの) >0 / 0 = 0x7fffffffffffffff (正の無限大のようなもの) <0 / 0 = -0x7fffffffffffffff (負の無限大のようなもの)
'%' の右側がゼロの場合、結果は 0 になります。
これらのどれも Funcref では機能しません。
. および % は Float では機能しません。 E804

expr7 expr7

! expr7 論理 NOT expr-!
expr7 単項マイナス expr-unary--
+ expr7 単項プラス expr-unary-+
'!' の場合、TRUEFALSE になり、FALSETRUE (1) になります。'-' の場合、数値の符号が変更されます。'+' の場合、数値は変更されません。注意: "++" には効果がありません。
String は最初に Number に変換されます。
これら 3 つは、繰り返したり混合したりできます。例: !-1 == 0 !!8 == 1 --9 == 9

expr8 expr8

この式は、expr9 か、以下の代替式のシーケンスのいずれかであり、任意の順序で指定できます。例: これらはすべて可能です: expr8[expr1].name expr8.name[expr1] expr8(expr1, ...)[expr1].name expr8->(expr1, ...)[expr1] 評価は常に左から右に行われます。
expr8[expr1] String または List の項目 expr-[] E111 subscript
レガシー Vim スクリプトでは: expr8 が Number または String の場合、これは expr8 から expr1 番目のシングルバイトを含む String になります。expr8 は String として使用され (数値は自動的に String に変換されます)、expr1 は Number として使用されます。これはマルチバイトエンコーディングを認識しません。代替策として byteidx() を使用するか、split() を使用して文字列を文字のリストに変換してください。例: カーソルの下のバイトを取得するには
:let c = getline(".")[col(".") - 1]
インデックス 0 は最初のバイトを与えます。これは C での動作と同じです。注意: テキスト列番号は 1 から始まります! 例: カーソルの下のバイトを取得するには
:let c = getline(".")[col(".") - 1]
インデックス 0 は最初のバイトを与えます。注意: テキスト列番号は 1 から始まります!
String の長さがインデックスよりも短い場合、結果は空の String になります。負のインデックスは常に空の文字列になります (理由: 後方互換性)。最後のバイトを取得するには、[-1:] を使用します。
expr8 が List の場合、結果はインデックス expr1 の項目になります。可能なインデックス値については、list-index を参照してください。インデックスが範囲外の場合、エラーになります。例
:let item = mylist[-1]                " get last item
一般に、List のインデックスが List の長さ以上であるか、List の長さよりも負である場合、エラーになります。
expr8[expr1a : expr1b] 部分文字列または サブリスト expr-[:] substring
expr8 が String の場合、結果は expr1a から expr1b までのバイトまたは文字を含む部分文字列になります。expr8 は String として使用され、expr1a および expr1b は Number として使用されます。
旧Vimスクリプトでは、インデックスはバイトインデックスです。これはマルチバイトエンコーディングを認識しません。インデックスの計算についてはbyteidx()を参照してください。expr8が数値の場合、最初に文字列に変換されます。
インデックスexpr1bの項目は含まれ、これは包括的です。排他的なインデックスには、slice()関数を使用してください。
expr1aが省略された場合、ゼロが使用されます。expr1bが省略された場合、文字列の長さから1を引いたものが使用されます。
負の数は、文字列の末尾からの測定に使用できます。-1は最後の文字、-2は最後から2番目の文字、といった具合です。
インデックスが文字列の範囲外になる場合、文字は省略されます。expr1bがexpr1aより小さい場合、結果は空の文字列になります。
: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
スライス
expr8がListの場合、これはインデックスexpr1aとexpr1bで示される項目を含む新しいListになります。これは上記で説明したように、文字列の場合と同様に機能します。以下のsublistも参照してください。例
: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の場合、これはインデックスexpr1aとexpr1bのバイトを含む新しいBlobになります。例
:let b = 0zDEADBEEF
:let bs = b[1:2]                " 0zADBE
:let bs = b[]                        " copy of 0zDEADBEEF
Funcrefでexpr8[expr1]またはexpr8[expr1a : expr1b]を使用すると、エラーが発生します。
名前空間と、サブリストのためのコロンが続く変数の間の混乱に注意してください
mylist[n:]     " uses variable n
mylist[s:]     " uses namespace s:, error!
Dictionary内のexpr8.nameエントリexpr-entry
expr8がDictionaryで、その後にドットが続く場合、後続の名前はDictionaryのキーとして使用されます。これはexpr8[name]とまったく同じです。
名前は、変数名のように英数字で構成されている必要がありますが、数字で始めることもできます。中括弧は使用できません。
ドットの前後に空白があってはなりません。
: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
ドットは文字列連結にも使用されることに注意してください。混乱を避けるために、文字列連結には常にドットの周りにスペースを置いてください。
expr8(expr1, ...) Funcref関数呼び出し E1085
expr8がFuncref型の変数の場合、それが参照する関数を呼び出します。
expr8->name([args]) メソッド呼び出し method -> expr8->{lambda}([args])
E260 E276 グローバル関数としても利用できるメソッドの場合、これは次と同じです
name(expr8 [, args])
"expr8"のタイプに特有のメソッドも存在します。
これにより、あるメソッドが返す値を次のメソッドに渡す、メソッドのチェーンが可能になります
mylist->filter(filterexpr)->map(mapexpr)->sort()->join()
ラムダの使用例
GetPercentage()->{x -> x * 100}()->printf('%d%%')
->を使用する場合、expr7演算子が最初に適用されます。したがって
-1.234->string()
次のものと同等です
(-1.234)->string()
以下ではありません
-(1.234->string())
E274
"->name(" には空白を含めてはなりません。 "->" の前と "(" の後には空白を含めることができるため、次のように行を分割できます
mylist
\ ->filter(filterexpr)
\ ->map(mapexpr)
\ ->sort()
\ ->join()
ラムダ形式を使用する場合、}と の間に空白があってはなりません

(.

expr9

数値

数値 定数 expr-number
0x hex-number 0o octal-number binary-number 10進数、16進数(0xまたは0Xで始まる)、2進数(0bまたは0Bで始まる)、8進数(0、0oまたは0Oで始まる)。
浮動小数点形式
浮動小数点数は2つの形式で記述できます
[-+]{N}.{M} [-+]{N}.{M}[eE][-+]{exp}
{N}{M}は数値です。{N}{M}の両方が存在する必要があり、数字のみを含めることができます。[-+]はオプションのプラスまたはマイナス記号があることを意味します。{exp}は指数であり、10のべき乗です。小数点のみが受け入れられ、コンマは受け入れられません。現在のロケールがどうであれ。
例:123.456 +0.0001 55.0 -0.123 1.234e03 1.0E-6 -3.1416e+88
これらは無効です:3。空の {M} 1e40 欠落している .{M}
理論的根拠:浮動小数点数が導入される前は、テキスト "123.456" は、両方とも文字列に変換されて連結された2つの数値 "123" と "456" として解釈され、結果として文字列 "123456" が生成されました。これは無意味であると考えられ、Vimスクリプトで意図的に使用されていることがわからなかったため、浮動小数点数の通常の表記法を使用できるようにするために、この下位互換性のない変更が受け入れられました。
float-pi float-e コピー&ペーストに便利な値
:let pi = 3.14159265359
:let e  = 2.71828182846
または、浮動小数点リテラルとして書き込みたくない場合は、次のような関数を使用することもできます
:let pi = acos(-1.0)
:let e  = exp(1.0)
浮動小数点精度
浮動小数点数の精度と範囲は、Vimがコンパイルされたライブラリで "double" が何を意味するかに依存します。これを実行時に変更する方法はありません。
Floatを表示する場合のデフォルトは、printf("%g", f) を使用するように、小数点以下6桁を使用することです。printf()関数を使用する場合、別のものを選択できます。例
:echo printf('%.15e', atan(1))
7.853981633974483e-01
"string" 文字列定数 expr-quote
二重引用符が使用されていることに注意してください。
文字列定数は、これらの特殊文字を受け入れます:\... 3桁の8進数 (例: "\316") \.. 2桁の8進数 (数字以外が続く必要あり) \. 1桁の8進数 (数字以外が続く必要あり) \x.. 2つの16進数で指定されたバイト (例: "\x1f") \x. 1つの16進数で指定されたバイト (16進数以外の文字が続く必要あり) \X.. \x..と同じ \X. \x.と同じ \u.... 最大4つの16進数で指定された文字。UTF-8として保存 (例: "\u02a4") \U.... \uと同じだが、最大8つの16進数が許可される。 \b バックスペース <BS> \e エスケープ <Esc> \f 改ページ 0x0C \n 改行 <NL> \r 復帰 <CR> \t タブ <Tab> \\ バックスラッシュ \" 二重引用符 \<xxx> "xxx" という名前の特殊キー。例:CTRL-Wの場合は "\<C-W>" 。これはマッピングで使用するためのもので、0x80バイトはエスケープされます。二重引用符文字を使用するには、エスケープする必要があります: "<M-\">"。UTF-8文字を取得するために<Char-xxxx>を使用しないでください。上記のように\uxxxxを使用してください。 \<*xxx> \<xxx>と同様ですが、文字に含めるのではなく、修飾子を先頭に追加します。たとえば、"\<C-w>" は1文字の0x17ですが、"\<*C-w>" は4バイトです。CTRL修飾子の3バイトと、文字 "W" です。
"\xff"はバイト255として保存されます。これは一部のエンコーディングでは無効になる場合があります。UTF-8として文字255を正しく保存するには、"\u00ff"を使用してください。
"\000" と "\x00" は文字列の末尾を強制的に指定することに注意してください。

blob-リテラル blob-literal E973

0zまたは0Zで始まり、任意の数のバイトを含む16進数。シーケンスは偶数の16進文字数である必要があります。例
:let b = 0zFF00ED015DAF

リテラル文字列 literal-string E115

文字列 文字列定数 expr-'
単一引用符が使用されていることに注意してください。
この文字列はそのまま解釈されます。バックスラッシュは削除されず、特別な意味を持ちません。唯一の例外は、2つの引用符が1つの引用符を表すことです。
単一引用符で囲まれた文字列は、パターンに役立ちます。バックスラッシュを二重にする必要がないためです。次の2つのコマンドは同等です
if a =~ "\\s*"
if a =~ '\s*'

補間文字列 $quote interpolated-string

$"文字列" 補間文字列定数 expr-$quote
$'文字列' 補間リテラル文字列定数 expr-$'
補間文字列は、stringliteral-stringの拡張であり、Vimスクリプト式(expr1を参照)を含めることができます。値を返す式は中括弧で囲むことができます。値は文字列に変換されます。すべてのテキストと式の結果が連結されて、新しい文字列が作成されます。E1278
文字列の内容に開き中括弧 '{' または閉じ中括弧 '}' を含めるには、それを2倍にします。二重引用符付きの文字列の場合、バックスラッシュを使用することもできます。単一の閉じ中括弧 '}' はエラーになります。
let your_name = input("What's your name? ")
あなたの名前は何ですか?ピーター
echo
echo $"Hello, {your_name}!"
こんにちは、ピーター!
echo $"The square root of {{9}} is {sqrt(9)}"
{9} の平方根は3.0です
文字列オフセットエンコーディング
文字列は複数の文字で構成されています。UTF-8は、ASCII文字には1バイト、他のラテン文字には2バイト、その他の文字にはそれ以上のバイトを使用します。
文字列オフセットは、文字またはバイトをカウントできます。他のプログラムでは、UTF-16エンコーディング(16ビットワード)とUTF-16ワードのオフセットを使用する場合があります。一部の関数はバイトオフセットを使用します。通常はUTF-8エンコーディングの場合です。その他の関数は文字オフセットを使用します。この場合、エンコーディングは関係ありません。
文字列 "a©😊" の異なるオフセットを以下に示します
UTF-8 オフセット: [0]: 61, [1]: C2, [2]: A9, [3]: F0, [4]: 9F, [5]: 98, [6]: 8A UTF-16 オフセット: [0]: 0061, [1]: 00A9, [2]: D83D, [3]: DE0A UTF-32 (文字) オフセット: [0]: 00000061, [1]: 000000A9, [2]: 0001F60A
文字で "g8" および "ga" コマンドを使用して、10進数/16進数/8進数の値を確認できます。
関数byteidx()utf16idx()charidx()を使用して、これらのインデックスを変換できます。関数strlen()strutf16len()strcharlen()は、それぞれ文字列のバイト数、UTF-16コード単位数、文字数を返します。

オプション expr-option E112 E113

&option オプション値、可能な場合はローカル値 &g:option グローバルオプション値 &l:option ローカルオプション値
echo "tabstop is " .. &tabstop
if &expandtab
ここには、任意のオプション名を使用できます。optionsを参照してください。ローカル値を使用し、バッファローカルまたはウィンドウローカルの値がない場合、グローバル値が使用されます。

レジスタ expr-register @r

@r レジスタ 'r' の内容
結果は、名前付きレジスタの内容を単一の文字列として取得したものです。必要な場所に改行が挿入されます。名前のないレジスタの内容を取得するには、@" または @@ を使用します。利用可能なレジスタの説明については、registersを参照してください。
「=」レジスタを使用すると、評価された結果ではなく、式そのものが得られます。評価するにはeval()を使用してください。
ネスト expr-nesting E110 ------- (expr1) ネストされた式

環境変数 expr-env

$VAR 環境変数
環境変数の文字列値。定義されていない場合は、結果は空の文字列になります。
getenv() および setenv() 関数も使用でき、英数字以外の名前の環境変数にも機能します。 environ() 関数を使用すると、すべての環境変数を含む辞書を取得できます。
expr-env-expand
$VARを直接使用する場合とexpand("$VAR")を使用する場合の違いに注意してください。直接使用すると、現在のVimセッション内で認識されている環境変数のみが展開されます。 expand()を使用すると、まず現在のVimセッション内で認識されている環境変数が使用されます。それが失敗した場合、シェルを使用して変数が展開されます。これは遅くなる可能性がありますが、シェルが認識しているすべての変数を展開します。例:
:echo $shell
:echo expand("$shell")
最初のものは何もエコーしない可能性がありますが、2番目のものは$shell変数をエコーします(シェルがそれをサポートしている場合)。

内部変数 expr-variable

変数 内部変数 下記のinternal-variablesを参照してください。

関数呼び出し expr-function E116 E118 E119 E120

function(expr1, ...) 関数呼び出し 下記のfunctionsを参照してください。

ラムダ式 expr-lambda lambda

{args -> expr1} ラムダ式 E451
ラムダ式は、expr1を評価した結果を返す新しい無名関数を作成します。ラムダ式は、次の点でuser-functionと異なります。
1. ラムダ式の本体はexpr1であり、Exコマンドのシーケンスではありません。 2. 引数にはプレフィックス「a:」を使用しないでください。例:
:let F = {arg1, arg2 -> arg1 - arg2}
:echo F(5, 2)
3
引数はオプションです。例:
:let F = {-> 'error function'}
:echo F('ignored')
エラー関数 closure
ラムダ式は、外側のスコープの変数と引数にアクセスできます。これはしばしばクロージャと呼ばれます。例:関数スコープにすでに存在している間に、ラムダ内で「i」と「a:arg」が使用されています。これらは関数が戻った後でも有効です。
:function Foo(arg)
:  let i = 3
:  return {x -> x + i - a:arg}
:endfunction
:let Bar = Foo(4)
:echo Bar(6)
5 変数が機能するために、ラムダが定義される前に外側のスコープに存在する必要があることに注意してください。:func-closureも参照してください。
ラムダとクロージャのサポートは、以下で確認できます。
if has('lambda')
sort()map()、およびfilter()でラムダ式を使用する例
:echo map([1, 2, 3], {idx, val -> val + 1})
[2, 3, 4]
:echo sort([3,7,2,1,4], {a, b -> a - b})
[1, 2, 3, 4, 7]
ラムダ式はジョブとタイマーにも役立ちます
:let timer = timer_start(500,
                \ {-> execute("echo 'Handler called'", "")},
                \ {'repeat': 3})
Handler called Handler called Handler called
クロージャが依存するコンテキストによって参照されている場合、メモリが使用され、解放されない可能性があることに注意してください。
function Function()
   let x = 0
   let F = {-> x}
 endfunction
クロージャは関数スコープの「x」を使用し、同じスコープの「F」はクロージャを参照します。このサイクルにより、メモリが解放されません。推奨:これをしないでください。
execute()を使用してExコマンドを実行する方法に注目してください。それは醜いですが。
ラムダ式には「<lambda>42」のような内部名があります。ラムダ式のエラーが発生した場合、次のコマンドでそれを特定できます。
:function <lambda>42
こちらも参照してください:numbered-function

3. 内部変数 internal-variables E461

内部変数名は、文字、数字、および「_」で構成できます。ただし、数字で始めることはできません。中括弧を使用することもできます。curly-braces-namesを参照してください。
内部変数は、":let"コマンド:letで作成されます。内部変数は、":unlet"コマンド:unletで明示的に破棄されます。内部変数ではない名前を使用するか、破棄された変数を参照すると、エラーが発生します。
変数スコープ
変数にはいくつかの名前空間があります。どの名前空間を使用するかは、先頭に何が付けられているかによって指定されます。
(何もなし) 関数内:関数ローカル。それ以外の場合:グローバル バッファ変数 b: 現在のバッファにローカル。 ウィンドウ変数 w: 現在のウィンドウにローカル。 タブページ変数 t: 現在のタブページにローカル。 グローバル変数 g: グローバル。 ローカル変数 l: 関数にローカル。 スクリプト変数 s: :source されたVimスクリプトにローカル。 関数の引数 a: 関数の引数(関数内のみ)。 Vim変数 v: グローバル、Vimによって事前定義されています。
スコープ名自体は辞書として使用できます。たとえば、すべてのスクリプトローカル変数を削除するには
:for k in keys(s:)
:    unlet s:[k]
:endfor
バッファ変数 b:var b: 「b:」が前に付いた変数名は、現在のバッファにローカルです。したがって、各バッファに対して1つずつ、複数の「b:foo」変数を持つことができます。この種の変数は、バッファがワイプアウトされるか、:bdeleteで削除されると削除されます。
1つのローカルバッファ変数が事前定義されています:b:changedtick changetick b:changedtick 現在のバッファへの変更の総数。変更ごとにインクリメントされます。この場合、アンドゥコマンドも変更です。バッファを書き込むときに'modified'をリセットすることもカウントされます。これは、バッファが変更された場合にのみアクションを実行するために使用できます。例:
:if my_changedtick != b:changedtick
:        let my_changedtick = b:changedtick
:        call My_Update()
:endif
b:changedtick変数を変更または削除することはできません。
ウィンドウ変数 w:var w: 「w:」が前に付いた変数名は、現在のウィンドウにローカルです。ウィンドウが閉じられると削除されます。
タブページ変数 t:var t: 「t:」が前に付いた変数名は、現在のタブページにローカルです。タブページが閉じられると削除されます。
グローバル変数 g:var g: 関数内では、グローバル変数にアクセスするには「g:」を使用します。これを省略すると、関数にローカルな変数にアクセスします。ただし、必要であれば、他の場所でも「g:」を使用できます。
ローカル変数 l:var l: 関数内では、何も付けずにローカル変数にアクセスします。ただし、必要であれば「l:」を付けることもできます。ただし、「l:」を付けないと、予約済みの変数名に遭遇する可能性があります。たとえば、「count」です。それ自体では、「v:count」を参照します。「l:count」を使用すると、同じ名前のローカル変数を持つことができます。
スクリプト変数 s:var Vimスクリプトでは、「s:」で始まる変数を使用できます。スクリプトの外部からアクセスすることはできないため、スクリプトに対してローカルです。
それらは以下で使用できます
スクリプトのソース中に実行されるコマンド
スクリプトで定義された関数
スクリプトで定義された自動コマンド
スクリプトで定義された関数および自動コマンドで定義された関数および自動コマンド(再帰的)
スクリプトで定義されたユーザー定義コマンド 以下では使用できません
これからソースされた他のスクリプト
マッピング
メニュー
スクリプト変数を使用して、グローバル変数名との競合を回避できます。この例を見てください
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()でアクセス可能になります。
同じスクリプトが再度ソースされると、同じスクリプト変数が使用されます。Vimが実行されている限り、それらは有効なままです。これは、カウンターを維持するために使用できます
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を使用してください。

事前定義されたVIM変数 vim-variable v:var v:

E963
すべての組み込み変数のアルファベット順のリストと詳細は、別のヘルプファイルにあります:vvars

4. 組み込み関数 vim-function functions

Vimscriptサブシステム(内部では「eval」と呼ばれます)は、組み込み関数を提供します。スクリプトはuser-functionも定義できます。
トピック別に関数を閲覧するには、function-listを参照してください。
すべての組み込み関数のアルファベット順のリストと詳細は、別のヘルプファイルにあります:組み込み関数

5. 関数の定義 user-function

新しい関数を定義できます。これらは組み込み関数とまったく同様に呼び出すことができます。関数は引数を取り、一連のExコマンドを実行し、値を返すことができます。
関数の定義に関するほとんどの情報は、userfunc.txt にあります。

6. 波括弧の名前 curly-braces-names

変数が使用できるほとんどの場所で、「波括弧の名前」変数を使用できます。これは、次のように 1 つ以上の式が波括弧 {} で囲まれた通常の変数名です。
my_{adjective}_variable
Vim がこれに遭遇すると、波括弧内の式を評価し、その式を置き換え、全体を変数名として再解釈します。したがって、上記の例では、変数 "adjective" が "noisy" に設定されている場合、参照は "my_noisy_variable" になります。一方、"adjective" が "quiet" に設定されている場合は、"my_quiet_variable" になります。
このアプリケーションの 1 つは、オプションの値によって制御される変数のセットを作成することです。たとえば、次のステートメント。
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" であり、これは変数名ではないためです。
curly-braces-function-names
同様の方法で、評価された名前で関数を呼び出し、定義することができます。例:
:let func_end='whizz'
:call my_func_{func_end}(parameter)
これにより、関数 "my_func_whizz(parameter)" が呼び出されます。
これは機能しません。
:let i = 3
:let @{i} = ''  " error
:echo @{i}      " error

7. コマンド expression-commands

:let {var-name} = {expr1} :let E18 内部変数 {var-name} を式 {expr1} の結果に設定します。変数は {expr} から型を取得します。{var-name} がまだ存在しない場合は、作成されます。
:let {var-name}[{idx}] = {expr1} E689
リスト項目を式 {expr1} の結果に設定します。{var-name} はリストを参照する必要があり、{idx} はそのリスト内の有効なインデックスである必要があります。ネストされたリストの場合、インデックスを繰り返すことができます。これは、List に項目を追加するために使用することはできません。これは、String内のバイトを設定するために使用することはできません。これは次のように行うことができます。
:let var = var[0:2] .. 'X' .. var[4:]
{var-name}Blob の場合、{idx} は blob の長さになり、その場合は 1 バイトが追加されます。
E711 E719 :let {var-name}[{idx1}:{idx2}] = {expr1} E708 E709 E710 List 内の項目のシーケンスを式 {expr1} の結果に設定します。これは、正しい数の項目を持つリストである必要があります。{idx1} は省略できます。代わりにゼロが使用されます。{idx2} は省略できます。リストの末尾を意味します。選択した項目の範囲がリストの末尾を一部過ぎている場合、項目が追加されます。
:let+= :let-= :let*= :let/= :let%= :let.= :let..= E734 :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}" のようになります。:let {var} ..= {expr1} は ":let {var} = {var} .. {expr1}" のようになります。{var} がまだ設定されていない場合、および {var}{expr1} の型が演算子に適合しない場合、これらは失敗します。+= は新しいものを作成するのではなく、List または Blob をインプレースで変更します。
:let ${env-name} = {expr1} :let-environment :let-$ 環境変数 {env-name} を式 {expr1} の結果に設定します。型は常にStringです。:let ${env-name} .= {expr1} {expr1} を環境変数 {env-name} に追加します。環境変数がまだ存在しない場合は、"=" のように機能します。
:let @{reg-name} = {expr1} :let-register :let-@{expr1} の結果をレジスタ {reg-name} に書き込みます。{reg-name} は 1 文字である必要があり、書き込み可能なレジスタの名前である必要があります(registers を参照してください)。無名レジスタには "@@" を、検索パターンには "@/" を使用できます。{expr1} の結果が <CR> または <NL> で終わる場合、レジスタは行単位になり、それ以外の場合は文字単位に設定されます。これは、最後の検索パターンをクリアするために使用できます。
:let @/ = ""
これは空の文字列を検索するのとは異なり、すべてに一致します。
:let @{reg-name} .= {expr1} {expr1} をレジスタ {reg-name} に追加します。レジスタが空の場合、{expr1} に設定するようなものです。
:let &{option-name} = {expr1} :let-option :let-& オプション {option-name} を式 {expr1} の結果に設定します。String または Number の値は、常にオプションの型に変換されます。ウィンドウまたはバッファにローカルなオプションの場合、効果は :set コマンドを使用するのとまったく同じです。ローカル値とグローバル値の両方が変更されます。例:
:let &path = &path .. ',/usr/local/include'
:let &{option-name} .= {expr1} 文字列オプションの場合:{expr1} を値に追加します。:set+= のようにコンマは挿入しません。
:let &{option-name} += {expr1} :let &{option-name} -= {expr1} 数値またはブールオプションの場合:{expr1} を加算または減算します。
:let &l:{option-name} = {expr1} :let &l:{option-name} .= {expr1} :let &l:{option-name} += {expr1} :let &l:{option-name} -= {expr1} 上記と同様ですが、オプションのローカル値のみを設定します(存在する場合)。:setlocal のように機能します。
:let &g:{option-name} = {expr1} :let &g:{option-name} .= {expr1} :let &g:{option-name} += {expr1} :let &g:{option-name} -= {expr1} 上記と同様ですが、オプションのグローバル値のみを設定します(存在する場合)。:setglobal のように機能します。
:let [{name1}, {name2}, ...] = {expr1} :let-unpack E687 E688 {expr1}List に評価される必要があります。リストの最初の項目は {name1} に、2 番目の項目は {name2} に、といったように割り当てられます。名前の数は、List 内の項目数と一致する必要があります。各名前は、上記で説明した ":let" コマンドの項目の 1 つにすることができます。例:
:let [s, item] = GetItem(s)
詳細:{expr1} が最初に評価され、次に代入が順番に行われます。これは、{name2}{name1} に依存する場合に重要です。例:
:let x = [0, 1]
:let i = 0
:let [i, x[i]] = [1, 2]
:echo x
結果は [0, 2] です。
:let [{name1}, {name2}, ...] .= {expr1} :let [{name1}, {name2}, ...] += {expr1} :let [{name1}, {name2}, ...] -= {expr1} 上記と同様ですが、List の各項目に対して値を追加/加算/減算します。
:let [{name}, ..., ; {lastname}] = {expr1} E452
:let-unpack と同様ですが、List には名前よりも多くの項目がある場合があります。残りの項目のリストが {lastname} に割り当てられます。残りの項目がない場合、{lastname} は空のリストに設定されます。例:
:let [a, b; rest] = ["aval", "bval", 3, 4]
:let [{name}, ..., ; {lastname}] .= {expr1} :let [{name}, ..., ; {lastname}] += {expr1} :let [{name}, ..., ; {lastname}] -= {expr1} 上記と同様ですが、List の各項目に対して値を追加/加算/減算します。
:let=<< :let-heredoc E990 E991 E172 E221 E1145 :let {var-name} =<< [trim] [eval] {endmarker} テキスト... テキスト... {endmarker} 内部変数 {var-name} を、文字列 {endmarker} で区切られたテキスト行を含む List に設定します。
"eval" が指定されていない場合、テキストの各行は literal-string として使用されます。ただし、単一引用符を二重にする必要はありません。"eval" が指定されている場合、{expr} 形式の Vim 式が評価され、interpolated-string のように、結果が式を置き換えます。$HOME が展開される例:
let lines =<< trim eval END
  some text
  See the file {$HOME}/.vimrc
  more text
END
1 行に複数の Vim 式を含めることができますが、式が複数行にまたがることはできません。式評価が失敗すると、代入も失敗します。
{endmarker} には空白文字を含めることはできません。{endmarker} は小文字で始めることはできません。最後の行は、他の文字なしで {endmarker} 文字列のみで終わる必要があります。{endmarker} の後の空白に注意してください!
"trim" がない場合、テキストの行にある空白文字は保持されます。"trim" が {endmarker} の前に指定されている場合、インデントが削除されるため、次のように実行できます。
let text =<< trim END
   if ok
     echo 'done'
   endif
END
結果:["if ok", " echo 'done'", "endif"] マーカーは "let" と整列する必要があり、最初の行のインデントはすべてのテキスト行から削除されます。具体的には、最初の空でないテキスト行の先頭のインデントと完全に一致するすべての先頭のインデントが、入力行から削除されます。let の前の先頭のインデントと完全に一致するすべての先頭のインデントは、{endmarker} を含む行から削除されます。スペースとタブの違いがここで重要であることに注意してください。
{var-name} がまだ存在しない場合は、作成されます。別のコマンドを続けることはできませんが、コメントを続けることはできます。
行継続を適用しないようにするには、'cpoptions' に 'C' を追加することを検討してください。
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
E121
:let {var-name} .. 変数 {var-name} の値をリスト表示します。複数の変数名を指定できます。ここで認識される特殊な名前: E738
g: グローバル変数 b: ローカルバッファ変数 w: ローカルウィンドウ変数 t: ローカルタブページ変数 s: スクリプトローカル変数 l: ローカル関数変数 v: Vim 変数。
:let すべての変数の値をリスト表示します。変数の型は値の前に示されます: <nothing> String # Number * Funcref
:unl[et][!] {name} ... :unlet :unl E108 E795 内部変数 {name} を削除します。複数の変数名を指定でき、すべて削除されます。名前は、リストまたは辞書の項目にすることもできます。 [!] を指定すると、存在しない変数に対するエラーメッセージは表示されません。リストから1つ以上の項目を削除できます
:unlet list[3]          " remove fourth item
:unlet list[3:]   " remove fourth item to last
辞書からは一度に1つの項目を削除できます
:unlet dict['two']
:unlet dict.two
これは、使用済みのグローバル変数やスクリプトローカル変数 (スクリプトが終了しても削除されない) をクリーンアップするのに特に役立ちます。関数ローカル変数は、関数が終了すると自動的に削除されます。
:unl[et] ${env-name} ... :unlet-environment :unlet-$ 環境変数 {env-name} を削除します。 :unlet コマンドで {name} と ${env-name} を混在させることができます。存在しない変数に対してエラーメッセージは表示されません。! がなくても同様です。システムが環境変数の削除をサポートしていない場合は、空になります。
:cons :const :cons[t] {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
E995
:const で既存の変数を指定するとエラーになります。
:let x = 1
:const x = 1  " Error!
E996
環境変数、オプション値、およびレジスタ値はロックできないため、ここでは使用できないことに注意してください。
:cons[t] :cons[t] {var-name} 引数が指定されていない場合、または {var-name} のみが指定されている場合、動作は :let と同じです。
:lockv[ar][!] [depth] {name} ... :lockvar :lockv 内部変数 {name} をロックします。ロックとは、(ロック解除されるまで) 変更できなくなることを意味します。ロックされた変数は削除できます
:lockvar v
:let v = 'asdf'          " fails!
:unlet v          " works
E741 E940 E1122 ロックされた変数を変更しようとすると、「E741: Value is locked: {name}」というエラーメッセージが表示されます。組み込み変数をロックまたはロック解除しようとすると、「E940: Cannot lock or unlock variable {name}」というエラーメッセージが表示されます。
[depth] は、リストまたは辞書をロックするときに関連します。ロックの深さを指定します: 0 変数 {name} をロックしますが、その値はロックしません。 1 リストまたは辞書自体をロックし、項目の追加または削除はできませんが、値を変更することはできます。 2 値もロックし、項目を変更することはできません。項目がリストまたは辞書の場合、項目の追加または削除はできませんが、値を変更することはできます。 3 レベルが1つ深い、リスト / 辞書内のリスト / 辞書の場合、2 と同様。デフォルトの [depth] は 2 です。したがって、{name}リストまたは辞書の場合、値は変更できません。
[depth] 0 の例
let mylist = [1, 2, 3]
lockvar 0 mylist
let mylist[0] = 77        " OK
call add(mylist, 4)        " OK
let mylist = [7, 8, 9]  " Error!
E743
無制限の深さには [!] を使用し、[depth] を省略します。ただし、ループを捕捉するために、最大深度は100です。
2つの変数が同じリストを参照しているときに、その一方をロックすると、もう一方の変数を通して使用した場合もリストがロックされることに注意してください。例
:let l = [0, 1, 2, 3]
:let cl = l
:lockvar l
:let cl[1] = 99                " won't work!
これを避けるために、リストのコピーを作成することが必要な場合があります。 deepcopy() を参照してください。
:unlo[ckvar][!] [depth] {name} ... :unlockvar :unlo 内部変数 {name} をロック解除します。:lockvar の反対を行います。
{name} が存在しない場合はエラーは表示されません。
:if {expr1} :if :end :endif :en E171 E579 E580 :en[dif] {expr1} がゼロ以外と評価された場合、次の対応する :else または :endif までのコマンドを実行します。短い形式も機能しますが、混乱を避けて自動インデントを適切に機能させるために、常に :endif を使用することをお勧めします。
Vim バージョン 4.5 から 5.0 まで、:if:endif の間のすべての Ex コマンドは無視されます。これらの 2 つのコマンドは、下位互換性のある方法で将来の拡張を可能にするためだけに使用されていました。ネストが許可されました。: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 の間では正しく機能しません。
:else :el E581 E583 :el[se] 以前に実行されていなかった場合、次の対応する :else または :endif までのコマンドを実行します。
:elseif :elsei E582 E584 :elsei[f] {expr1} :else :if の短縮形です。追加の :endif はありません。
:wh[ile] {expr1} :while :endwhile :wh :endw E170 E585 E588 E733 :endw[hile] {expr1} がゼロ以外と評価される限り、:while:endwhile の間のコマンドを繰り返します。ループ内のコマンドでエラーが検出されると、endwhile の後に実行が続行されます。例
:let lnum = 1
:while lnum <= line("$")
   :call FixLine(lnum)
   :let lnum = lnum + 1
:endwhile
注: :append コマンドと :insert コマンドは、:while ループと :for ループ内では正しく機能しません。
: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
リストの順序を変更 (たとえば、sort() や reverse() を使用) すると、予期しない影響がある場合があります。
{object}Blobの場合、Vim は常にコピーを作成して反復処理を行います。リストとは異なり、Blobを変更しても反復処理には影響しません。
{object}文字列の場合、各項目は1文字と結合文字を含む文字列です。
:for [{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
:continue :con E586 :con[tinue] :while または :for ループ内で使用すると、ループの先頭に戻ります。
ループ内の :try の後、一致する :finally (存在する場合) の前に使用すると、一致する :endtry までの :finally に続くコマンドが最初に実行されます。このプロセスは、ループ内のすべてのネストされた :try に適用されます。最も外側の :endtry は、ループの先頭に戻ります。
:break :brea E587 :brea[k] :while または :for ループ内で使用すると、対応する :endwhile または :endfor の後のコマンドにスキップします。ループ内の :try の後、対応する :finally (存在する場合) の前に使用された場合、:finally に続くコマンドが、対応する :endtry まで最初に実行されます。このプロセスは、ループ内のすべてのネストされた :try に適用されます。最も外側の :endtry は、ループ後のコマンドにジャンプします。
:try :try :endt :endtry E600 E601 E602 :endt[ry] :try:endtry の間のコマンドのエラー処理を変更します。これには、:source コマンド、関数呼び出し、または自動コマンドの呼び出しを介して実行されるすべてが含まれます。
エラーまたは割り込みが検出され、後に :finally コマンドがある場合、実行は :finally の後で続行されます。それ以外の場合、またはその後 :endtry に到達した場合、次の(動的な)周囲の :try で対応する :finally などがないかどうかが確認されます。その後、スクリプト処理は終了します。関数定義に "abort" 引数があるかどうかは関係ありません。例
try | call Unknown() | finally | echomsg "cleanup" | endtry
echomsg "not reached"
さらに、:try:endtry の内部でのエラーまたは割り込みは、例外に変換されます。これは、:throw コマンドによってスローされたかのようにキャッチできます(:catch を参照)。この場合、スクリプト処理は終了しません。
値 "Vim:Interrupt" は、割り込み例外に使用されます。Vim コマンドのエラーは "Vim({command}):{errmsg}" 形式の値に変換され、その他のエラーは "Vim:{errmsg}" 形式の値に変換されます。{command} は完全なコマンド名であり、{errmsg} はエラー例外がキャッチされなかった場合に表示されるメッセージであり、常にエラー番号で始まります。例
try | sleep 100 | catch /^Vim:Interrupt$/ | endtry
try | edit | catch /^Vim(edit):E\d\+/ | echo "error" | endtry
:cat :catch E603 E604 E605 :cat[ch] /{pattern}/ :catch が属する同じ :try に属する次の :catch:finally、または :endtry までの次のコマンドは、{pattern} に一致する例外がスローされ、前の :catch でまだキャッチされていない場合に実行されます。それ以外の場合、これらのコマンドはスキップされます。{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" することは、ロケールによって異なる場合があるため、信頼性がありません。
:fina :finally E606 E607 :fina[lly] 対応する :try:finally の間の部分が、:finally にフォールスルーした場合、または :continue:break:finish、または :return、あるいはエラー、割り込み、または例外(:throw を参照)によって離れるときは常に、次の対応する :endtry までのコマンドが実行されます。
:th :throw E608 :th[row] {expr1} {expr1} が評価され、例外としてスローされます。:throw:try の後、最初の対応する :catch の前に使用された場合、{expr1} に一致する最初の :catch に到達するまでコマンドはスキップされます。そのような :catch がない場合、または :throw:catch の後、:finally の前に使用された場合、:finally に続くコマンド(存在する場合)は、対応する :endtry まで実行されます。:throw:finally の後にある場合は、:endtry までのコマンドはスキップされます。:endtry で、このプロセスは、一致する :catch が見つかるまで、次の動的な周囲の :try (呼び出し関数またはソーススクリプトで見つかる場合がある) に対して再び適用されます。例外がキャッチされない場合、コマンド処理は終了します。例
:try | throw "oops" | catch /^oo/ | echo "caught" | endtry
エラーにより解析でライン全体がスキップされ、コマンドを区切る "|" が見えない場合に備えて、"catch" を別の行にする必要がある場合があることに注意してください。
:ec :echo :ec[ho] {expr1} .. 各 {expr1} を間にスペースを入れてエコーします。最初の {expr1} は新しい行で開始します。:comment も参照してください。新しい行を開始するには "\n" を使用します。カーソルを最初の列に移動するには "\r" を使用します。:echohl コマンドで設定された強調表示を使用します。コメントを後に続けることはできません。例
:echo "the value of 'shell' is" &shell
:echo-redraw
後で再描画すると、メッセージが再び消える場合があります。そして、Vim は通常、コマンドのシーケンスが完了するまで再描画を延期するため、これが頻繁に発生します。:echo の前のコマンドが後で再描画を引き起こす(再描画は多くの場合、何かを入力するまで延期される)のを避けるには、:redraw コマンドで再描画を強制します。例
:new | redraw | echo "there is a new window"
:echo-self-refer
ネストされたコンテナを印刷する場合、echo は自己参照コンテナの 2 番目の出現箇所を "[...@level]"(自己参照 List)または "{...@level}"(自己参照 Dict)を使用して印刷します。
:let l = []
:call add(l, l)
:let l2 = []
:call add(l2, [l2])
:echo l l2
"[[...@0]] [[[...@0]]]" がエコーされます。"l" をエコーすると、l が最初に 2 番目のレベルで発生するため、"[[[...@1]]]" がエコーされます。
:echon
:echon {expr1} .. 各 {expr1} を何も追加せずにエコーします。:comment も参照してください。:echohl コマンドで設定された強調表示を使用します。コメントを後に続けることはできません。例
:echon "the value of 'shell' is " &shell
Vim コマンドである :echo を使用する場合と、外部シェルコマンドである :!echo を使用する場合の違いに注意してください。
:!echo %                --> filename
":!" の引数は展開されます。:_% を参照してください。
:!echo "%"                --> filename or "filename"
前の例と同様です。二重引用符が表示されるかどうかは、'shell' によって異なります。
:echo %                        --> nothing
'%' は式では不正な文字です。
:echo "%"                --> %
これは単に '%' 文字をエコーします。
:echo expand("%")        --> filename
これは expand() 関数を呼び出して、'%' を展開します。
:echoh :echohl :echoh[l] {name} 後続の :echo:echon、および :echomsg コマンドに、ハイライトグループ {name} を使用します。input() プロンプトにも使用されます。例
:echohl WarningMsg | echo "Don't panic!" | echohl None
グループを "None" に戻すことを忘れないでください。そうしないと、後続のすべての echo が強調表示されます。
:echom :echomsg :echom[sg] {expr1} .. 式を真のメッセージとしてエコーし、メッセージを message-history に保存します。:echo コマンドと同様に、引数の間にスペースが配置されます。ただし、印刷できない文字は解釈されずに表示されます。解析は :echo とは少し異なり、:execute に似ています。すべての式は、最初に評価および連結されてから、何もエコーされません。式が Number または String に評価されない場合は、string() を使用して文字列に変換します。:echohl コマンドで設定された強調表示を使用します。例
:echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see."
画面が再描画されたときにメッセージが消えるのを避けるには、:echo-redraw を参照してください。:echoe :echoerr :echoe[rr] {expr1} .. 式をエラーメッセージとしてエコーし、メッセージを message-history に保存します。スクリプトまたは関数で使用すると、行番号が追加されます。引数の間にスペースが配置されるのは :echomsg コマンドと同様です。try 条件内で使用すると、メッセージは代わりにエラー例外として発生します(try-echoerr を参照)。例
:echoerr "This script just failed!"
強調表示されたメッセージのみが必要な場合は、:echohl を使用します。また、ビープ音を鳴らすには
:exe "normal \<Esc>"
:eval
:eval {expr} {expr} を評価して結果を破棄します。例
:eval Getlist()->Filter()->append('$')
結果の値は使用されないため、式には副作用があるはずです。この例では、append() 呼び出しによってテキスト付きの List がバッファーに追加されます。これは :call に似ていますが、任意の式で動作します。
コマンドは :ev または :eva に短縮できますが、これらは認識しにくいため、使用しないでください。
コマンドは "|" と別のコマンドを続けることはできません。 "|" は式の一部と見なされるためです。
:exe :execute :exe[cute] {expr1} .. {expr1} の評価から得られる文字列を Ex コマンドとして実行します。複数の引数は、間にスペースを入れて連結されます。余分なスペースを避けるには、".." 演算子を使用して文字列を 1 つの引数に連結します。{expr1} は処理されたコマンドとして使用され、コマンドライン編集キーは認識されません。コメントを後に続けることはできません。例
:execute "buffer" nextbuf
:execute "normal" count .. "w"
":execute" は、'|' を受け入れないコマンドにコマンドを追加するために使用できます。例
:execute '!ls' | echo "theend"
":execute" は、":normal" コマンドの Vim スクリプトで制御文字を入力する必要がないようにするための優れた方法でもあります。
:execute "normal ixxx\<Esc>"
これには <Esc> 文字があります。expr-string を参照してください。
ファイル名内の特殊文字を正しくエスケープするように注意してください。Vim コマンドには fnameescape() 関数を、:! コマンドには shellescape() を使用できます。例
:execute "e " .. fnameescape(filename)
:execute "!ls " .. shellescape(filename, 1)
注意: 実行される文字列は任意のコマンドラインにできますが、"if"、"while"、および "for" で開始または終了すると、コマンドがスキップされた場合、":execute" が評価されず、Vim はブロックがどこで開始および終了するかを追跡できなくなるため、常に機能するとは限りません。また、"break" および "continue" は ":execute" の内側に含めないでください。次の例は、":execute" が評価されず、Vim が "while" を認識せず、":endwhile" を見つけたためエラーが発生するため、機能しません。
:if 0
: execute 'while i > 5'
:  echo "test"
: endwhile
:endif
"while" コマンドまたは "if" コマンドを完全に実行された文字列に含めることはできます。
:execute 'while i < 5 | echo i | let i = i + 1 | endwhile'
:exe-comment
":execute"、":echo"、および ":echon" は、'"' を文字列の開始として認識するため、コメントを直接後に続けることはできません。ただし、'|' の後にコメントを使用できます。例
:echo "foo" | "this is a comment

8. 例外処理 exception-handling

Vim スクリプト言語には、例外処理機能が含まれています。このセクションでは、Vim スクリプトでこの機能を使用する方法について説明します。
例外は、エラー時または割り込み時に Vim によって発生する場合があります。catch-errors および catch-interrupt を参照してください。":throw" コマンドを使用して例外を明示的にスローすることもできます。throw-catch を参照してください。

TRY 条件式 try-conditionals

例外はキャッチしたり、クリーンアップコードを実行させたりすることができます。try 条件式を使用すると、キャッチ句 (例外をキャッチする) や finally 句 (クリーンアップのために実行される) を指定できます。try 条件式は、:try コマンドで始まり、対応する :endtry コマンドで終わります。その間には、:catch コマンドを使用してキャッチ句を開始したり、:finally コマンドを使用して finally 句を開始したりできます。キャッチ句は複数でも 1 つもなくてもかまいませんが、finally 句は最大で 1 つしかなく、キャッチ句を後に続けることはできません。キャッチ句と finally 句の前の行は、try ブロックと呼ばれます。
:try
:        ...
:        ...                                TRY BLOCK
:        ...
:catch /{pattern}/
:        ...
:        ...                                CATCH CLAUSE
:        ...
:catch /{pattern}/
:        ...
:        ...                                CATCH CLAUSE
:        ...
:finally
:        ...
:        ...                                FINALLY CLAUSE
:        ...
:endtry
try 条件文を使用すると、コード内で例外を監視し、適切なアクションを実行できます。try ブロックからの例外をキャッチできます。try ブロック、および catch 句からの例外は、クリーンアップアクションを引き起こす可能性があります。try ブロックの実行中に例外がスローされない場合、制御は (存在すれば) finally 句に転送されます。その実行後、スクリプトは「:endtry」の次の行から続行されます。try ブロックの実行中に例外が発生すると、try ブロックの残りの行はスキップされます。例外は、「:catch」コマンドの引数として指定されたパターンと照合されます。最初に一致する「:catch」の後の catch 句が実行され、他の catch 句は実行されません。catch 句は、次の「:catch」、「:finally」、または「:endtry」コマンド (最初に到達したコマンド) に達すると終了します。次に、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」を参照してください。
finally 句は、try 条件文全体を囲む「:while」ループの「:break」または「:continue」が try ブロックまたは catch 句から実行された場合にも実行されます。または、「:return」または「:finish」が、関数またはソーススクリプト内の try 条件文の try ブロックまたは catch 句から実行された場合にも実行されます。「:break」、「:continue」、「:return」、または「:finish」は finally 句の実行中に保留され、「:endtry」に到達したときに再開されます。ただし、例外が finally 句からスローされた場合は破棄されます。finally 句に「:while」ループ全体を囲む「:break」または「:continue」が出現した場合、または finally 句に「:return」または「:finish」が出現した場合、finally 句の残りの部分はスキップされ、「:break」、「:continue」、「:return」、または「:finish」は通常どおり実行されます。finally 句が、try ブロックまたは catch 句からの例外または以前の「:break」、「:continue」、「:return」、または「:finish」のために実行された場合、この保留中の例外またはコマンドは破棄されます。
例については、「throw-catch」および「try-finally」を参照してください。

TRY 条件文のネスト try-nesting

try 条件文は任意にネストできます。つまり、完全な try 条件文を、別の try 条件文の try ブロック、catch 句、または finally 句に入れることができます。内部の try 条件文が try ブロックでスローされた例外をキャッチしない場合、または catch 句または finally 句のいずれかから新しい例外をスローする場合、外部の try 条件文は上記のルールに従ってチェックされます。内部の try 条件文が外部の try 条件文の try ブロック内にある場合、その catch 句がチェックされますが、それ以外の場合は finally 句のみが実行されます。ネストの場合、内部の try 条件文が外部の try 条件文に直接含まれているか、外部の try 条件文が内部の try 条件文を含むスクリプトをソースしているか、関数を呼び出しているかは関係ありません。
アクティブな try 条件文のいずれも例外をキャッチしない場合、それらの finally 句のみが実行されます。その後、スクリプトの処理は終了します。「:throw」コマンドによって明示的にスローされたキャッチされない例外の場合は、エラーメッセージが表示されます。Vim によって暗黙的に発生するキャッチされないエラーおよび割り込み例外の場合、エラーメッセージまたは割り込みメッセージは通常どおり表示されます。
例については、「throw-catch」を参照してください。

例外処理コードの検査 except-examine

例外処理コードは複雑になる可能性があります。何が起こるか不明な場合は、「'verbose'」を 13 に設定するか、スクリプトファイルをソースするときに「:13verbose」コマンド修飾子を使用してください。そうすれば、例外がいつスロー、破棄、キャッチ、または完了したかを確認できます。少なくとも 14 の詳細レベルを使用すると、finally 句で保留されているものも表示されます。この情報は、デバッグモードでも提供されます(「debug-scripts」を参照)。

例外のスローとキャッチ throw-catch

任意の数値または文字列を例外としてスローできます。「:throw」コマンドを使用し、スローする値を引数として渡します。
:throw 4711
:throw "string"
throw-expression
式の引数を指定することもできます。式は最初に評価され、結果がスローされます。
: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」がスローされ、Bar() は実行されないため、「in Bar」は表示されません。
:throw Foo("foo") + Bar()
ただし、「in Bar」が表示され、4711 がスローされます。
引数として式を取る他のコマンドも、式の評価中に(キャッチされない)例外によって中止される可能性があります。例外は、コマンドの呼び出し元に伝播されます。例
:if Foo("arrgh")
:  echo "then"
:else
:  echo "else"
:endif
ここでは、「then」も「else」も表示されません。
catch-order
例外は、1 つ以上の「:catch」コマンドを持つ try 条件文でキャッチできます。「try-conditionals」を参照してください。各「:catch」コマンドによってキャッチされる値は、パターン引数として指定できます。後続の catch 句は、一致する例外がキャッチされたときに実行されます。例
: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」と表示され、2 番目の呼び出しは「String thrown」と表示されます。例外は、「:catch」コマンドに対して、指定された順序で照合されます。最初の一致のみがカウントされます。したがって、より具体的な「:catch」を最初に配置する必要があります。次の順序は意味をなしません。
:  catch /.*/
:    echo "String thrown"
:  catch /^\d\+$/
:    echo "Number thrown"
ここの最初の「:catch」は常に一致するため、2 番目の catch 句が実行されることはありません。
throw-variables
一般的なパターンで例外をキャッチした場合、変数「v:exception」で正確な値にアクセスできます。
:  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-nested
try 条件文によってキャッチされない例外は、外側の try 条件文によってキャッチできます。
:try
:  try
:    throw "foo"
:  catch /foobar/
:    echo "foobar"
:  finally
:    echo "inner finally"
:  endtry
:catch /foo/
:  echo "foo"
:endtry
内部の try 条件文は例外をキャッチせず、finally 句のみが実行されます。例外は、外側の try 条件文によってキャッチされます。例では「inner finally」と「foo」が表示されます。
throw-from-catch
例外をキャッチし、catch 句から別の場所でキャッチされるように新しい例外をスローできます。
: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」と表示されます。
rethrow
Vim スクリプト言語には実際のリトローはありませんが、代わりに「v:exception」をスローすることができます。
:function! Bar()
:  try
:    call Foo()
:  catch /.*/
:    echo "Rethrow" v:exception
:    throw v:exception
:  endtry
:endfunction
try-echoerr
Vim の内部例外を偽装することはできないため、このメソッドを使用して Vim のエラーまたは割り込み例外を「リトロー」することはできないことに注意してください。そうすると、エラー例外が発生します。状況を示す独自の例外をスローする必要があります。元のエラー例外の値を含む Vim エラー例外を引き起こしたい場合は、「:echoerr」コマンドを使用できます。
:try
:  try
:    asdf
:  catch /.*/
:    echoerr v:exception
:  endtry
:catch /.*/
:  echo v:exception
:endtry
このコードは次のように表示します。
Vim(echoerr):Vim:E492: Not an editor command: asdf

クリーンアップコード try-finally

スクリプトは多くの場合、グローバル設定を変更し、終了時に復元します。ただし、ユーザーが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
このメソッドは、関数またはスクリプトの一部が、その関数またはスクリプト部分の失敗または正常終了時に復元する必要があるグローバル設定を変更するたびに、ローカルで使用する必要があります。
break-finally
クリーンアップコードは、try ブロックまたは catch 句が「:continue」、「:break」、「:return」、または「:finish」によって離脱した場合にも機能します。例
: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」を追加する必要はありません。(とりわけ、これは戻り値を上書きします。)
except-from-finally
finally 句で「:continue」、「:break」、「:return」、「:finish」、または「:throw」のいずれかを使用することは可能ですが、try 条件文のクリーンアップアクションを放棄するため、推奨されません。ただし、もちろん、割り込みおよびエラー例外は finally 句から発生する可能性があります。finally 句のエラーが、割り込みが正しく機能するのを妨げる例
: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」を参照してください。

エラーの捕捉 catch-errors

特定のエラーを捕捉したい場合は、監視対象のコードを try ブロックに入れ、エラーメッセージに対する catch 句を追加する必要があります。try 条件文が存在すると、すべてのエラーが例外に変換されます。メッセージは表示されず、v:errmsg も設定されません。":catch" コマンドの正しいパターンを見つけるには、エラー例外の形式を知る必要があります。エラー例外は次の形式を持ちます。
Vim({cmdname}):{errmsg}
または
Vim:{errmsg}
{cmdname} は失敗したコマンドの名前です。2番目の形式は、コマンド名が不明な場合に使用されます。{errmsg} は通常、try 条件文の外でエラーが発生した場合に生成されるエラーメッセージです。常に大文字の「E」で始まり、その後に2桁または3桁のエラー番号、コロン、およびスペースが続きます。
コマンド
: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-text
注:エラーメッセージのテキスト自体を捕捉すべきではありません。
:catch /No such variable/
は英語ロケールでのみ機能しますが、ユーザーが :language コマンドで別の言語を選択した場合は機能しません。ただし、コメントでメッセージテキストを引用すると役立ちます。
:catch /^Vim(\a\+):E108:/   " No such variable

エラーの無視 ignore-errors

特定 のVim コマンドでのエラーを無視するには、ローカルで捕捉します。
:try
:  write
:catch
:endtry
ただし、この単純な形式は、意図したものよりも多くのものを捕捉する可能性があるため、使用しないことを強くお勧めします。":write" コマンドでは、いくつか の自動コマンド が実行され、書き込みに関連しないエラーが発生する可能性があります。たとえば、
:au BufWritePre * unlet novar
スクリプト作成者として責任のないエラーが発生する可能性もあります。スクリプトのユーザーがそのような自動コマンドを定義している可能性もあります。そうなると、エラーをユーザーから隠蔽することになります。代わりに、次を使用する方がはるかに優れています。
:try
:  write
:catch /^Vim(write):/
:endtry
これは、実際の書き込みエラーのみを捕捉します。したがって、意図的に無視したいものだけを捕捉してください。
自動コマンドの実行を引き起こさない単一のコマンドの場合は、":silent!" コマンドでエラーから例外への変換を抑制することもできます。
:silent! nunmap k
これは、try 条件文がアクティブな場合にも機能します。

割り込みの捕捉 catch-interrupt

アクティブな 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 を押すと、スクリプトは終了します。
スクリプトの特定の行で CTRL-C が押された場合に何が起こるかをテストするには、デバッグモードを使用し、その行で >quit または >interrupt コマンドを実行します。debug-scripts を参照してください。

すべてを捕捉 catch-all

コマンド
: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

例外と自動コマンド except-autocmd

例外は、自動コマンドの実行中に使用できます。例
: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!」と表示します。
except-autocmd-Pre
一部のコマンドでは、コマンドのメインアクションが実行される前に自動コマンドが実行されます。自動コマンドのシーケンスで例外がスローされ、捕捉されない場合、シーケンスと実行を発生させたコマンドは中止され、例外はコマンドの呼び出し元に伝播されます。例
: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 "*"
except-autocmd-Post
一部のコマンドでは、コマンドのメインアクションが実行された後に自動コマンドが実行されます。このメインアクションが失敗し、コマンドがアクティブな try 条件文内にある場合、自動コマンドはスキップされ、コマンドの呼び出し元が捕捉できるエラー例外がスローされます。例
: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
":silent!" を使用することもできます。
: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
except-autocmd-Cmd
一部のコマンドでは、通常の動作を自動コマンドのシーケンスで置き換えることができます。そのシーケンスからの例外は、コマンドの呼び出し元が捕捉できます。例:":write" コマンドの場合、呼び出し元は例外が発生したときにファイルが実際に書き込まれたかどうかを知ることができません。何らかの方法でそれを伝える必要があります。
: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
except-autocmd-ill
異なるイベントの自動コマンドに try 条件文をまたがって広げることはできません。次のコードは不正です。
:autocmd BufWritePre  * try
:
:autocmd BufWritePost * catch
:autocmd BufWritePost *   echo v:exception
:autocmd BufWritePost * endtry
:
:write

例外の階層とパラメータ化された例外 except-hier-param

一部のプログラミング言語では、例外クラスの階層を使用したり、例外クラスのオブジェクトに追加情報を渡したりできます。Vim でも同様のことができます。階層から例外をスローするには、コンポーネントをコロンで区切った完全なクラス名をスローします。たとえば、数学ライブラリでのオーバーフローの場合は文字列 "EXCEPT:MATHERR:OVERFLOW" をスローします。例外クラスに追加情報を渡したい場合は、括弧で囲んで追加します。たとえば、"myfile" の書き込みエラーの場合は文字列 "EXCEPT:IO:WRITEERR(myfile)" をスローします。":catch" コマンドの適切なパターンを使用すると、階層の基本クラスまたは派生クラスを捕捉できます。括弧内の追加情報は、":substitute" コマンドで v:exception から切り取ることができます。例
: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"
:
:endtry
Vim 自体が(エラー時または CTRL-C を押したときに)発生させる例外は、フラットな階層を使用します。それらはすべて「Vim」クラスに属しています。「Vim」プレフィックスを付けて例外をスローすることはできません。これらは Vim 用に予約されています。Vim のエラー例外は、失敗したコマンドの名前がわかっている場合は、コマンドの名前でパラメータ化されます。catch-errors を参照してください。

特異性

except-compat
例外処理の概念では、例外を引き起こしているコマンドシーケンスがすぐに中止され、制御が finally 句および/または catch 句に転送される必要があります。
Vim スクリプト言語では、エラー後もスクリプトと関数が継続される場合があります。"abort" フラグのない関数内、または ":silent!" 後のコマンドでは、制御フローは次の行に移動し、関数外では、制御フローは最も外側の ":endwhile" または ":endif" に続く行に移動します。一方、エラーは例外として捕捉可能である必要があります(したがって、即時中止が必要になります)。
この問題は、try 条件文がアクティブな場合にのみ、エラーを例外に変換し、即時中止を使用することによって解決されました(":silent!" で抑制されていない場合)。(エラー) 例外はアクティブな try 条件文からのみ捕捉できるため、これは制限ではありません。エラーを捕捉せずにすぐに終了したい場合は、catch 句のない try 条件文を使用するだけです。(finally 句を指定することにより、終了前にクリーンアップコードを実行させることができます。)
try 条件文がアクティブでない場合、即時中止の代わりに、通常の中止および継続動作が使用されます。これにより、Vim 6.1 以前用に作成されたスクリプトの互換性が保証されます。
ただし、既存のスクリプト(またはその関数の1つ)を、新しいスクリプトのアクティブな try 条件文の中からソースすると、エラー時に既存のスクリプトの制御フローが変更される可能性があります。エラー時に即時中止が発生し、新しいスクリプトでエラーを捕捉できます。ただし、ソースされたスクリプトが ":silent!" コマンドを使用してエラーメッセージを抑制している場合(必要に応じて v:errmsg をテストしてエラーを確認している場合)、その実行パスは変更されません。エラーは例外に変換されません。(:silent を参照してください。)したがって、このようになる残りの原因は、エラーを気にせずにエラーメッセージを生成するスクリプトの場合のみです。おそらく、新しいスクリプトからそのようなコードを使用したくないでしょう。
except-syntax-err
例外処理コマンドの構文エラーは、それらが属する try 条件文の ":catch" コマンドでは捕捉されません。ただし、finally 句は実行されます。例
: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
元の例外は破棄され、代わりにエラー例外が発生します。
except-single-line
":try"、":catch"、":finally"、および ":endtry" コマンドは1行に記述できますが、その場合、構文エラーによって "catch" 行を認識するのが難しくなる可能性があるため、避けることをお勧めします。例
:try | unlet! foo # | catch | endtry
":unlet!" 引数の後の後続文字に対してエラー例外が発生しますが、":catch" および ":endtry" コマンドは認識されないため、エラー例外は破棄され、「E488: Trailing characters」メッセージが表示されます。
except-several-errors
単一のコマンドで複数のエラーが発生した場合、通常、最初のエラーメッセージが最も具体的であり、そのためエラー例外に変換されます。例
echo novar
は次のようになります。
E121: Undefined variable: novar
E15: Invalid expression: novar
try 条件文内のエラー例外の値は次のようになります。
Vim(echo):E121: Undefined variable: novar
except-syntax-error
ただし、同じコマンドで通常のエラーの後に構文エラーが検出された場合、スローされる例外には構文エラーが使用されます。例
unlet novar #
は次のようになります。
E108: No such variable: "novar"
E488: Trailing characters
try 条件文内のエラー例外の値は次のようになります。
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 を参照してください。
2進数での印刷
:" 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
1行で
:call setline(1, sort(getline(1, '$'), function("Strcmp")))
scanf() の置換
sscanf
Vimにはsscanf()関数はありません。行から一部を抽出する必要がある場合は、matchstr()とsubstitute()を使用できます。この例では、「foobar.txt, 123, 45」のような行からファイル名、行番号、列番号を取得する方法を示します。
:" 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

サンドボックス eval-sandbox sandbox

'foldexpr''formatexpr''includeexpr''indentexpr''statusline''foldtext'オプションは、サンドボックス内で評価される場合があります。これは、これらの式が意図しない副作用をもたらすのを防ぐための保護手段です。これにより、これらのオプションがmodelineから設定された場合の安全性が向上します。また、tagsファイルからのコマンドが実行される場合や、コマンドラインでCTRL-R = が使用される場合にも使用されます。サンドボックスは、:sandboxコマンドにも使用されます。
E48
以下の項目はサンドボックスでは許可されていません。
バッファテキストの変更
マッピング、自動コマンド、ユーザーコマンドの定義または変更
特定のオプションの設定(option-summaryを参照)
特定のv:変数の設定(v:varを参照)E794
シェルコマンドの実行
ファイルの読み書き
別のバッファへのジャンプまたはファイルの編集
Python、Perlなどのコマンドの実行。これは100%安全であるとは限りませんが、ほとんどの攻撃をブロックするはずです。
:san :sandbox :san[dbox] {cmd} サンドボックス内で{cmd}を実行します。modelineから設定された可能性のあるオプション(例:'foldexpr')を評価するのに役立ちます。
サンドボックス-オプション
いくつかのオプションには式が含まれています。この式が評価される際に、セキュリティリスクを回避するためにサンドボックス内で実行する必要がある場合があります。ただし、サンドボックスは制限されているため、これはオプションが安全でない場所から設定された場合にのみ発生します。この文脈における「安全でない」とは、以下のものを指します。
現在のディレクトリにある.nvimrcまたは.exrcを読み込む
サンドボックス内で実行している
modelineから来る値
サンドボックス内で定義された関数を実行している
サンドボックス内でオプション値を保存して復元する場合、オプションはサンドボックス内で設定されたものとしてマークされたままになることに注意してください。

テキストロック textlock

いくつかの状況では、バッファ内のテキストを変更したり、別のウィンドウにジャンプしたり、Vimが現在実行していることを混乱させたり、壊したりする可能性のあるその他の操作を行うことが許可されていません。これは主に、Vimが実際に別の処理を実行しているときに発生するものに適用されます。たとえば、TextYankPost自動コマンドは、ヤンクしているテキストを編集することはできません。
テキストロックがアクティブな場合は、以下は許可されていません。
バッファテキストの変更
別のバッファまたはウィンドウへのジャンプ
別のファイルの編集
ウィンドウを閉じるまたはVimを終了する

Vimスクリプトライブラリ vim-script-library

Vimには、ランタイムやスクリプト作成者が使用できるVimスクリプトライブラリがバンドルされています。現在、含まれている関数はごくわずかですが、今後増える可能性があります。
dist#vim
これらの関数は、オートロードされた接頭辞「dist#vim」を使用します。
以下の関数が利用可能です。
dist#vim#IsSafeExecutable(filetype, executable)
この関数は、ファイルタイプと実行可能ファイルを受け取り、指定された実行可能ファイルの実行が安全かどうかを確認します。セキュリティ上の理由から、ユーザーはVimがランダムな実行可能ファイルを実行することを望まない場合や、特定のファイルタイプに対して "<filetype>_exec" 変数(plugin_exec)を設定して実行を禁止している場合があります。
この関数は、プラグインが指定された実行可能ファイルを実行すべきかどうかを示すTRUEまたはFALSEを返します。以下の引数を取ります。
引数タイプ
ファイルタイプ 文字列 実行可能ファイル 文字列

コマンドライン式ハイライト expr-highlight

i_CTRL-R_=c_CTRL-\_equote=でユーザーが入力した式は、組み込みの式パーサーによってハイライトされます。これは、以下の表で説明されているハイライトグループを使用します。これはカラースキームによって上書きされる場合があります。hl-NvimInvalid
以下で説明する「Nvim」プレフィックスのハイライトグループに加えて、同じ意味を持つが、トークンにエラーが含まれているか、その直前にエラーが発生したことを示す「NvimInvalid」プレフィックスのハイライトグループがあります。それらはほとんど同じ階層構造を持っていますが、(デフォルトでは)非Nvimプレフィックスのグループの代わりにErrorにリンクするNvimInvalidが使用され、他の中間グループも存在します。
グループ デフォルトリンク 色付きの式
hl-NvimInternalError なし、赤/赤 パーサーのバグ
hl-NvimAssignment 演算子 一般的な代入 hl-NvimPlainAssignment NvimAssignment :let= hl-NvimAugmentedAssignment NvimAssignment 一般的な、+=/`-=`/`.=` hl-NvimAssignmentWithAddition NvimAugmentedAssignment :let+=+= hl-NvimAssignmentWithSubtraction NvimAugmentedAssignment :let-=-= hl-NvimAssignmentWithConcatenation NvimAugmentedAssignment :let.=.=
hl-NvimOperator 演算子 一般的な演算子
hl-NvimUnaryOperator NvimOperator 一般的な単項演算子 hl-NvimUnaryPlus NvimUnaryOperator expr-unary-+ hl-NvimUnaryMinus NvimUnaryOperator expr-unary-- hl-NvimNot NvimUnaryOperator expr-!
hl-NvimBinaryOperator NvimOperator 一般的な二項演算子 hl-NvimComparison NvimBinaryOperator expr4演算子 hl-NvimComparisonModifier NvimComparison expr4演算子の近くの#/`?` 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-NvimTernary NvimOperator expr1? hl-NvimTernaryColon NvimTernary expr1:
hl-NvimParenthesis 区切り文字 一般的な括弧 hl-NvimLambda NvimParenthesis lambda{/`}` hl-NvimNestingParenthesis NvimParenthesis expr-nesting(/`)` hl-NvimCallingParenthesis NvimParenthesis expr-function(/`)`
hl-NvimSubscript NvimParenthesis 一般的な添字 hl-NvimSubscriptBracket NvimSubscript expr-[][/`]` hl-NvimSubscriptColon NvimSubscript expr-[:]: hl-NvimCurly NvimSubscript curly-braces-names{/`}`
hl-NvimContainer NvimParenthesis 一般的なコンテナ hl-NvimDict NvimContainer dictリテラルの{/`}` hl-NvimList NvimContainer listリテラルの[/`]`
hl-NvimIdentifier 識別子 一般的な識別子 hl-NvimIdentifierScope NvimIdentifier 名前空間:internal-variables:前の文字 hl-NvimIdentifierScopeDelimiter NvimIdentifier 名前空間の文字の後の: hl-NvimIdentifierName NvimIdentifier 識別子の残りの部分 hl-NvimIdentifierKey NvimIdentifier expr-entryの後の識別子
hl-NvimColon 区切り文字 dictリテラルの: hl-NvimComma 区切り文字 dictまたはlistリテラル、またはexpr-function, hl-NvimArrow 区切り文字 lambda->
hl-NvimRegister 特殊文字 expr-register hl-NvimNumber 数値 expr-numberの整数の非プレフィックスの数字 hl-NvimNumberPrefix タイプ 8進数016進数0x2進数0b hl-NvimFloat NvimNumber 浮動小数点数
hl-NvimOptionSigil タイプ expr-option& hl-NvimOptionScope NvimIdentifierScope オプションスコープ(ある場合) hl-NvimOptionScopeDelimiter NvimIdentifierScopeDelimiter オプションスコープの後の: hl-NvimOptionName NvimIdentifier オプション名
hl-NvimEnvironmentSigil NvimOptionSigil expr-env$ hl-NvimEnvironmentName NvimIdentifier 環境変数名
hl-NvimString String 一般的な文字列 hl-NvimStringBody NvimString 一般的な文字列リテラル本体 hl-NvimStringQuote NvimString 一般的な文字列の引用符 hl-NvimStringSpecial SpecialChar 一般的な文字列の非リテラル本体
hl-NvimSingleQuote NvimStringQuote expr-' 内の ' hl-NvimSingleQuotedBody NvimStringBody expr-' 文字列本体のリテラル部分 hl-NvimSingleQuotedQuote NvimStringSpecial expr-' 文字列本体内の ''
hl-NvimDoubleQuote NvimStringQuote expr-quote 内の " hl-NvimDoubleQuotedBody NvimStringBody expr-quote 本体のリテラル部分 hl-NvimDoubleQuotedEscape NvimStringSpecial 有効な expr-quote エスケープシーケンス hl-NvimDoubleQuotedUnknownEscape NvimInvalidValue 未認識の expr-quote エスケープシーケンス
メイン
コマンド索引
クイックリファレンス