vim-jp / vimdoc-ja / eval

eval - Vim日本語ドキュメント

メインヘルプファイルに戻る English | 日本語 | 編集
eval.txt      For Vim バージョン 9.1.  Last change: 2024 Feb 08


                VIMリファレンスマニュアル    by Bram Moolenaar


式の評価                                expression expr E15 eval
                                                        E1002
式の評価についてはユーザーマニュアルの41章usr_41.txtでも解説されている。

Note: 式の評価はコンパイル時に無効化できる。無効化されている場合、このドキュメ
ントに書かれている事は有効ではない。+eval と no-eval-feature を参照。

このファイルは主に後方互換の(旧来の) Vim script について書かれている。より高速
に実行でき、型チェックや多くの機能に対応する Vim9 script については vim9.txt
を参照のこと。構文およびセマンティクスが異る場合は注釈が付く。

1.  変数                        variables
    1.1 変数の型
    1.2 関数への参照                    Funcref
    1.3 リスト                          Lists
    1.4 辞書                            Dictionaries
    1.5 Blobs                           Blobs
    1.6 変数について補足                more-variables
2.  式の文法                    expression-syntax
3.  内部変数                    internal-variables
4.  組み込み関数                functions
5.  関数定義                    user-functions
6.  波括弧{}変数                curly-braces-names
7.  コマンド                    expression-commands
8.  例外処理                    exception-handling
9.  例                          eval-examples
10. Vim scriptバージョン        vimscript-version
11. +eval機能が無効             no-eval-feature
12. サンドボックス              eval-sandbox
13. テキストロック              textlock
14. Vim script ライブラリ       vim-script-library

テストのサポートは testing.txt を参照。
プロファイリングは profiling に記録されている。

==============================================================================
1. 変数                                                 variables

1.1 変数の型 ~
                                        E712 E896 E897 E899 E1098
                                        E1107 E1135 E1138
変数には10種類の型がある:

                                                        Number Integer
数値            32ビットまたは64ビットの符号有整数。expr-number
                ビット数は v:numbersize で得られる。
                例:  -123  0x10  0177  0o177 0b1011

浮動小数点数    浮動小数点数。floating-point-format Float
                例: 123.456  1.15e-6  -1.1e3

文字列          終端がNUL文字である8ビットの符号無し文字(バイト)。
                expr-string 例: "ab\txx\"--"  'x-z''a,c'

リスト          要素の順序つきの列。詳細は List を参照。
                例: [1, 2, ['a', 'b']]

辞書            順序を持たない連想配列: 各要素はキーと値を持つ。Dictionary
                例:
                    {'blue': "#0000ff", 'red': "#ff0000"}
                    #{blue: "0000ff", red: "ff0000"}

Funcref         関数への参照 Funcref
                例: function("strlen")
                辞書や引数とバインドすることができ、そのときは部分適用(Partial)
                のように働く。
                例: function("Callback", [arg], myDict)

特殊値          v:falsev:truev:none と v:null。  Special

ジョブ          ジョブに使われる。job_start()を参照。 Job Jobs

チャネル        チャネルに使われる。ch_open()を参照。 Channel Channels

Blob            バイナリラージオブジェクト。任意のバイトシーケンスを格納する。
                詳細は Blob を参照。
                例: 0zFF00ED015DAF
                0z は空のBlobである。

数値と文字列は文脈に応じて相互に変換される。

数値から文字列への変換は数字のASCII表現によって行われる。例:
        数値 123        -->     文字列 "123" ~
        数値 0          -->     文字列 "0" ~
        数値 -1         -->     文字列 "-1" ~
                                                        octal
文字列から数値への変換は旧来の Vim script のみで行われ、Vim9 script では行われ
ない。最初に出る数字を用いて数値に変換する。16進表記 "0xf9" や8進表記 "017" も
しくは "0o17"、2進表記の "0b10" も認識される。
NOTEVim9 script か scriptversion-4 を使用する場合、先頭が "0" の8進数は
認識されない。"0o" 記法はパッチ 8.2.0886 が必要になる。
文字列が数字で始まらない場合結果は0となる。
例:
        文字列 "456"    -->     数値 456 ~
        文字列 "6bar"   -->     数値 6 ~
        文字列 "foo"    -->     数値 0 ~
        文字列 "0xf1"   -->     数値 241 ~
        文字列 "0100"   -->     数値 64 ~
        文字列 "0o100"  -->     数値 64 ~
        文字列 "0b101"  -->     数値 5 ~
        文字列 "-8"     -->     数値 -8 ~
        文字列 "+8"     -->     数値 0 ~

文字列を強制的に数値に変換するには0を足す: >
        :echo "0100" + 0
<       64 ~

先頭の0によって8進数とみなされるのを防いだり、異なる基数を使うにはstr2nr()
使う。

                                                TRUE FALSE Boolean
ブール(真偽値)演算には数値が使われる。0は偽を意味し、非0は真を表す。また、
v:false と v:true を使うこともでき、Vim9 script では false と true に
なる。
関数から真が返されたときは数値の 1 であり、偽が返されたときは数値の 0 である。

Note 次のコマンドをみると >
        :if "foo"
        :" 実行されない
"foo" は 0 に変換され、それは偽を意味する。もし文字列がゼロでない数値から始ま
る場合は真を意味する: >
        :if "8foo"
        :" 実行される
文字列が空ではないか調べるためには empty() を使用して次のようにする。 >
        :if !empty("foo")

<                                               falsy truthy
式は、型を無視した値が「真の一種」か「偽の一種」のどちらであるかだけを利用し
て、判定条件として使用できる。Falsy は:
        値が0
        空の文字列、Blob、リスト、辞書
それ以外の値は truthy。例:
        0       falsy
        1       truthy
        -1      truthy
        0.0     falsy
        0.1     truthy
        ''      falsy
        'x'     truthy
        []      falsy
        [0]     truthy
        {}      falsy
        #{x: 1} truthy
        0z      falsy
        0z00    truthy

                                                        non-zero-arg
関数の引数は、TRUE とは少し異なる場合がある: 引数が存在し、それが非ゼロの
Number、v:true または空でない String に評価される場合、値は TRUE と見なされ
る。
Note: " " と "0" も空文字列ではないので、TRUE と見なされる。List、Dictionary、
または Float は数値または文字列ではないため、FALSE と評価される。

                E611 E745 E728 E703 E729 E730 E731 E908 E910
                E913 E974 E975 E976 E1319 E1320 E1321 E1322
                E1323 E1324
リスト List, 辞書 DictionaryFuncref, ジョブ Job, チャネル Channel,
Blob, クラス Class および object は自動的に変換されない。

                                                        E805 E806 E808
数値と浮動小数点数をまぜると浮動小数点数になる。それ以外には浮動小数点数への自
動的な変換は存在しない。文字列から浮動小数点数へは str2float() を使い、浮動小
数点数から文字列へは printf() を、浮動小数点数から数値へは float2nr() を使う。

                        E362 E891 E892 E893 E894 E907 E911 E914
浮動小数点数が予期されているところでは数値も使用可能だが、それ以外は使用できな
い。

                                                no-type-checking
変数の型を変更しようとしてもエラーは発生しない。


1.2 関数への参照 ~
                                        Funcref E695 E718 E1192
関数への参照は、関数 function()、関数 funcref()、(Vim9 script 内で)関数
の名前あるいはラムダ式 expr-lambda による生成で得られる。関数への参照は、式
の中で関数名が要求される場所で使うと参照先の関数を呼び出す。Vim9 script での
例: >

        :var Fn = MyFunc
        :echo Fn()

旧来のスクリプトでは: >
        :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')

これは関数を何かに渡す場合、例えば ch_open() の引数とする場合などに非常に有
用である。

Note 関数の辞書へのバインドは、その関数が辞書のメンバーであるときにも発生する
ことに注意: >

        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" である。なぜなら明示的にバインドされているからで
ある。


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
リストの要素にアクセスするには、リスト名の後に[]を書き、その中にインデックスを
書く。インデックスは0基点(つまり最初の要素のインデックスは0)である。 >
        :let item = mylist[0]           " 最初の要素(1)を取得
        :let item = mylist[2]           " 3番目の要素(3)を取得

取得した要素がリストならば、さらに続けてインデックスを書くことができる: >
        :let item = nestlist[0][1]      " 最初のリストの2番目の要素(12)を取得
<
負のインデックスを指定すると、リストの末尾から数えられる。インデックス-1は最後
の要素を示し、-2は最後から2番目を指す >
        :let last = mylist[-1]          " 最後の要素("four")を取得

無効なインデックスによるエラーを回避するには関数get()を使う。するとインデッ
クスが無効な場合は、0かまたは自分で指定した既定値が返る: >
        :echo get(mylist, idx)
        :echo get(mylist, idx, "NONE")


リストの連結 ~
                                                        list-concatenation
2つのリストを連結するには演算子 "+" を使う: >
        :let longlist = mylist + [5, 6]
        :let longlist = [5, 6] + mylist
1個の要素を先頭または末尾に付け加えるには、[]で囲んでリストにして連結する。

リストは :let+= もしくは extend() を使うことで、他のリストとその場で連結す
ることができる: >
        :let mylist += [7, 8]
        :call extend(mylist, [7, 8])
<
リストをその場で変更する他の方法については list-modification を参照。


部分リスト ~
                                                        sublist
リストの一部分を取り出すには、[]の中に始点と終点のインデックスを書き、コロンで
区切る: >
        :let shortlist = mylist[2:-1]   " リスト[3, "four"]を得る

始点のインデックスを省略すると0となる。終点のインデックスを省略すると-1となる >
        :let endlist = mylist[2:]       " 2番目から最後まで: [3, "four"]
        :let shortlist = mylist[2:2]    " 1個の要素からなるリスト: [3]
        :let otherlist = mylist[:]      " リストのコピーを作る

最後のインデックスが含まれることに注意。排他的なインデックスを利用するなら
slice() メソッドを利用する。

終点のインデックスが始点のインデックスよりも前になってしまった場合は空リストと
なる。エラーメッセージは表示されない。

終点のインデックスがリストの長さより大きい場合は、長さ-1を指定したときと同じに
なる: >
        :let mylist = [0, 1, 2, 3]
        :echo mylist[2:8]               " 結果: [2, 3]

NOTE: mylist[s:e]と書くと変数 "s:e" をインデックスとして使ったと解釈される。
":" の前に1文字の変数を使うときは十分注意すること。必要ならこのようにスペース
を入れるとよい: mylist[s : e].


リストの同一性 ~
                                                        list-identity
変数 "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レベルまでである。

2つの変数が同じリストを指しているかは演算子 "is" で判定できる。"isnot" はその
逆である。一方、"==" は2つのリストが同じ値を持っているかを判定する。 >
        :let alist = [1, 2, 3]
        :let blist = [1, 2, 3]
        :echo alist is blist
<       0 >
        :echo alist == blist
<       1

Note リストの比較について注意: 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" は空リストになる。


リストの変更 ~
                                                        list-modification
リストの中の特定の要素を変更するには次のように:letを使う: >
        :let list[4] = "four"
        :let listlist[0][3] = item

始点と終点を指定してリストの一部分を変更することができる。代入する値は、少なく
とも削除する範囲の要素数と同じ数だけ必要である: >
        :let list[3:5] = [3, 4, 5]

リストに要素をその場で追加するには、:let+= (list-concatenation) を使うこと
ができる: >
        :let listA = [1, 2]
        :let listA += [3, 4]
<
2 つのリストが同じリストを参照している時は、片方のリストをその場で変更すると、
他方のリストもその場で変更される: >
        :let listA = [1, 2]
        :let listB = listA
        :let listB += [3, 4]
        :echo listA
        [1, 2, 3, 4]
<
リストに要素を追加したり削除するには関数を使う。いくつか例を示す: >
        :call insert(list, 'a')         " 先頭に要素 'a' を挿入する
        :call insert(list, 'a', 3)      " 要素 'a' をlist[3]の前に挿入する
        :call add(list, "new")          " 文字列の要素を最後に追加する
        :call add(list, [1, 2])         " 1個の要素としてリストを追加する
        :call extend(list, [1, 2])      " 2個の要素からなるリストを連結する
        :let i = remove(list, 3)        " 要素3を削除する
        :unlet list[3]                  " 同上
        :let l = remove(list, 3, -1)    " 要素3から最後までを削除する
        :unlet list[3 : ]               " 同上
        :call filter(list, 'v:val !~ "x"')  " 要素 'x' を削除

要素の順番を変更する: >
        :call sort(list)                " リストをアルファベット順にソート
        :call reverse(list)             " 要素の順序を反転させる
        :call uniq(sort(list))          " ソートして重複を削除する


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コマンドを実行するかのように実行される。また
この場合も引数の型は全て同じでないとエラーになる。

引数の残りを1個のリスト変数に代入することもできる: >
        :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)   " 引数リストをつけて関数を呼び出す
        :if empty(list)                 " リストが空かどうか判定する
        :let l = len(list)              " リストの要素数
        :let big = max(list)            " リスト中の最大値
        :let small = min(list)          " リスト中の最小値
        :let xs = count(list, 'x')      " 'x' の出現回数を数える
        :let i = index(list, 'x')       " 最初に 'x' が現れる位置のインデックス
        :let lines = getline(1, 10)     " バッファから10行を取得
        :call append('$', lines)        " バッファに行を追加する
        :let list = split("a b c")      " 文字列を分割してリストにする
        :let string = join(list, ', ')  " リストの要素を連結して文字列にする
        :let s = string(list)           " リストの文字列表現
        :call map(list, '">> " .. v:val')  " 各要素の前に ">> " をつける

機能を組み合わせると、処理を単純に記述できることを覚えておくとよい。例えば、リ
スト中の全ての数値の和を求める例: >
        :exe 'let sum = ' .. join(nrlist, '+')


1.4 辞書 ~
                                dict Dict Dictionaries Dictionary
辞書とは連想配列である。各要素はキーと値を持つ。要素はキーによって特定できる。
要素は特に順序を持たずに保持される。


辞書の作成 ~
                                                E720 E721 E722 E723
辞書を作るには、{}の中にコンマで区切って要素を書く。各要素のキーと値はコロンで
区切る。それぞれのキーは1度しか現れてはならない。例: >
        :let mydict = {1: 'one', 2: 'two', 3: 'three'}
        :let emptydict = {}
<                                                       E713 E716 E717
キーは必ず文字列である。数値を使うこともできるが、自動的に文字列に変換される。
よって文字列 '4' のキーと数値4のキーは同一の要素を参照する。
Note 文字列 '04' と数値04は異なることに注意。先頭の0が削除されてから数値が文字
列 '4' に変換されるためである。空文字列もまたキーとして使用できる。

Vim9 script では、キーが英数字、アンダースコア、ダッシュのみで構成されている
場合に、リテラルのキーが使える。vim9-literal-dict を参照。
                                                literal-Dict #{}
すべてのキーを引用符で囲む必要を避けるために、旧来のスクリプトでは #{} 形式を
使用できる。この形式は、ASCII文字、数字、'-' および '_' のみで構成されるキーを
必要とする。
例: >
        :let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3}
Note ここでは 333 は 文字列 "333" であることに注意。空のキーは #{} を使うこと
ができない。
Vim9 script では #{} 形式は使用できない、なぜならコメントの開始と紛らわしい
ためである。

値はどんな式でもよい。辞書を値にすると、ネストした辞書ができる: >
        :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

このキーのリストはソートされていない。ソートさせるには関数sort()を使う: >
        :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


辞書の同一性 ~
                                                        dict-identity
辞書のコピーを作るにはリストと同様にcopy()deepcopy()を使う必要がある。そ
うでなく代入を行うと同一の辞書を参照するようになる: >
        :let onedict = {'a': 1, 'b': 2}
        :let adict = onedict
        :let adict['a'] = 11
        :echo onedict['a']
        11

2つの辞書は、全てのキー・値のペアが等しいとき等しいとみなされる。より詳しくは
list-identityを参照。


辞書の変更 ~
                                                        dict-modification
辞書の要素を変更したり、新しい要素を追加するには:letを使う: >
        :let dict[4] = "four"
        :let dict['one'] = item

辞書から要素を取り除くにはremove():unletを使う。以下のように辞書からキー
"aaa" を取り除くには3つの方法がある: >
        :let i = remove(dict, 'aaa')
        :unlet dict.aaa
        :unlet dict['aaa']

2つの辞書を併合させるにはextend()を使う: >
        :call extend(adict, bdict)
上のコマンドはbdictの全ての要素をadictに追加する。キーが重複した要素はbdictの
要素により上書きされる。この動作は3番目の引数により変更できる。
Note 辞書の要素間に順序は定まっていない。そのため ":echo adict" としたとき、も
ともとadictにあった要素が先に、bdictから追加された要素が後に表示されると考えて
はならない。

辞書から条件を指定して要素を取り除くにはfilter()が使える: >
        :call filter(dict, 'v:val =~ "x"')
このコマンドは "dict" から 'x' にマッチしない要素を全て取り除く。
このコマンドで全てのエントリを除去することもできる: >
        call filter(dict, 0)

状況によっては辞書から項目削除や追加が許可されない。とりわけ全項目を列挙してい
る時がそうである。その場合 E1313 あるいは他のエラーが発生する。


関数を辞書に入れる ~
                                Dictionary-function 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" は、この関数を呼び出した
辞書を参照している。Vim9 script 使用時は、クラスとオブジェクトを使うことがで
きる、`:class` を参照。

"dict" 属性をつけないでFuncrefを辞書に入れることもできる。しかしその場合、変
数 "self" は定義されない。

                                numbered-function anonymous-function
関数に名前をつける必要をなくすために、関数を定義して直接辞書に代入することがで
きる: >
        :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')        " 辞書がキー "foo" の要素を持つなら真
        :if empty(dict)                 " 辞書が空なら真
        :let l = len(dict)              " 辞書の要素数
        :let big = max(dict)            " 辞書中の最大値
        :let small = min(dict)          " 辞書中の最小値
        :let xs = count(dict, 'x')      " 'x' の出現回数を数える
        :let s = string(dict)           " 辞書の文字列表現
        :call map(dict, '">> " .. v:val')  " 各要素の前に ">> " をつける


1.5 Blobs ~
                                                blob Blob Blobs E978
Blobは、バイナリオブジェクトである。例えば、ファイルから画像を読んでチャネルを
通し送信することなどに使える。

Blobは、ほとんどの場合、数値の List のように振る舞う。数値は、0 から 255 の
8ビットの値を持つ。


Blobの作成 ~

BlobはBlobリテラル blob-literal を使って作成できる: >
        :let b = 0zFF00ED015DAF
読みやすくするために、ドットをバイト間(16進文字のペア)に挿入することができる。
ドットは値を変更しない: >
        :let b = 0zFF00.ED01.5DAF

Blobは readfile() で引数{type}を "B" に設定してファイルから読み込むことがで
きる。例: >
        :let b = readfile('image.png', 'B')

Blobは、ch_readblob() 関数を使用してチャネルから読み取ることができる。


Blobのインデックス ~
                                                        blob-index E979
Blob内のバイトは、Blobの後ろに角括弧でインデックスを入れることによってアクセス
することができる。インデックスは 0 から始まるため、最初のバイトのインデックス
は 0 になる。 >
        :let myblob = 0z00112233
        :let byte = myblob[0]           " 1番目のバイトを取得: 0x00
        :let byte = myblob[2]           " 3番目のバイトを取得: 0x22

負のインデックスは終端から数えられる。インデックス -1 はBlobの最後のバイト、-2
は最後の1つ前のバイトを表す。 >
        :let last = myblob[-1]          " 最後のバイトを取得: 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-concatenation
2つのBlobは "+" 演算子で連結できる: >
        :let longblob = myblob + 0z4455
        :let longblob = 0z4455 + myblob
<
Blob は :let+= を使うことで、他の Blob とその場で連結することができる: >
        :let myblob += 0z6677
<
Blob をその場で変更する他の方法については、blob-modification を参照。


Blobの一部 ~

Blobの一部は、角括弧内のコロンで区切られた最初と最後のインデックスを指定するこ
とによって取得できる: >
        :let myblob = 0z00112233
        :let shortblob = myblob[1:2]    " 0z1122 を取得
        :let shortblob = myblob[2:-1]   " 0z2233 を取得

最初のインデックスを省略することはゼロと同じである。最後のインデックスを省略す
ることは -1 と同じである。 >
        :let endblob = myblob[2:]       " 項目2から終端まで: 0z2233
        :let shortblob = myblob[2:2]    " 1バイトのBlob: 0z22
        :let otherblob = myblob[:]      " Blobのコピーを作成

最初のインデックスがBlobの最後のバイトを超えている場合、または2番目のインデッ
クスが最初のインデックスより前にある場合、結果は空のBlobになる。エラーメッセー
ジはない。

2番目のインデックスがリストの長さ以上の場合、長さから 1 を引いたものが使用され
る: >
        :echo myblob[2:8]               " result: 0z2233


Blobの変更 ~
                                        blob-modification E1182 E1184
Blobの特定のバイトを変更するには、 :let を使用する: >
        :let blob[4] = 0x44

インデックスがBlobの終端を1つ超える場合は、それが追加される。それより上のイン
デックスはエラーである。

バイトシーケンスを変更するには、[:] 表記が使用できる: >
        let blob[1:3] = 0z445566
置き換えられたバイトの長さは、提供された値と丁度同じでなければならない。 E972

Blobの一部を変更するには、変更する最初と最後のバイトを指定する。値の範囲内のバ
イト数は同じでなければならない: >
        :let blob[3:5] = 0z334455

Blob に要素をその場で追加するには、:let+= (blob-concatenation)を使うことが
できる: >
        :let blobA = 0z1122
        :let blobA += 0z3344
<
2 つの Blob が同じ 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 変数について補足 ~
                                                        more-variables

変数や式の結果の型を知りたいのならば、関数type()を使う。

オプション 'viminfo' にフラグ '!' が含まれるならば、大文字で始まり小文字を含ま
ない名前のグローバル変数は、viminfoファイルviminfo-fileに格納される。

オプション 'sessionoptions' が "global" を含むなら、大文字で始まり少なくとも一
文字以上の小文字を含む名前のグローバル変数は、sessionファイルsession-file
格納される。

変数名                  何処に保存されるか ~
my_var_6                されない
My_Var_6                sessionファイル
MY_VAR_6                viminfoファイル


旧来のスクリプトでは波括弧を使って変数名を構成できる。詳細は
curly-braces-names を参照。

==============================================================================
2. 式の文法                                             expression-syntax
                                                        E1143
式文法一覧、優先順位の低いものから高い順に:

expr1 expr2
        expr2 ? expr1 : expr1   if-then-else 条件式

expr2 expr3
        expr3 || expr3 ...      論理和

expr3 expr4
        expr4 && expr4 ...      論理積

expr4 expr5
        expr5 == expr5          等しい
        expr5 != expr5          等しくない
        expr5 >  expr5          より大きい
        expr5 >= expr5          大きいか等しい
        expr5 <  expr5          より小さい
        expr5 <= expr5          小さいか等しい
        expr5 =~ expr5          正規表現にマッチする
        expr5 !~ expr5          正規表現にマッチしない

        expr5 ==? expr5         文字列として等しい(大文字/小文字区別無し)
        expr5 ==# expr5         文字列として等しい(大文字/小文字区別有り)
        etc.                    上記の各式は大小文字の区別を、?を付加すると行
                                わず、#を付加すると行う

        expr5 is expr5          同一のリスト List、辞書 Dictionary または
                                Blob のインスタンス
        expr5 isnot expr5       異なるリスト List、辞書 Dictionary または
                                Blob のインスタンス

expr5 expr6
        expr6 << expr6          ビット単位の左シフト
        expr6 >> expr6          ビット単位の右シフト

expr6 expr7
        expr7 +  expr7 ...      足し算、リストまたはBlobの連結
        expr7 -  expr7 ...      引き算
        expr7 .  expr7 ...      文字列の連結
        expr7 .. expr7 ...      文字列の連結

expr7 expr8
        expr8 *  expr8 ...      掛け算
        expr8 /  expr8 ...      割り算
        expr8 %  expr8 ...      剰余(割った余り)

expr8 expr9
        <type>expr9             型のチェックと変換 (Vim9 のみ)

expr9 expr10
        ! expr9                 論理否定
        - expr9                 単項のマイナス
        + expr9                 単項のプラス

expr10  expr11
        expr10[expr1]           文字列のバイト、またはリストの要素
        expr10[expr1 : expr1]   文字列の部分文字列、またはリストの部分リスト
        expr10.name             辞書 Dictionary の要素
        expr10(expr1, ...)      Funcref 変数による関数呼び出し
        expr10->name(expr1, ...) method 呼び出し


expr11  number                数定数
        "string"                文字列定数。バックスラッシュは特別な意味を持つ
        'string'                リテラル文字列定数。'を含めるには2重にする
        [expr1, ...]            リスト List
        {expr1: expr1, ...}     辞書 Dictionary
        #{key: expr1, ...}      旧来の辞書 Dictionary
        &option                 オプション変数
        (expr1)                 式の入れ子
        variable                内部変数
        va{ria}ble              波括弧付きの内部変数
        $VAR                    環境変数
        @r                      レジスタ 'r' の値
        function(expr1, ...)    関数呼出し
        func{ti}on(expr1, ...)  波括弧付きの関数呼出し
        {args -> expr1}         旧来のラムダ式
        (args) => expr1         Vim9 のラムダ式

"..." はその演算が、その後に他の演算を続ける事ができることを示している。
例: >
        &nu || &list && &shell == "csh"

一つのレベルにある全ての式は左から右に解釈される。

式のネストはスタックの不足とクラッシュの回避のため深さ1000段(MSVCでのビルドで
は300)までに制限されている。 E1169


expr1                           expr1 ternary falsy-operator ?? E109
-----

三項演算子:   expr2 ? expr1 : expr1
Falsy 演算子: expr2 ?? expr1

三項演算子 ~

旧来のスクリプトでは '?' より前の式は数値として評価される。その結果がTRUE
あった場合、'?' と ':' に挟まれた式の値がこの式全体の値となり、そうでなかった
場合は ':' 以降の式の値が全体の値となる。

Vim9 script では最初の式は真偽値として評価される必要がある。vim9-boolean
を参照。

例: >
        :echo lnum == 1 ? "先頭" : lnum

始めの式が "expr2" であるから、そこに別の?:を含むことはできない。残り二つの式
については以下のように再帰的な?:の利用が許される。
例: >
        :echo lnum == 1 ? "top" : lnum == 1000 ? "last" : lnum

読み易くするために、行継続line-continuationを利用することが推奨される: >
        :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度評価される。そして Vim9 script であれば "?" 前の expr2
の型が真偽値でなければならない。

expr2 and expr3                                         expr2 expr3
---------------

expr3 || expr3 ..       論理和          expr-barbar
expr4 && expr4 ..       論理積          expr-&&

演算子 "||" と "&&" は左右に一つずつ引数を取る。

旧来のスクリプトでは引数は数値に変換される。

Vim9 script では値は真偽値でなければならない。vim9-boolean を参照。"!!" を
使用すればどの型でも真偽値に変換される。

結果は:

    入力                         出力 ~
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"

Note "&&" は "||" よりも高い優先順位を持っている。これは次の事を意味する: >

        &nu || (&list && &shell == "csh")

結果が確定した時点で残りの式は省略され、解釈されない。これはC言語で行われるこ
とに似ている。例: >

        let a = 1
        echo a || b

これはaがTRUEであるため、変数bが宣言されていなくても有効であり、結果は絶対
TRUEである。次のも同様に: >

        echo exists("b") && b == "yes"

これもbが宣言されているいないにかかわらず有効である。後半の項はbが定義されてい
る時にだけ評価される。


expr4                                                   expr4 E1153
-----

expr5 {cmp} expr5

2つの式expr5を比較。旧来のスクリプトでは結果が偽なら0を、真なら1を返す。Vim9
script では結果を true または false で返す。

                        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? E1072
                'ignorecase'次第   大小文字考慮    大小文字無視 ~
等しい                  ==              ==#             ==?
等しくない              !=              !=#             !=?
より大きい              >               >#              >?
より大きいか等しい      >=              >=#             >=?
より小さい              <               <#              <?
より小さいか等しい      <=              <=#             <=?
正規表現マッチ          =~              =~#             =~?
正規表現非マッチ        !~              !~#             !~?
同一のインスタンス      is              is#             is?
異なるインスタンス      isnot           isnot#          isnot?

例:
"abc" ==# "Abc"   0と評価される
"abc" ==? "Abc"   1と評価される
"abc" == "Abc"    'ignorecase' が設定されていれば1と、でなければ0と評価
NOTEVim9 script では 'ignorecase' を使用しない。

                                                        E691 E692
リストListはリストとだけ比較可能で、==系、!=系、is、isnotのみ利用できる。
これらはそれぞれのリストの値を再帰的に比較する。大文字小文字無視にすると要素を
比較するときに大文字小文字を無視する。

                                                        E735 E736
辞書Dictionaryは辞書とだけ比較可能で、==系、!=系、is、isnotのみ利用できる。
これらは辞書のキー/値を再帰的に比較する。大文字小文字無視にすると要素を
比較するときに大文字小文字を無視する。

                                                        E694
FuncrefFuncrefとだけ比較可能で、"equal", "not equal", "is", "isnot" のみ
利用できる。大文字小文字は常に区別される。引数や辞書が(部分適用に)バインドされ
ているかどうかも重要である。辞書も同値(あるいは "is" の場合は同一)でなければな
らず、引数も同値(あるいは同一)でなければならない。

関数参照が同じ関数を指しているのかを、バインドされた辞書や引数を無視して比較し
たい場合は、get() を使用して関数名を取得すればよい: >
        if get(Part1, 'name') == get(Part2, 'name')
           " Part1 と Part2 は同じ関数を指している
<                                                       E1037
リスト List 、辞書 Dictionary または Blob に対して "is" や "isnot" を使
うと、それらの式が同じリスト、辞書 または Blob のインスタンスを参照している
か判定される。リストのコピーと元のリストは異なると判定される。リスト、辞書また
は Blob 以外に対して "is" は "equal" と同じで、"isnot" は "not equal" と同じ
である。ただし "is"、"isnot" は型が異なると値が等しくない点が "==" とは異なる:
>
        echo 4 == '4'
        1
        echo 4 is '4'
        0
        echo 0 is []
        0
"is#"/"isnot#" と "is?"/"isnot?" は大文字小文字を区別するかどうかが違う。
Vim9 script ではこれは動作しない、2つの文字列は同一になることはない。

旧来のスクリプトでは文字列と数値を比較した場合、文字列が数値に変換され、数値と
して比較される。これは以下のようになることを意味する: >
        echo 0 == 'x'
        1
なぜなら、'x' は数値のゼロに変換されるからである。しかし、 >
        echo [0] == ['x']
        0
リストや辞書の中ではこの変換は行われない。

Vim9 script では型が一致しなくてはならない。

文字列同士を比較した場合、strcmp()やstricmp()によって比較される。これは数値的
に(バイトの値で)比較されるのであって、必ずしも言語に基づく文字種の違いではな
い。

'#' を付けた演算子を使うか、省略形かつ 'ignorecase' が設定されていない場合、比
較はstrcmp()で行われる。大文字・小文字は区別される。

'?' を付けた演算子を使うか、省略形かつ 'ignorecase' が設定されている場合、比較
はstricmp()で行われる。大文字・小文字は区別されない。

'smartcase' は適用されない。

"=~" と "!~" 演算子は右側の引数を正規表現のパターンとして、左側の引数に対して
マッチを試みる。正規表現のパターンに関してはpatternを参照。このマッチは
'magic' が設定され 'cpoptions' が空であるように振舞い、実際の 'magic' や
'cpoptions' に何が設定されているには依存しない。これがスクリプトをポータブルに
してくれる。正規表現中のバックスラッシュが重複してしまうのを避けるには、シング
ルクォーテーションの文字列を使用する。詳細はliteral-stringを参照。
文字列は単一行として扱われるので、複数行のパターン(\nを含むもの)はマッチしな
い。しかしながらリテラルなヌル文字(NL)を、普通の文字として代用することはでき
る。例:
        "foo\nbar" =~ "\n"      1として評価される
        "foo\nbar" =~ "\\n"     0として評価される

expr5                                           expr5 bitwise-shift
-----
expr6 << expr6  ビット単位の左シフト                            expr-<<
expr6 >> expr6  ビット単位の右シフト                            expr->>
                                                        E1282 E1283
"<<" および ">>" 演算子を使用して、右オペランドで指定されたビット数だけ左オペ
ランドのビット単位の左または右シフトがおこなえる。オペランドは正の数として使用
される。">>" で右にシフトすると、最上位ビット(しばしば符号ビットと呼ばれる)は
クリアされる。右オペランド(シフト量)が数値の最大ビット数(v:numbersize)より大
きい場合、結果は0になる。

expr6 and expr7                         expr6 expr7 E1036 E1051
---------------
expr7 + expr7   足し算、リスト List または Blob の連結      expr-+
expr7 - expr7   引き算                                          expr--
expr7 . expr7   文字列の連結                                    expr-.
expr7 .. expr7  文字列の連結                                    expr-..

リストに対しては "+" のみ可能で、expr7 は両方ともリストでなければならない。結
果は2つのリストを連結した新しいリスト。

文字列の連結には ".." が推奨される。"." はあいまいで、Dict メンバーアクセス
と浮動小数点数にも使用される。
Vim9 script もしくは vimscript-version が2以上の場合は "." を使用すること
はできない。

Vim9 script では ".." の引数の単順な型は文字列に変換される: 数値、浮動小数点
数、特殊値、真偽値。その他の型は string() を使用する必要がある。

expr8 * expr8  掛け算                                           expr-star
expr8 / expr8  割り算                                           expr-/
expr8 % expr8  剰余(割った余り)                                 expr-%

旧来のスクリプトでは、"." と ".." を除くすべての演算子で文字列は数値に変換され
る。

ビット演算については and()or()xor() を参照。

Note 旧来のスクリプトでの "+" と ".." の違い:
        "123" + "456" = 579
        "123" .. "456" = "123456"

'..' は '+' と '-' と等しい優先順位を持つので、次の式は: >
        1 .. 90 + 90.0
次のように解釈される: >
        (1 .. 90) + 90.0
文字列 "190" は自動的に数値 190 に変換され、浮動小数点数 90.0 に追加できるた
め、これは旧来のスクリプトでは動作する。しかし次の式は: >
        1 .. 90 * 90.0
次のように解釈される: >
        1 .. (90 * 90.0)
'..' は '*' よりも優先順位が低いためである。これは浮動小数点数と文字列を連結し
ようとするため、動作しない。

数値をゼロで割った結果は、被除数によって次のようになる:
          0 / 0  = -0x80000000  (浮動小数点数の NaN のようなもの)
         >0 / 0  =  0x7fffffff  (正の無限大のようなもの)
         <0 / 0  = -0x7fffffff  (負の無限大のようなもの)
        {訳注: >0 は正の数、<0 は負の数の意味}
        (Vim 7.2 以前では常に 0x7fffffff だった)

64ビット数値が有効化されている場合は:
          0 / 0  = -0x8000000000000000  (浮動小数点数の NaN のようなもの)
         >0 / 0  =  0x7fffffffffffffff  (正の無限大のようなもの)
         <0 / 0  = -0x7fffffffffffffff  (負の無限大のようなもの)
Vim9 script では0除算でエラーになる。                 E1154

'%' の右辺(法)が0の場合、結果は0になる。

これらは全てFuncrefには適用できない。

"."、".."、"%" は浮動小数点数には適用できない。 E804 E1035


expr8                                                   expr8
-----
<type>expr9

これは Vim9 script でのみ使用可能である。type-casting を参照。

expr9                                                   expr9
-----
! expr9                 論理否定                expr-!
- expr9                 単項マイナス            expr-unary--
+ expr9                 単項プラス              expr-unary-+

'!' 演算子ではTRUEFALSEに、FALSETRUEになる。
'-' では数値の符号が反転される。
'+" では変化はない。Note: "++" は効果がない。

旧来のスクリプトでは文字列はまず数値に変換される。Note 文字列が数値から始まっ
ていない時は期待した結果が得られないことがある。

Vim9 script では "-" か "+" が使われていて型が数値でないものはエラーになる。

Vim9 script では "!" は任意の型に使用でき、結果は常に真偽値になる。"!!" を使
用し、値が falsy かどうかに応じて、任意の型を真偽値に変換する。

これら2つは繰り返したり混ぜたりできる。例:
        !-1         == 0
        !!8         == 1
        --9         == 9


expr10                                                  expr10
------
この式は expr11、もしくは連続する以下の選択方式であり、どんな順番でもよい。
例として、これらはすべて可能である:
        expr10[expr1].name
        expr10.name[expr1]
        expr10(expr1, ...)[expr1].name
        expr10->(expr1, ...)[expr1]
評価は常に左から右に行われる。

expr10[expr1]           文字列またはリストの要素        expr-[] E111
                                                E909 subscript E1062
旧来の Vim script では:
expr10 が数値か文字列ならば、この値は文字列 expr10 の第 expr1 番目のバイトから
なる1バイトの文字列となる。expr10 は文字列 (数値の場合は自動で文字列に変換され
る)、expr1 は数として扱われる。マルチバイトのエンコーディングを認識しないため、
代わりの方法は `byteidx()` を参照するか、`split()`を使って文字列を文字のリスト
に変換すれば良い。例えばカーソルの下のバイトを得るには: >
        :let c = getline(".")[col(".") - 1]

Vim9 script では:                                     E1147 E1148
expr10 が文字列ならば、この値は文字列 expr10 の第 expr1 番目の文字 (合成文字が
ある場合はそれらを全て含む) に相当する文字列となる。バイトインデックスの場合は
strpart() を使う。

インデックスが0の場合最初のバイトもしくは文字になる。注意: テキストの列番号は0
始まりである!

文字列の長さよりも大きなインデックスが指定された場合、結果は空文字列になる。負
数のインデックスを指定すると、結果は常に空文字列になる(後方互換性のため)。
最後のバイトもしくは文字を得るには[-1:]を使うこと。
Vim9 script では負数のインデックスはリストと同様に使用され、終端からのカウント
になる。

expr10 がリストListならばインデックスexpr1の要素が返る。取りうるインデックス
の値についてはlist-indexを参照。インデックスが範囲を超えている場合はエラーと
なる。例: >
        :let item = mylist[-1]          " 最後の要素を取得

一般的には、インデックスが正でリストの長さ以上または、負でリストの長さ×-1より
小さいときエラーとなる。


                                                        expr-[:] substring
expr10[expr1a : expr1b] 部分文字列または部分リスト(sublist)

expr10 が文字列ならば、バイトか文字数で expr1a から expr1b までの部分文字列と
なる (両端を含む)。expr10 は文字列として扱われ、expr1a と expr1b は数値として
扱われる。

旧来の Vim script ではインデックスはバイトインデックスとなる。マルチバイトのエ
ンコーディングは認識しない。マルチバイト文字列のインデックスを計算する方法につ
いては byteidx() を参照。expr10 が数値ならば最初に文字列に変換される。

Vim9 script ではインデックスは文字インデックスであり、合成文字を含む {訳注: 1
個の基底文字とその任意個の合成文字をまとめて 1 としてカウントする}。バイトイン
デックスを使用するには strpart() を使用する。合成文字を含まない文字インデッ
クスを使用するには strcharpart() を使用する。

インデックスの expr1b の項目は含まれ、内包的である。排他的なインデックスは
slice() 関数を使う。

expr1aが省略されたときは0となる。expr1bが省略されたときは文字列の長さ-1となる。

負数のインデックスを使うことによって文字列の末尾から取り出すことができる。-1は
最後の文字、-2は最後から2文字目…を表す。

インデックスがその文字の範囲外に出てしまったときは、その文字は省かれる。expr1b
がexpr1aより小さいときは空文字列となる。

例: >
        :let c = name[-1:]              " 文字列の最後のバイト
        :let c = name[0:-1]             " 文字列全体
        :let c = name[-2:-2]            " 文字列の最後から2バイト目
        :let s = line(".")[4:]          " 5バイト目から末尾まで
        :let s = s[:-3]                 " 最後の2文字を削除する
<
                                                        slice
expr10 が List ならば、インデックスexpr1aとexpr1bの間の要素からなる新しい
List となる。すぐ上で説明した文字列の場合と同様である。部分リストsublist
参照のこと。例: >
        :let l = mylist[:3]             " 最初の4個の要素
        :let l = mylist[4:4]            " 1個の要素からなるリスト
        :let l = mylist[:]              " リストの浅いコピー

expr10 が Blob ならば、インデックス expr1a と expr1b のバイト数を含む新しい
Blob となる。例: >
        :let b = 0zDEADBEEF
        :let bs = b[1:2]                " 0zADBE
        :let bs = b[:]                  " 0zDEADBEEF のコピー

Funcref に対して expr10[expr1] や expr10[expr1a : expr1b] を使うとエラーにな
る。

部分リストでスコープと変数に続くコロンとの混乱に注意してください: >
        mylist[n:]     " 変数nは使える
        mylist[s:]     " スコープs:を使うとエラー!


expr10.name             辞書Dictionaryの要素          expr-entry
                                                        E1203 E1229
expr10 が辞書 Dictionary のとき、ドットをつけるとその後に書かれた名前が辞書
のキーと見なされる。例: expr10[name]。

名前は変数名と同じようにアルファベットと数字だけから構成されなければならない
が、数字で始まってもよい。波括弧は使えない。

ドットの前後に空白があってはならない。

例: >
        :let dict = {"one": 1, 2: "two"}
        :echo dict.one          " "1" を表示
        :echo dict.2            " "two" を表示
        :echo dict .2           " ドットの前のスペースによるエラー

Note ドットは文字列連結にも使われる。混乱を避けるために、文字列連結のドットの
周りには必ずスペースを入れること。


expr10(expr1, ...)      Funcref 関数呼び出し          E1085

expr10 が Funcref 型の変数のとき、その参照する関数を呼び出す。


expr10->name([args])    メソッド呼び出し                method ->
expr10->{lambda}([args])
                                                        E260 E276 E1265
グローバル関数としても利用可能なメソッドの場合、これは次と同じである: >
    name(expr10 [, args])
これらは "expr10" 専用としても利用できる

これにより、あるメソッドが返す値を次のメソッドに渡して連鎖させることができる: >
    mylist->filter(filterexpr)->map(mapexpr)->sort()->join()
<
ラムダの使用例: >
        GetPercentage()->{x -> x * 100}()->printf('%d%%')
<
-> を使用する場合 expr9 演算子が最初に適用される。したがって: >
        -1.234->string()
は、以下と同等である: >
        (-1.234)->string()
以下ではない: >
        -(1.234->string())

"->" の後ろに続けられるのは、名前、(括弧を含まない)単順な式、括弧内の任意の式
である: >
        base->name(args)
        base->some.name(args)
        base->alist[idx](args)
        base->(getFuncRef())(args)
Note この最後の呼び出しでは "(getFuncRef())" 関数の解決で "args" の前に base
が挿入されて渡される。  E1275

                                                        E274
"->name(" には空白を含めることはできない。"->" の前と "(" の後に空白を含めるこ
とができる。したがって、次のように行を分割できる: >
        mylist
        \ ->filter(filterexpr)
        \ ->map(mapexpr)
        \ ->sort()
        \ ->join()

ラムダ形式を使用する場合、} と ( の間に空白があってはならない。


                                                        expr11

--
number                  数定数                          expr-number

                        0x hex-number 0o octal-number binary-number
10進数、16進数(0xか0Xで始まる)、2進数(0bか0Bで始まる)、もしくは8進数(0か0oか0O
で始まる)の数定数。

64bitの数値が使用されている(v:numbersize を参照)と仮定するなら、符号なし整数
は 0x7fffffffffffffff か 9223372036854775807 に丸められる。-1 を使用して
0xffffffffffffffff を取得できる。

                                                floating-point-format
浮動小数点数は次の2つの形式で書ける:

        [-+]{N}.{M}
        [-+]{N}.{M}[eE][-+]{exp}

ここで {N} と {M} は数値である。{N} と {M} の両方とも省略してはならず、数値の
みを含めることができるが、Vim9 script では {N} がシングルクォートで挟まれた
数値である場合を除く。
[-+] は、省略可能なプラスまたはマイナス記号である。
{exp} は指数で、10 のベキ。
現在のロケールが何であれ、小数点にはドットのみを使える。コンマは使えない。

例:
        123.456
        +0.0001
        55.0
        -0.123
        1.234e03
        1.0E-6
        -3.1416e+88

次のものは無効である:
        3.              {M} が空
        1e40            .{M} がない

論理的根拠:
浮動小数点数が導入される前は、123.456 と書くと 123 と 456 の2つの数値と解釈
され、それらが文字列に変換されて結合されて "123456" という文字列になった。
これは無意味であり、Vim script 内で意図的に使われているものが見つからなかった
ので、浮動小数点数の普通の表記法を用いるため、この後方非互換性は許容された。

                                                        float-pi float-e
コピー&ペーストしておくのに便利な値: >
        :let pi = 3.14159265359
        :let e  = 2.71828182846
または、浮動小数点リテラルとして書き込むことを望まない場合は、次のような関数を
使用することもできる: >
        :let pi = acos(-1.0)
        :let e  = exp(1.0)
<
                                                floating-point-precision
浮動小数点数の精度と範囲は、Vim とリンクしたライブラリの "double" の意味によ
る。実行時にこれを変更することはできない。

浮動小数点数 Float は printf("%g", f) とするのと同様に、小数点以下6桁まで表
示される。表示する桁数は printf() を使えば変えられる。例: >
        :echo printf('%.15e', atan(1))
<       7.853981633974483e-01



文字列                                  string String expr-string E114
------
"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進数で表現したもので、実際の値は現在の 'encoding' の値に
        依存する (例えば "\u02a4")
\U....  \u と同じだが8桁までの16進数が使える
\b      バックスペース <BS>
\e      エスケープ <Esc>
\f      フォームフィード 0x0C
\n      改行 <NL>
\r      改行(キャリッジリターン) <CR>
\t      タブ <Tab>
\\      円記号(バックスラッシュ)
\"      ダブルクォート
\<xxx>  "xxx" という名の特殊キー。例 "\<C-W>" は CTRL-W。これはマップで使うた
        めのものであり、0x80 バイトはエスケープされる。
        ダブルクォート文字を使う場合はエスケープしなければならない: "<M-\">"
        UTF-8 文字を得るためには <Char-xxxx> を使わずに、上述の \uxxxx を使う
        こと。
\<*xxx>  \<xxx> と同じだが、文字に修飾子を含むのではなくそれを前に付加する。
        例えば、"\<C-w>" は 0x17 の1文字だが、"\<*C-w>" は 4バイトになる:
        3は CTRL 修飾子で、その後に文字の "W"。

Note "\xff" は値255の1バイトとなる。これはエンコーディングによっては無効な値か
もしれない。現在の 'encoding' の値に応じた文字255を得るには "\u00ff" を使う。

Note "\000" と "\x00" は強制的に文字列の終端として扱われる。


blobリテラル                            blob-literal E973
------------

0zまたは0Zで始まる任意のバイト数の16進数。
シーケンスは偶数個の16進数文字でなければならない。例:
        :let b = 0zFF00ED015DAF


リテラル文字列                                          literal-string E115
--------------
'string'                文字列定数              expr-'

Note シングルクォートが使われていることに注意。

この文字列は文字通りに扱われる。バックスラッシュは取り除かれないし、また特別な
意味を持ったりもしない。唯一の例外は、2つのシングルクォートで1つのシングル
クォートになることである。

シングルクォートの文字列は、バックスラッシュを2重にしなくてよいため、正規表現
パターンを表すのに便利である。以下の2つのコマンドは同値である: >
        if a =~ "\\s*"
        if a =~ '\s*'


文字列補間                                      $quote interpolated-string
----------
$"string"               補間された文字列定数                    expr-$quote
$'string'               補間されたリテラル文字列定数            expr-$'

文字列補間は、文字列 string とリテラル文字列 literal-string の拡張であり、
Vim script の式(expr1 を参照)を含めることができる。任意の値を返す式は波括弧
で囲むことができる。値は文字列に変換される。すべてのテキストと式の結果が連結さ
れ新しい文字列が作成される。
                                                        E1278 E1279
文字列の内容に開き波括弧 '{' または閉じ波括弧 '}' を含めるには、それを2重にす
る。バックスラッシュを使用したダブルクォートで囲まれた文字列も動作する。単一の
閉じ波括弧 '}' はエラーになる。

例: >
        let your_name = input("What's your name? ")
<       What's your name?  Peter ~
>
        echo
        echo $"Hello, {your_name}!"
<       Hello, Peter! ~
>
        echo $"The square root of {{9}} is {sqrt(9)}"
<       The square root of {9} is 3.0 ~

                                                string-offset-encoding
文字列は複数の文字で構成される。文字がどのように格納されるかは 'encoding' に
よって異なる。最も一般的なのは UTF-8 で、ASCII 文字には 1 バイト、その他のラテ
ン文字には 2 バイト、その他の文字にはそれ以上のバイトが使用される。

文字列のオフセットは、文字数またはバイト数をカウントできる。他のプログラムで
は、UTF-16 エンコーディング (16-bit ワード) と 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 .. " です"
        if &insertmode

ここにはあらゆるオプション名を使うことができる。optionsを参照。ローカル変数
を使おうとして、実際にはバッファローカルもウィンドウローカルも存在しない場合に
は、グローバル変数が利用される。


レジスタ                                                expr-register @r
--------
@r                      レジスタ 'r' の値

名前付きレジスタの中身を1つの文字列として得る。必要なところには改行文字が挿入
されている。無名レジスタの中身を取得するには@"か@@を使う。利用可能なレジスタの
説明についてはregistersを参照。

レジスタ '=' を使うと、式の値でなく式そのものを得る。それを評価するには
eval()を使う。


入れ子                                          expr-nesting E110
------
(expr1)                 式の入れ子


環境変数                                                expr-env
--------
$VAR                    環境変数

環境変数の文字列。定義されていない環境変数を指定した場合、結果は空文字列。

`getenv()` と `setenv()` 関数も使用でき、英数字以外の名前を持つ環境変数に対し
て機能する。
`environ()` 関数は、すべての環境変数を含む辞書を取得するために使用できる。


                                                        expr-env-expand
Note $VARを直接使用した場合とexpand("$VAR")を使用した場合では、動作に違いがあ
ることに注意。直接使用した場合には、現在のVimのセッション中で既知の値に展開さ
れるだけである。expand()を使用した場合、まず最初にVimのセッション中で既知の値
に展開される。それが失敗した場合、変数の展開にシェルが使用されることになる。こ
れは遅くはなるが、シェルの知りうる全ての変数を展開することができる。例: >
        :echo $shell
        :echo expand("$shell")
最初の一つは恐らく何も返ってこず、2つ目は $shell の値が返ってくるだろう (貴方
のシェルがそれをサポートしているなら)


内部変数                                expr-variable E1015 E1089
--------
variable                内部変数
以下のinternal-variablesを参照。


関数呼出                expr-function E116 E118 E119 E120
--------
function(expr1, ...)    関数呼出
以下のfunctionsを参照。


ラムダ式                                        expr-lambda lambda
--------
{args -> expr1}         旧来のラムダ式                          E451
(args) => expr1         Vim9 のラムダ式

ラムダ式は、expr1 を評価した結果を返す新しい無名関数を作成する。ラムダ式は以
下の点がユーザー定義関数user-functionsと異なる:

1. ラムダ式の本体は単一の式expr1であり、Exコマンド列ではない。
2. 引数にプリフィックス "a:" を使用しない。例: >
        :let F = {arg1, arg2 -> arg1 - arg2}
        :echo F(5, 2)
<       3

引数は任意である。例: >
        :let F = {-> 'error function'}
        :echo F('ignored')
<       error function

Vim9 lambda は、異なる文法を使用するだけでなく、型チェックを追加し、複数の行
に分割できる。vim9-lambda を参照。

                                                        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

Note: これが正しく機能するためには、ラムダが定義される前の外側のスコープ内にそ
れらの変数が存在していなければならない。: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

Note クロージャが自身の依存するコンテキストから参照されている場合、メモリが使
われたままになり解放されない可能性がある: >
        function Function()
           let x = 0
           let F = {-> x}
         endfunction
このクロージャが関数スコープの "x" を使用しており、そして同じスコープの "F" が
クロージャを参照している。この循環の結果解放されることのないメモリになる。
推奨: このようなことはしないこと。

Exコマンドを実行するためにどのように execute() を使っているかに注目せよ。醜い
が。
Vim9 script ではコマンドブロックが使える。inline-function を参照。

`for` コマンドのループ変数を使用することはできるが、クロージャの呼び出し時にま
だ変数が存在している必要があり、そうでないならエラーになる。 E1302

ラムダ式は '<lambda>42' のような内部名を持っている。もしラムダ式でエラーが発生
した場合には、以下のコマンドでどのラムダ式でエラーが起きたかを調べることができ
る: >
        :function <lambda>42
numbered-functionも参照。

==============================================================================
3. 内部変数                             internal-variables E461 E1001

内部変数の名前には文字と、数字とアンダーバー('_')を使うことができる。しかし数
字で始めることはできない。旧来のスクリプトでは波括弧を使うこともできる。詳細
curly-braces-namesを参照。

旧来のスクリプトでは内部変数は ":let" コマンドで作成される :let。":unlet" コ
マンドで明示的に内部変数を破棄することができる :unlet。内部変数に使われてな
い名前か、既に破棄された内部変数を使うとエラーとなる。

Vim9 script では `:let` は使用せず変数は違う動作をする。:var を参照。

                                                variable-scope
変数には幾つもの名前空間が存在する。実際にどれが利用されるかは、どのような前置
子が使われたかで決まる:

                (無し) 関数の中では関数ローカル
                          旧来のスクリプトでは: グローバル
                          Vim9 script では: スクリプトについてローカル
buffer-variable    b:   現在のバッファにローカル
window-variable    w:   現在のウィンドウにローカル
tabpage-variable   t:   現在のタブページにローカル
global-variable    g:   グローバル
local-variable     l:   関数にローカル(旧来の関数のみ)
script-variable    s:   :sourceされたVim scriptにローカル
function-argument  a:   関数の引数(旧来の関数のみ)
vim-variable       v:   グローバル、Vimがあらかじめ定義

これらのスコープそのものに辞書を通じてアクセスできる。例えば、全てのスクリプト
ローカル変数を削除するには次のようにする: >
        :for k in keys(s:)
        :    unlet s:[k]
        :endfor

Note: Vim9 script では、変数はコマンドのブロックについてローカルにすることもで
きる。vim9-scopes を参照。

                                                buffer-variable b:var b:
"b:" で始まる変数名は、カレントバッファに局所的な変数を意味する。このように一
つ一つのバッファ毎に、変数 "b:foo" を別々に使用することができる。この種の変数
はバッファが掃除(wipe out)された時や、":bdelete" で削除された時に一緒に削除さ
れる。

1つのバッファローカル変数が定義済:
                                        b:changedtick changetick
b:changedtick   現在のバッファに対する総変更の回数。変更を行うたびに増加する。
                これには一回のアンドゥ操作もカウントされる。バッファ書き込み時
                に 'modified' をリセットすることもカウントされる。
                この変数はバッファに変更が行われた際にだけアクションを起こした
                い時に利用できる。例: >
                    :if my_changedtick != b:changedtick
                    :   let my_changedtick = b:changedtick
                    :   call My_Update()
                    :endif
<               b:changedtick 変数を変更したり削除することはできない。
                変更に関する詳細情報が必要な場合は、listener_add() を参照。

                                                window-variable w:var w:
"w:" で始まる変数名は、カレントウィンドウにローカルな変数を意味する。これはウィ
ンドウを閉じるときに破棄される。

                                                tabpage-variable t:var t:
"t:" で始まる変数名は、カレントタブページにローカルな変数を意味する。これはタ
ブページを閉じるときに破棄される。{+windows 機能つきでコンパイルしたときのみ
利用可能}

                                                global-variable g:var g:
関数の中からと Vim9 script でグローバル変数へアクセスするには、"g:" を付けた
名前を使用する。これが省略された場合は関数もしくはスクリプトローカルな変数にア
クセスする。"g:" 自体は、関数の外でも使うことができる。

                                                local-variable l:var l:
関数の中からそのローカル変数にアクセスするには何も前置しなければ良い。明示的
に "l:" を付けることも可能である。ただし "l:" をつけないと予約されている変数名
と衝突してしまうことがある。例: "count" とすると "v:count" を参照してしまう。
"l:count" とすればローカル変数countを参照できる。

                                                script-variable s:var
旧来の Vim script 内では "s:" で始まる変数名を使うことができる。これはスクリプ
トについてローカルであり、スクリプトの外部からはアクセスできない。
Vim9 script では "s:" 始まりは省略でき、変数はスクリプトローカルがデフォルト
になっている。

スクリプト変数は次の場所で使える:
- そのスクリプトをsourceしている間に実行されるコマンド
- そのスクリプト内で定義される関数
- そのスクリプト内で定義される自動コマンド
- そのスクリプト内で定義される関数や自動コマンドで定義される関数や自動コマンド
  (再帰的)
- そのスクリプト内で定義されるユーザー定義コマンド
次の場面では使えない:
- そのスクリプトからsourceされる他のスクリプト
- マッピング
- メニュー
- など。

グローバル変数との衝突を避けるにはスクリプト変数を使う。
次の例を参照: >

        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" だけが変
化する。

これと同じことをするもう1つの例: >

        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()がどこで呼ばれたかに関係なく、
MyCounter()の中では変数s:counterにアクセスできる。

同じスクリプトが再度読み込まれた場合、同一のスクリプト変数が使われる。スクリプ
ト変数は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

Note これはつまり、ファイルタイププラグインはバッファごとにスクリプト変数を1セッ
ト持つのではないということを意味する。そのような目的にはバッファローカル変数
b:varを使うこと。


Vimの定義済変数                                vim-variable v:var v:
                                                        E963 E1063
一部の変数はユーザーが設定できるが、型を変更することはできない。

                                        v:argv argv-variable
v:argv          Vimの起動に使用したコマンドライン引数。これは文字列のリストで
                ある。最初の項目はVimコマンドである。
                コマンドのフルパスは v:progpath を参照。

                                        v:beval_col beval_col-variable
v:beval_col     マウスポインタがある桁の桁番号。v:beval_lnum行目のバイトイン
                デックスである。オプション 'balloonexpr' を評価している最中の
                み有効。

                                        v:beval_bufnr beval_bufnr-variable
v:beval_bufnr   マウスポインタがあるバッファの番号。オプション 'balloonexpr'
                を評価している最中のみ有効。

                                        v:beval_lnum beval_lnum-variable
v:beval_lnum    マウスポインタがある行の行番号。オプション 'balloonexpr' を
                評価している最中のみ有効。

                                        v:beval_text beval_text-variable
v:beval_text    マウスポインタの下もしくは後ろにあるテキスト。Cプログラムのデ
                バッグのために有用。'iskeyword' が適用されるが、マウスポインタ
                の下より前にあるドットと "->" は含まれる。マウスポインタが ']'
                の上にあるときは、そこから対応する '[' とその前にあるテキスト
                までが含まれる。マウスポインタが1行に収まるビジュアル領域の上
                にあるときはその選択領域となる。<cexpr> も参照。
                オプション 'balloonexpr' を評価している最中のみ有効。

                                        v:beval_winnr beval_winnr-variable
v:beval_winnr   マウスポインタがあるウィンドウの番号。オプション 'balloonexpr'
                を評価している最中のみ有効。1番目のウィンドウの番号はゼロであ
                る(他の場所でのウィンドウ番号と異なっている)。

                                        v:beval_winid beval_winid-variable
v:beval_winid   マウスポインタがあるウィンドウのウィンドウID window-ID
                それ以外は v:beval_winnr と同様。

                                        v:char char-variable
v:char          'formatexpr' を評価しているときの引数。また、短縮入力
                :map-<expr> で <expr> を指定しているとき、タイプされた文字を
                保持する。
                これは InsertCharPre と InsertEnter イベントでも使われる。

                        v:charconvert_from charconvert_from-variable
v:charconvert_from
                変換しようとしているファイルの文字エンコーディング名。オプショ
                ン 'charconvert' を評価している最中のみ有効。

                        v:charconvert_to charconvert_to-variable
v:charconvert_to
                変換後のファイルの文字エンコーディング名。オプション
                'charconvert' を評価している最中のみ有効。

                                        v:cmdarg cmdarg-variable
v:cmdarg        2つの目的のために使われる:
                1. ファイルの読み書きコマンドに与えられる余分な引数。現在のと
                   ころ "++enc=" と "++ff=" がそれである。読み書きコマンドに対
                   する自動コマンドイベントが発生する前にこの変数が代入される。
                   その読み書きコマンドの後に直接この変数を連結できるように、
                   先頭にスペースがついている。Note: ここには "+cmd" 引数は含
                   まれていない。どちらにしろそれは実行されるからである。
                2. ":hardcopy" でPostScriptファイルを印刷するとき、これが
                   ":hardcopy" への引数になる。'printexpr' の中で使うことがで
                   きる。

                                        v:cmdbang cmdbang-variable
v:cmdbang       v:cmdargと同じく読み書きコマンドを実行したとき設定される。読み
                書きコマンドに "!" が使われたときは1となり、使われていなければ
                0となる。Note 自動コマンドの中でのみ利用可能なことに注意。
                ユーザー定義コマンドでは<bang>を使えば同じことができる。
                                                v:collate collate-variable
v:collate       現在のロケール設定での実行環境の照合順序。これは Vim script が
                現在のロケールのエンコーディングを検知するのを許可する。技術的
                説明: LC_COLLATE の値となる。ロケールを使用していない時の値は
                "C" となる。この変数は直接は設定できなく、:language コマンド
                を使う。
                multi-lang を参照。
                                                                v:colornames
v:colornames    カラー名を16進数カラー文字列に対応付ける辞書。これらのカラー名
                は、highlight-guifghighlight-guibghighlight-guisp の
                パラメーターで使用できる。

                Vim は色を小文字の色名で探すので、辞書のキーの値 (色名) は小文
                字であるべきである。

                v:colornames のエントリを更新しても、構文ハイライトにすぐに作
                用することはない。更新されたカラー値を使用するには、highlight
                コマンド(おそらくカラースキームスクリプト内)を再評価する必要が
                ある。例: >

                    :let v:colornames['fuscia'] = '#cf3ab4'
                    :let v:colornames['mauve'] = '#915f6d'
                    :highlight Normal guifg=fuscia guibg=mauve
<
                これは cterm-colors を上書きすることはできないが、他のカラー
                を上書きするために使用することはできる。例えば、X11 カラーは
                `colors/lists/default.vim` (以前は rgb.txt で定義されていた)
                で定義されている。プラグインにて新しいカラー名を定義するときに
                推奨される方法は、カラーエントリがまだ存在しない場合にのみ設定
                することである。例: >

                    :call extend(v:colornames, {
                        \ 'fuscia': '#cf3ab4',
                        \ 'mauve': '#915f6d,
                        \ }, 'keep')
<
                'keep' オプションを指定して extend() を使用すると、
                v:colornames に存在しない場合にのみ各カラーが更新される。そ
                うすることで、ユーザーは .vimrc の設定による一般名の正確なカ
                ラー値を選択できる。

                この辞書からエントリを削除することは可能だが、他のスクリプトを
                混乱させるため、それは推奨されない。また、:colorscheme コマ
                ンドと :highlight コマンドの両方が
                `colors/lists/default.vim` カラースクリプト全体を自動的にロー
                ドするため、目的の結果が得られる可能性は低くなる。

                                v:completed_item completed_item-variable
v:completed_item
                最も最近補完された単語が含まれたcomplete-itemsDictionary
                がCompleteDoneイベント後に設定される。補完に失敗した時、その
                Dictionaryは空である。
                Note: プラグインは、組み込みの CompleteDone イベントの動作を
                エミュレートするために、この値を変更することができる。

                                        v:count count-variable
v:count         最後に実行されたノーマルモードコマンドに渡されたカウント数。
                マッピングの前のカウントを取得するのに使用できる。読出し専用。
                使用例: >
        :map _x :<C-U>echo "the count is " .. v:count<CR>
<               Note<C-U>は、カウントの後に ':' をタイプした時に示される行範
                囲指定を削除するために必要となる。
                "3d2w" のようにカウントが2個指定された場合、その数が掛けられる。
                よって "d6w" となる。
                オプション 'formatexpr' を評価するためにも使われる。
                scriptversion が 3以降でなければ、"count" も、以前の版のVim
                との互換性の為に動作する。

                                        v:count1 count1-variable
v:count1        "v:count" と同じだが、カウントが指定されなかった時の既定値が 1
                となる。

                                                v:ctype ctype-variable
v:ctype         文字に関する実行環境の現在のロケール設定。これを使えばVim
                script内で現在のロケール設定に対応できるようになる。技術的な詳
                細: LC_CTYPEに等しい。ロケールを使用していないときは "C"になる。
                この変数を設定するには:languageコマンドを使うこと。直接設定
                することはできない。
                multi-langを参照。

                                        v:dying dying-variable
v:dying         通常時は0。致命的なシグナルを受信したとき1が代入される。複数
                のシグナルを受信すると値が増加していく。自動コマンド内でVimが
                正常に終了するかチェックするために使える。{Unix でのみ動作}
                例: >
        :au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif

<               Note: v:dying が 1 のときに別の致命的なシグナルを受信した場合
                は VimLeave 自動コマンドは実行されない。

                                        v:exiting exiting-variable
v:exiting       Vim の終了コード。通常は0、何か問題があった時は非0。
                VimLeavePre と VimLeave の自動コマンドが実行される前は値が
                v:null。:q:x:cquit を参照。
                例: >
                        :au VimLeave * echo "Exit value is " .. v:exiting
<
                                        v:echospace echospace-variable
v:echospace     hit-enter-prompt を引き起こす前の最後の画面行の `:echo` メッ
                セージに使用できる画面セルの数。'showcmd''ruler' および
                'columns' に依存する。最後の行の上に全幅の行があるかどうかを
                'cmdheight' で確認する必要がある。

                                        v:errmsg errmsg-variable
v:errmsg        最後に表示されたエラーメッセージ。この変数は代入することが許
                されている。例: >
        :let errmsg = ""
        :next
        :if (errmsg != "")
        :  ...
<               scriptversion が 3以降でなければ、"errmsg" も、以前の版のVim
                との互換性の為に動作する。

                                v:errors errors-variable assert-return
v:errors        assert_true()のような、テスト用関数によって見つかったエラー。
                これは文字列のリストである。
                テスト用関数はテストに失敗した時にエラーを末尾に追加する。
                戻り値が示すもの: 要素が v:errors に追加された場合 1 が返る。
                それ以外では 0 が返る。
                古い結果を削除する方法はこの変数を空にする: >
        :let v:errors = []
<               たとえv:errors にリスト以外のいかなる値をセットしたとしても、
                (次に実行される時に)テスト用関数によって空のリストが設定(上書
                き)される。

                                        v:event event-variable
v:event         現在の autocommand に関する情報を含む辞書。辞書に何が入るか
                は個々のイベントを参照。
                この辞書は autocommand が終了したときに空にされる。独立した
                コピーの取得方法については dict-identity を参照。イベントト
                リガー後の情報を保持したいのであれば deepcopy() を使うこと。
                例: >
                        au TextYankPost * let g:foo = deepcopy(v:event)
<
                                        v:exception exception-variable
v:exception     最も直近に捕捉され、まだ終了していない例外の値。
                v:throwpointthrow-variablesを参照。
                例: >
        :try
        :  throw "oops"
        :catch /.*/
        :  echo "caught " .. v:exception
        :endtry
<               出力: "caught oops".

                                        v:false false-variable
v:false         数値0。JSONでは "false" として使われる。json_encode()を参照。
                文字列として使われた時、これは "v:false" として評価される。 >
                        echo v:false
<                       v:false ~
                これは eval() がその文字列をパースしたときに、元の値に戻せるよ
                うにするためである。読出し専用。
                Vim9 script では、真偽値型として "false" を使用できる。

                                        v:fcs_reason fcs_reason-variable
v:fcs_reason    FileChangedShellイベントが発生した理由。自動コマンドの中で何
                をすべきかやv:fcs_choiceに何を代入すべきかを決めるために使う。
                値は次のどれかとなる:
                        deleted         もはやファイルが存在しない
                        conflict        ファイルの内容、モード、タイムスタンプ
                                        が変化しており、バッファが変更されてい
                                        る状態。
                        changed         ファイルの内容が変化している
                        mode            ファイルのモードが変化している
                        time            タイムスタンプだけが変化している

                                        v:fcs_choice fcs_choice-variable
v:fcs_choice    FileChangedShellイベントが発生した後に何をすべきかを表す。
                自動コマンドの中で、そのバッファに対して何をすべきかを指示する
                ために使う。
                        reload          バッファを読み直す(バッファが削除され
                                        ている場合には効果がない)。
                        edit            バッファを読み直し 'fileformat'
                                        'fileencoding''binary' オプションの
                                        値の検出を行う(ファイル削除時は動作し
                                        ない)。
                        ask             何をすべきかをユーザーに問い合わせる。
                                        これはこの自動コマンドがない場合と同じ
                                        である。ただしタイムスタンプだけが変化
                                        しているときは何もしない。
                        <empty>         何もしない。自動コマンドの中だけで必要
                                        なことは全て行ってしまっているという場
                                        合にこの値を代入する。
                既定値は<empty>。これら以外の(無効な)値が代入されたときは空の
                ときと同じ動作になり、警告メッセージは表示されない。

                                        v:fname fname-variable
v:fname         'includeexpr' の評価中: 検知したファイル名。それ以外のときは空。

                                        v:fname_in fname_in-variable
v:fname_in      入力ファイルの名前。以下のオプションを評価している最中のみ
                有効:
                        オプション      このファイル名の意味 ~
                        'charconvert'   変換するファイル
                        'diffexpr'      元のファイル
                        'patchexpr'     元のファイル
                        'printexpr'     印刷するファイル
                また、自動コマンドイベントSwapExistsが発生したときスワップ
                ファイル名が代入される。

                                        v:fname_out fname_out-variable
v:fname_out     出力ファイルの名前。以下のオプションを評価している最中のみ
                有効:
                        オプション      このファイル名の意味 ~
                        'charconvert'   変換した結果のファイル (*)
                        'diffexpr'      diffの出力
                        'patchexpr'     パッチを当てた結果のファイル
                (*) 書き込みコマンド(":w file" など)を実行する際の変換では
                v:fname_inと同じになる。読み込みコマンド(":e file" など)を実行
                する際の変換では一時ファイル名になり、v:fname_inと異なる。

                                        v:fname_new fname_new-variable
v:fname_new     新しい方のファイル名。'diffexpr' を評価している最中のみ有効。

                                        v:fname_diff fname_diff-variable
v:fname_diff    diff(patch)ファイルの名前。'patchexpr' を評価している最中のみ
                有効。

                                        v:folddashes folddashes-variable
v:folddashes    'foldtext' 用。閉じた折り畳みのレベルを表すダッシュ。
                サンドボックスsandboxの中では読出し専用。fold-foldtext

                                        v:foldlevel foldlevel-variable
v:foldlevel     'foldtext' 用。閉じた折り畳みのレベル。
                サンドボックスsandboxの中では読出し専用。fold-foldtext

                                        v:foldend foldend-variable
v:foldend       'foldtext' 用。閉じた折り畳みの最後の行。
                サンドボックスsandboxの中では読出し専用。fold-foldtext

                                        v:foldstart foldstart-variable
v:foldstart     'foldtext' 用。閉じた折り畳みの最初の行。
                サンドボックスsandboxの中では読出し専用。fold-foldtext

                                        v:hlsearch hlsearch-variable
v:hlsearch      検索による強調表示がオンになっているかどうかを示す変数。
                設定は +extra_search 機能が必要な 'hlsearch' が有効になって
                いる時のみ意味をなす。この変数を0に設定することは、
                :nohlsearchコマンドを実行することと同様に働き、1に設定するこ
                とは以下と同様に働く >
                        let &hlsearch = &hlsearch
<               関数から戻ったときに値が復元されることに注意すること。
                function-search-undo

                                        v:insertmode insertmode-variable
v:insertmode    自動コマンドイベントInsertEnterInsertChange用。
                値は次のどれか:
                        i       挿入モード
                        r       置換モード
                        v       仮想置換モード

                                                v:key key-variable
v:key           辞書Dictionaryの現在の要素のキー。map()filter()で使わ
                れる式を評価している最中のみ有効。
                読出し専用。

                                                v:lang lang-variable
v:lang          メッセージに関する実行環境の現在のロケール設定。これを使えば
                Vim script内で現在のロケール設定に対応できるようになる。
                技術的な詳細: LC_MESSAGESに等しい。この値はシステムに依存する。
                この変数を設定するには:languageコマンドを使うこと。直接設定
                することはできない。
                文字エンコーディングに使うのと違う言語でメッセージを表示させた
                い場合はv:ctypeと異なる値でもよい。multi-langを参照。

                                                v:lc_time lc_time-variable
v:lc_time       時刻のメッセージに関する実行環境の現在のロケール設定。これを使
                えばVim script内で現在のロケール設定に対応できるようになる。
                技術的な詳細: LC_TIMEに等しい。この値はシステムに依存する。こ
                の変数を設定するには:languageコマンドを使うこと。直接設定す
                ることはできない。

                                                v:lnum lnum-variable
v:lnum          'foldexpr' fold-expr と 'indentexpr' に使うための行番号。ま
                た 'guitablabel' と 'guitabtooltip' の文脈ではタブページ番号に
                なる。これらの式のどれかを評価しているときのみ有効。サンドボッ
                クス sandbox の中では読出し専用。

                                                v:maxcol maxcol-variable
v:maxcol        最大行長。使用場所に応じて、画面の行数、文字数、またはバイト数
                になる。現在はすべてのシステムで値が2147483647になっている。

                                        v:mouse_win mouse_win-variable
v:mouse_win     getchar()でマウスクリックイベントが発生したときのウィンドウ
                番号。winnr()と同じく番号は1から始まる。マウスがクリックされ
                なかったときは0となる。

                                        v:mouse_winid mouse_winid-variable
v:mouse_winid   getchar()でマウスクリックイベントが発生したときのウィンドウ
                ID。マウスがクリックされていないときは0になる。

                                        v:mouse_lnum mouse_lnum-variable
v:mouse_lnum    getchar()でマウスクリックイベントが発生したときの行番号。物
                理行ではなく論理行。マウスがクリックされていないときは0となる。

                                        v:mouse_col mouse_col-variable
v:mouse_col     getchar()でマウスクリックイベントが発生したときの桁番号。
                virtcol()と同じく画面上の桁番号。マウスがクリックされていな
                いときは0となる。

                                        v:none none-variable None
v:none          空の文字列。JSONでは空の要素として使われる。
                json_encode()を参照。
                これは関数の引数のデフォルト値に使うこともできる、
                none-function_argument を参照。
                数値として使われた時、これは 0 として評価される。
                文字列として使われた時、これは "v:none" として評価される。 >
                        echo v:none
<                       v:none ~
                これは eval() がその文字列をパースしたときに、元の値に戻せるよ
                うにするためである。読出し専用。
                Note `== v:none` および `!= v:none` の使用はエラーになる場合が
                ある。代わりに `is v:none` および `isnot v:none` を使用する。

                                        v:null null-variable
v:null          空の文字列。JSONでは "null" として使われる。json_encode()
                参照。数値として使われた時、これは 0 として評価される。
                文字列として使われた時、これは "v:null" として評価される。 >
                        echo v:null
<                       v:null ~
                これは eval() がその文字列をパースしたときに、元の値に戻せるよ
                うにするためである。読出し専用。
                Vim9 script では、`null` は "v:" なしで使用できる。
                `v:null` と `null` はリスト、辞書、Jobなどいくつかの場所で設定
                なしとして使用できる。これは空のリスト、辞書などとは異なる。

                                        v:numbermax numbermax-variable
v:numbermax     数値の最大値。

                                        v:numbermin numbermin-variable
v:numbermin     数値の最小値(負数)。

                                        v:numbersize numbersize-variable
v:numbersize    数値のビット数。これは通常64で、システムによっては32になること
                がある。

                                        v:oldfiles oldfiles-variable
v:oldfiles      起動時に viminfo から読み込まれたファイルの名前のリスト。
                これらはマークを記憶しているファイルである。リストの長さの上限
                はオプション 'viminfo' の引数 ' によって決まる(既定では 100)。
                viminfo ファイルが使われていない時、リストは空となる。
                :oldfiles と c_#< を参照。
                このリストは変更可能であるが、後で viminfo ファイルに書き込ま
                れるものには影響しない。文字列以外の値を使うと問題を引き起こす
                だろう。
                {+viminfo 機能つきでコンパイルされたときのみ有効}

                                                    v:option_new
v:option_new    オプションに設定された新しい値。自動コマンド OptionSet を実
                行している間のみ有効。
                                                    v:option_old
v:option_old    オプションの以前の値。自動コマンド OptionSet を実行している
                間のみ有効。設定に使用されたコマンドおよびオプションの種類に
                よって、ローカルの以前の値またはグローバルの以前の値のどちらか
                になる。
                                                    v:option_oldlocal
v:option_oldlocal
                オプションの以前のローカル値。OptionSet 自動コマンドの実行中
                に有効である。
                                                    v:option_oldglobal
v:option_oldglobal
                オプションの以前のグローバル値。OptionSet 自動コマンドの実行
                中に有効である。
                                                    v:option_type
v:option_type   set コマンドのスコープ。自動コマンド OptionSet を実行している
                間のみ有効。"global" もしくは "local" のどちらかとなる。
                                                    v:option_command
v:option_command
                オプションを設定するために使われたコマンド。OptionSet 自動コ
                マンドの実行中に有効である。
                        値              オプションは以下によって設定された ~
                        "setlocal"      :setlocal または ":let l:xxx"
                        "setglobal"     :setglobal または ":let g:xxx"
                        "set"           :set または :let
                        "modeline"      modeline
                                        v:operator operator-variable
v:operator      ノーマルモードにおいて最後に実行したオペレータコマンド。基本的
                に1文字である。例外は <g> や <z> で始まるコマンドで、その場合
                は2文字になる。v:prevcount と v:register と組み合わせて使う
                とよい。オペレータ待機モードをキャンセルして、それからオペレー
                タを使いたいときに便利である。例: >
                        :omap O <Esc>:call MyMotion(v:operator)<CR>
<               この値は他のオペレータが入力されるまでセットされてい
                る。よって空になると期待してはいけない。
                :delete:yank などの Ex コマンドに対しては v:operator は
                セットされない。
                読出し専用。

                                        v:prevcount prevcount-variable
v:prevcount     最後の1つ前のノーマルモードコマンドに与えられたカウントの値。
                前のコマンドのv:countの値である。ビジュアルモードやオペレータ
                待機モードをキャンセルし、その後にカウントを使う場合に便利であ
                る。例: >
                        :vmap % <Esc>:call MyFilter(v:prevcount)<CR>
<               読出し専用。

                                        v:profiling profiling-variable
v:profiling     通常時は0。":profile start" を実行すると1が代入される。
                profilingを参照。

                                        v:progname progname-variable
v:progname      Vimを起動したときのプログラム名(パスは除かれる)。view
                evim などの名前やシンボリックリンクなどで起動した場合に特別な
                初期化を行うのに便利。
                読出し専用。

                                        v:progpath progpath-variable
v:progpath      Vim を起動したときのコマンド (パスを含む)。--remote-expr で
                Vim サーバーにメッセージを送信するときに便利。
                Vimが呼び出されたときのコマンドが含まれている。シェルに渡され
                ると、現在のVimと同じVim実行可能ファイルが実行される($PATHが変
                更されない場合)。 --remote-expr を使用してVimサーバーにメッ
                セージを送信する場合に便利である。
                フルパスを得るには: >
                        echo exepath(v:progpath)
<               コマンドが相対パスの場合、フルパスに展開されるため、`:cd` の後
                でも機能する。したがって、"./vim" を開始すると
                "/home/user/path/to/vim/src/vim" という結果になる。
                Linuxおよびその他のシステムでは、常にフルパスになる。Macでは単
                に "vim" であり、前述の exepath() を使用してフルパスを取得する
                必要がある。
                MS-Windows では実行ファイルが "vim.exe" として呼び出されるかも
                しれないが、".exe" は v:progpath には追加されない。
                読出し専用。

                                v:python3_version python3-version-variable
v:python3_version
                Vim がビルドされた Python 3 のバージョン。Python が動的にロー
                ドされる場合 (python-dynamic)、このバージョンは Python ライ
                ブラリのマイナーバージョンと完全に一致しなければならない (例え
                ば 3.10.2 と 3.10.3 はマイナーバージョンが "10" なので互換性が
                あるが、3.9.4 と 3.10.3 は互換性がない)。python-stable-abi
                が使われた場合、代わりにこれは使える Python の最小バージョンに
                なる。(例えば、v:python3_version が 3.9 を示す場合、3.9 でも
                3.10 でもそれ以上でも使える)。

                この数値は Python ABI バージョン管理規則に従って 16 進数でエン
                コードされる。16 進数で人間が読める完全なバージョンを得るには:
>
                        echo printf("%08X", v:python3_version)
<               次のようにすることで、マイナーバージョンのみを取得することがで
                きる: >
                        echo and(v:python3_version>>16,0xff)
<               読み取り専用。

                                        v:register register-variable
v:register      現在のノーマルモードコマンドに適用されるレジスタの名前 (そのコ
                マンドが実際にレジスタを使うかどうかには依らない)。または、現
                在実行しているノーマルモードマッピング用のレジスタの名前 (レジ
                スタを使うカスタムコマンドの中で使う)。レジスタが指定されなかっ
                たときはデフォルトレジスタ '"' になる。'clipboard' に
                "unnamed" か "unnamedplus" が含まれているときはデフォルトはそ
                れぞれ '*' か '+' になる。
                getreg() と setreg() も参照。

                                        v:scrollstart scrollstart-variable
v:scrollstart   画面のスクロールの原因となったスクリプトや関数を説明する
                文字列。空であるときのみ代入される。よってこの変数には最初の原
                因だけが記録されている。原因がキーボードから入力されたコマンド
                の場合は "Unknown" {訳注: 日本語メッセージの場合: "不明"} が代
                入される。
                スクリプトを実行したとき現れたhit-enterプロンプトの原因を探る
                ために便利。

                                        v:servername servername-variable
v:servername    client-server-name で登録された結果。
                読出し専用。


v:searchforward                 v:searchforward searchforward-variable
                検索方向: 前方検索の後なら1、後方検索の後なら0。quote/ で示す
                方法によって最終検索パターンを直接セットしたときは1(前方検索)
                にリセットされる。
                関数から戻るとき、この値は呼び出し前の値に復元される。
                function-search-undo
                読み書き両用。

                                        v:shell_error shell_error-variable
v:shell_error   最後に実行したシェルコマンドの結果。シェルコマンドの実行時に何
                かエラーがあったならば、非零の値を取る。問題がなければ零になる。
                これはシェルがエラーコードをVimに通知する時のみ働く。コマンドが
                実行されなかった時には、値として-1が良く使われる。読出し専用。
                例: >
        :!mv foo bar
        :if v:shell_error
        :  echo 'could not rename "foo" to "bar"!'
        :endif
<               scriptversion が 3以降でなければ、"shell_error" も、以前の版
                のVimとの互換性の為に動作する。

                                        v:sizeofint sizeofint-variable
v:sizeofint     intのバイト数。Vimがどのようにコンパイルされたかに依存する。
                これは、テストで期待通りの結果が得られるかどうかを判断する場合
                にのみ役立つ。

                                        v:sizeoflong sizeoflong-variable
v:sizeoflong    longのバイト数。Vimがどのようにコンパイルされたかに依存する。
                これは、テストで期待通りの結果が得られるかどうかを判断する場合
                にのみ役立つ。

                                v:sizeofpointer sizeofpointer-variable
v:sizeofpointer ポインタのバイト数。Vimがどのようにコンパイルされたかに依存す
                る。これは、テストで期待通りの結果が得られるかどうかを判断する
                場合にのみ役立つ。

                                        v:statusmsg statusmsg-variable
v:statusmsg     最後に表示されたステータスメッセージ。この変数は代入すること
                が許されている。

                                        v:swapname swapname-variable
v:swapname      自動コマンドSwapExistsを実行している最中のみ有効。見つかった
                スワップファイルの名前。読出し専用。

                                        v:swapchoice swapchoice-variable
v:swapchoice    イベントSwapExistsにより実行された自動コマンドが、見つかった
                スワップファイルをどう処理するかをこの変数に代入する。
                        'o'     読込専用で開く
                        'e'     とにかく編集する
                        'r'     復活させる
                        'd'     スワップファイルを削除する
                        'q'     終了する
                        'a'     中止する
                この変数の値は1文字の文字列でなければならない。値が空のときは
                自動コマンドSwapExistsが存在しないときと同じようにユーザーに問
                い合わせる。既定値は空。

                                        v:swapcommand swapcommand-variable
v:swapcommand   ファイルを開いた後に実行するノーマルモードコマンド。自動コマン
                ドSwapExistsで、他のVimインスタンスにファイルを開かせ、指定
                位置までジャンプするために使うことができる。例えば、あるタグへ
                ジャンプするには、この変数に":tag tagname\r" という値を代入す
                る。":edit +cmd file" を実行させるには":cmd\r" を代入する。

                                v:t_TYPE v:t_bool t_bool-variable
v:t_bool        真偽値 Boolean 型の値。読出し専用。 参照: type()
                                        v:t_channel t_channel-variable
v:t_channel     チャネル Channel 型の値。読出し専用。 参照: type()
                                        v:t_dict t_dict-variable
v:t_dict        辞書 Dictionary 型の値。読出し専用。 参照: type()
                                        v:t_float t_float-variable
v:t_float       浮動小数点数 Float 型の値。読出し専用。 参照: type()
                                        v:t_func t_func-variable
v:t_func        Funcref 型の値。読出し専用。 参照: type()
                                        v:t_job t_job-variable
v:t_job         ジョブ Job 型の値。読出し専用。 参照: type()
                                        v:t_list t_list-variable
v:t_list        リスト List 型の値。読出し専用。 参照: type()
                                        v:t_none t_none-variable
v:t_none        特殊値 None 型の値。読出し専用。 参照: type()
                                        v:t_number t_number-variable
v:t_number      数値 Number 型の値。読出し専用。 参照: type()
                                        v:t_string t_string-variable
v:t_string      文字列 String 型の値。読出し専用。 参照: type()
                                        v:t_blob t_blob-variable
v:t_blob        Blob 型の値。読出し専用。 参照: type()
                                        v:t_class t_class-variable
v:t_class       class 型の値。読出し専用。 参照: type()
                                        v:t_object t_object-variable
v:t_object      object 型の値。読出し専用。 参照: type()
                                        v:t_typealias t_typealias-variable
v:t_typealias   typealias 型の値。読出し専用。 参照: type()

                                v:termresponse termresponse-variable
v:termresponse  termcapのエントリt_RVで端末から返されるエスケープシーケンス。
                ESC [ または CSI で始まり、次に '>' または '?' が来て、途中数
                字と ';' だけから構成され 'c' で終わるエスケープシーケンスを受
                け取ったとき代入される。このオプションがセットされると自動コマ
                ンドイベント TermResponse が発生し、端末からの応答に反応するこ
                とができる。また、同様に自動コマンドイベント TermResponseAll
                が <amatch> に "version" がセットされた状態で発生する。
                terminalprops() を使うことで Vim が端末をどのように認識した
                かを知ることができる。
                新しいxtermからの応答は次の形式である:
                 "<Esc>[> Pp ; Pv ; Pc c"。ここでPpは端末のタイプ: 0ならvt100、
                 1ならvt220。Pvはパッチレベル(パッチ95で導入されたため常に95以
                 上)。Pcは常に0。
                Pv が141以上の場合、Vim は端末コードの要求を試す。これは xterm
                でのみ動作する xterm-codes
                {Vimが+termresponse機能付きでコンパイルされたときのみ有効}

                                                v:termblinkresp
v:termblinkresp termcapのエントリ t_RC で端末から返されるエスケープシーケン
                ス。端末カーソルが点滅しているかを調べるために使用される。
                term_getcursor() で使用される。このオプションがセットされて
                いるとき、<amatch> に "cursorblink" がセットされた状態で自動コ
                マンドイベント TermResponseAll が発生する。

                                                v:termstyleresp
v:termstyleresp termcapのエントリ t_RS で端末から返されるエスケープシーケン
                ス。カーソルの形状を調べるために使用される。term_getcursor()
                で使用される。このオプションがセットされているとき、<amatch>
                に "cursorshape" がセットされた状態で自動コマンドイベント
                TermResponseAll が発生する。

                                                v:termrbgresp
v:termrbgresp   termcapのエントリ t_RS で端末から返されるエスケープシーケン
                ス。端末の背景色を調べるために使用される。'background' を参照。
                このオプションがセットされているとき、<amatch> に "background"
                がセットされた状態で自動コマンドイベント TermResponseAll が発
                生する。

                                                v:termrfgresp
v:termrfgresp   termcapのエントリ t_RF で端末から返されるエスケープシーケン
                ス。端末の文字色を調べるために使用される。このオプションがセッ
                トされているとき、<amatch> に "foreground" がセットされた状態
                で自動コマンドイベント TermResponseAll が発生する。

                                                v:termu7resp
v:termu7resp    termcapのエントリ t_u7 で端末から返されるエスケープシーケン
                ス。曖昧な幅の文字に対して端末が何をするか調べるのに使われる。
                'ambiwidth' を参照。このオプションがセットされているとき、
                <amatch> に "ambiguouswidth" がセットされた状態で自動コマンド
                イベント TermResponseAll が発生する。

                                        v:testing testing-variable
v:testing       `test_garbagecollect_now()` を使う前に設定する必要がある。
                また、これが設定されていると、特定のエラーメッセージが 2 秒間
                表示されなくなる。(例: "'dictionary' option is empty")

                                v:this_session this_session-variable
v:this_session  最後にロードされたか、セーブされたセッションファイルの完全な
                ファイル名。:mksessionを参照。この変数は代入することが許さ
                れている。それ以前にセーブされたセッションがなければ、この変数
                は空となる。
                scriptversion が 3以降でなければ、"this_session" も、以前の
                版のVimとの互換性の為に動作する。

                                        v:throwpoint throwpoint-variable
v:throwpoint    最も直近に捕捉されてまだ終了していない例外が発生した位置。キー
                ボードから入力されたコマンドは記録されていない。v:exception
                とthrow-variablesも参照。
                例: >
        :try
        :  throw "oops"
        :catch /.*/
        :  echo "Exception from" v:throwpoint
        :endtry
<               出力: "Exception from test.vim, line 2"

                                                v:true true-variable
v:true          数値1。JSONでは "true" として使われる。json_encode()を参照。
                文字列として使われた時、これは "v:true" として評価される。 >
                        echo v:true
<                       v:true ~
                これは eval() がその文字列をパースしたときに、元の値に戻せるよ
                うにするためである。読出し専用。
                Vim9 script では、真偽値型として "true" を使用できる。
                                                v:val val-variable
v:val           リストListもしくは辞書Dictionaryの現在の要素の値。map()
                とfilter()で使われる式を評価している最中のみ有効。読出し専
                用。

                                        v:version version-variable
v:version       Vimのバージョン番号。メジャーバージョン番号は100倍され、マイ
                ナーバージョン番号と足されている。Version 5.0は500。Version
                5.1は501となる。読出し専用。scriptversion が 3以降でなけれ
                ば、"version" も、以前の版のVimとの互換性の為に動作する。
                特定のパッチが適用されているかを調べるにはhas()を使う。例: >
                        if has("patch-7.4.123")
<               Note 5.0と5.1には両方ともパッチ123が存在しているが、バージョン
                が違えば番号は同じでもパッチの内容は全く異なっている。

                                        v:versionlong versionlong-variable
v:versionlong   v:versionと同じだが、最後の4桁にパッチレベルも含む。パッチ 123
                を適用したバージョン 8.1 の値は 8010123 である。これは次のよう
                に使用できる: >
                        if v:versionlong >= 8010123
<               ただし、含まれているパッチのリストに隙間がある場合は、うまくい
                かない。これは、最近のパッチが古いバージョンに含まれていた場合
                に起こる。例えば、セキュリティ修正のため。
                パッチが実際に含まれていることを確認するためには has() 関数を
                使用すること。

                                v:vim_did_enter vim_did_enter-variable
v:vim_did_enter ほとんどのスタートアップが完了するまでの間 0。VimEnter 自動
                コマンドが実行される直前に 1 にセットされる。

                                        v:warningmsg warningmsg-variable
v:warningmsg    最後に表示された警告メッセージ。この変数は代入することが許され
                ている。

                                        v:windowid windowid-variable
v:windowid      X11 ベースの GUI を使っているとき、もしくは端末の Vim を使って
                いて X サーバーに接続しているとき (-X) は、ウィンドウ ID が
                セットされる。
                MS-Windows の GUI を使っているときはウィンドウハンドルがセット
                される。
                それ以外では値はゼロである。
                Note: Vim の中のウィンドウを扱うときは winnr() または
                win_getid() を使う。window-ID を参照。

==============================================================================
4. 組み込み関数                                         functions

機能別に分類された一覧は function-list を参照のこと。

すべての組み込み関数のアルファベット順の一覧と詳細は、別のヘルプファイルに分離
した: builtin-functions

==============================================================================
5. 関数定義                                             user-functions

ユーザーは自分で新しい関数を定義することができる。その関数は組込み関数とまった
く同じように呼び出せる。関数は引数を取り、一連のExコマンドを実行して値を返せる。

関数定義についてほとんどの情報を userfunc.txt で見付けることができる。
より高速に実行され、型チェックなどをサポートする Vim9 関数については、
vim9.txt を参照。

==============================================================================
6. 波括弧変数                                           curly-braces-names

変数を使用可能なほとんどの文脈では「波括弧」変数を使うことができる。これは有効
な変数名であり、次のように、1個以上の式を波括弧{}で囲む: >
        my_{adjective}_variable

これは旧来のスクリプトのみで動作し、Vim9 script では動かない。

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

NoteVim9 script では、`:let` は使用されない。`:var` は変数宣言に使用され、
代入はコマンドを使用しない。vim9-declaration

:let {var-name} = {expr1}                               :let E18
                        内部変数{var-name}に式{expr1}の結果をセットする。変数
                        の型は{expr1}によって決定される。{var-name}という変数
                        がまだ存在しない場合、新たに作成される。

:let {var-name}[{idx}] = {expr1}                        E689 E1141
                        リストの要素に式{expr1}の結果をセットする。{var-name}
                        はリストを参照し、{idx}はそのリストの有効なインデック
                        スでなければならない。ネストしたリストに対してはイン
                        デックスを繰り返すことができる。
                        このコマンドはリストに要素を追加するためには使えない。
                        文字列の i バイト目をセットするためにも使えない。それ
                        には次のようにする: >
                                :let var = var[0:2] .. 'X' .. var[4:]
<                       {var-name}が Blob の場合、{idx}はblobの長さになる。
                        この場合、1バイトが追加される。

                                        E711 E719 E1165 E1166 E1183
:let {var-name}[{idx1}:{idx2}] = {expr1}                E708 E709 E710
                        リストListの一部を式{expr}の値で置き換える。{expr}
                        値は正しい個数の要素を持つリストでなければならない。
                        {idx1}を省略すると0となる。
                        {idx2}を省略するとリストの末尾となる。
                        指定された範囲の一部がリストの末尾を越える場合、要素が
                        追加される。

                        :let+= :let-= :letstar= :let/=  :let%=
                        :let.= :let..= E734 E985 E1019
: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 を作る代わりにそ
                        の場で変更する。
                        `.=` はVim scriptバージョン2以降ではサポートされていな
                        い。vimscript-version を参照。


:let ${env-name} = {expr1}                      :let-environment :let-$
                        環境変数{env-name}に式{expr1}の結果をセットする。型は
                        常に文字列。

                        一部のシステムでは、環境変数を空にすると環境変数が削除
                        される。多くのシステムは、設定されていない環境変数と空
                        の環境変数を区別しない。

:let ${env-name} .= {expr1}
                        環境変数{env-name}{expr1}を付け加える。その環境変数
                        が存在しないときは "=" と同様に働く。

:let @{reg-name} = {expr1}                      :let-register :let-@
                        式{expr1}の結果をレジスタ{reg-name}に書きこむ。
                        {reg-name}は単一の文字でかつ、書きこむことのできるレジ
                        スタでなければならない(registersを参照)。"@@" は名前
                        無しレジスタとして使用でき、"@/" はサーチパターンとし
                        て使用できる。
                        {expr1}の結果が<CR><NL>で終了していた場合、レジスタ
                        は行単位で設定され、そうでなければ文字単位で設定される。
                        次のコマンドにより最後に検索したパターンをクリアするこ
                        とができる: >
                                :let @/ = ""
<                       これは空文字列を検索するのとは異なる。空文字列を検索す
                        ると、いたるところでマッチする。

:let @{reg-name} .= {expr1}
                        レジスタ{reg-name}{expr1}を付け加える。このレジスタ
                        が空のときは、そこに{expr1}をセットする。

:let &{option-name} = {expr1}                   :let-option :let-&
                        オプション{option-name}に式{expr}の値をセットする。文
                        字列や数値の値はそのオプションの型に変換される。
                        ウィンドウやバッファについてローカルなオプションに対し
                        ては、その効果は:setコマンドを使ったときと同様で、ロー
                        カルな値とグローバルな値の両方が変更される。
                        例: >
                                :let &path = &path .. ',/usr/local/include'
<                       これは、t_xx 形式の端末コードにも使える。ただし、英数
                        字の名前に限る。例: >
                                :let &t_k1 = "\<Esc>[234;"
<                       コードが存在していなかったときは端末キーコードとして作
                        成され、エラーは発生しない。

:let &{option-name} .= {expr1}
                        文字列のオプションの場合: その値に{expr}を付け加える。
                        :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と同様に働
                        く。
                                                                E1093
:let [{name1}{name2}, ...] = {expr1}          :let-unpack E687 E688
                        {expr1}の値はリストListでなければならない。そのリス
                        トの最初の要素が{name1}に代入され、2番目の要素が
                        {name2}に代入される。以下同様。
                        nameの個数がリストListの要素の個数に一致しなければな
                        らない。
                        前述のように各nameは ":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の要素数がnamesの
                        数より多くてもよい。余った要素のリストが{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}
text...
text...
{endmarker}
                        内部変数 {var-name} を文字列 {endmarker} で囲まれたテ
                        キスト行を含むリスト List に設定する。{endmarker} は
                        空白を含んではならない。

                        "eval" が指定されていない場合、テキストの各行は
                        literal-string として扱われるが、シングルクォートは
                        除外され2重にする必要はない。
                        "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} の後の空白に気をつけること!

                        "trim" がない場合は、テキスト行内の全ての空白文字は保
                        持される。もし {endmarker} の前に "trim" が指定されて
                        いる場合、インデントが取り除かれるため以下を実行でき
                        る: >
                                let text =<< trim END
                                  if ok
                                    echo 'done'
                                  endif
                                END
<                       結果: ["if ok", "  echo 'done'", "endif"]
                        マーカーは "let" のインデントと並ばなければならず、最
                        初の行のインデントは全てのテキスト行から取り除かれる。
                        具体例: 最初の空でないテキスト行の先頭のインデントと完
                        全に一致する全ての先頭のインデントは入力行から削除され
                        る。`let` の前の先頭のインデントと完全に一致する先頭の
                        インデントはすべて {endmarker} を含む行から削除される。
                        Note スペースとタブの違いが重要であることに注意するこ
                        と。

                        {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の変数
                        Vim9 script では動作しない。 vim9-declaration

:let                    全変数の値を一覧表示する。値の前に変数の型が示される:
                            <nothing>   文字列
                                #       数値
                                *       Funcref
                        Vim9 script では動作しない。 vim9-declaration

:unl[et][!] {name} ...                  :unlet :unl E108 E795 E1081
                        内部変数{name}を削除する。複数の変数名を指定すると、そ
                        れらが全て削除される。名前はリストListや辞書
                        Dictionaryの要素でもよい。
                        [!]をつけると存在しない変数に対するエラーメッセージを
                        表示しない。
                        リストListから1個以上の要素を削除することができる: >
                                :unlet list[3]    " 4番目の要素を削除
                                :unlet list[3:]   " 4番目から最後までの要素を
                                                    削除
<                       辞書からは一度に1個の要素を削除することができる: >
                                :unlet dict['two']
                                :unlet dict.two
<                       グローバル変数とスクリプトローカル変数をクリーンアップ
                        するために特に便利である(これらはスクリプト終了時に検
                        出されない)。関数ローカルな関数は、その関数から抜ける
                        ときに自動的に削除される。
                        Vim9 scriptでは、関数内またはスクリプトで宣言された
                        変数は削除できない。

:unl[et] ${env-name} ...                        :unlet-environment :unlet-$
                        環境変数 {env-name} を削除する。
                        一つの :unlet コマンドの中に {name} と ${env-name} を
                        混ぜることができる。! が付いていない場合でも、存在しな
                        い変数に対してエラーメッセージは表示されない。
                        システムが環境変数の削除をサポートしていない場合は空に
                        する。

                                                :cons :const E1018
:cons[t] {var-name} = {expr1}
:cons[t] [{name1}{name2}, ...] = {expr1}
:cons[t] [{name}, ..., ; {lastname}] = {expr1}
:cons[t] {var-name} =<< [trim] {marker}
text...
text...
{marker}
                        :letに似ているが、加えて、値がセットされたあとに変数
                        がロックされる。これは、ロックされた変数と同じで、
                        :letのすぐ後に:lockvarを使うことで変数をロックする
                        ことと同義である。したがって: >
                                :const x = 1
<                       は、以下と同義である: >
                                :let x = 1
                                :lockvar! x
<                       NOTE: Vim9 script では `:const` とは異なった動きをする、
                        vim9-const を参照。
                        これは、変数が変更されないことを確実にしたいときに便利
                        である。
                        この値がリストか辞書のリテラルならその項目もまた変更で
                        きない: >
                                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 = 2  " エラー!
<                                                       E996
                        Note 環境変数、オプション値およびレジスタ値はロックで
                        きないため、ここでは使用できない。

:cons[t]
:cons[t] {var-name}
                        引数が指定されていない場合、または {var-name} のみが指
                        定されている場合、動作は :let と同じである。

:lockv[ar][!] [depth] {name} ...                        :lockvar :lockv
                        内部変数{name}をロックする。ロックすると、それ以降変更
                        ができなくなる(アンロックするまで)。
                        ロックされた変数を削除することはできる: >
                                :lockvar v
                                :let v = 'asdf'   " 失敗!
                                :unlet v          " 動作する
<                       E741 E940 E1118 E1119 E1120 E1121 E1122
                        ロックされた変数を変更しようとするとエラーメッセージ
                        "E741: Value is locked: {name}" が表示される。
                        もしも組み込み変数をロック・アンロックしようとすると、
                        エラーメッセージ "E940: Cannot lock or unlock variable
                        {name}" が表示される。

                        [depth]はリストListや辞書Dictionaryをロックすると
                        きに意味がある。どれだけ深くロックするかを指定する:
                                0       変数 {name} をロックするが値はロックし
                                        ない。
                                1       リストや辞書それ自身をロックする。要素
                                        を追加したり削除はできないが、要素の値
                                        を変えることはできる。
                                2       要素の値もロックする。その要素がリスト
                                        や辞書である場合、その中の要素の追加や
                                        削除はできないが、値の変更はできる。
                                3       2と同様だが、リスト・辞書内のリスト・
                                        辞書に対してもあてはまる。1レベル深い。
                        [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]  " エラー!
<                                                               E743
                        深さを無限にするには[!]を使い、[depth]を省略する。しか
                        しループを捕捉するために深さの最大値は100に設定されて
                        いる。

                        Note 2つの変数が同じリストListを参照している場合、片
                        方の変数をロックすると、もう一方の変数を介してアクセス
                        した場合もロックされている。
                        例: >
                                :let l = [0, 1, 2, 3]
                                :let cl = l
                                :lockvar l
                                :let cl[1] = 99         " 代入できない!
<
                        これを回避するにはリストのコピーを作るとよい。
                        deepcopy()を参照。

                                                        E1391 E1392
                        オブジェクト変数とクラス変数のロックとロック解除は現在
                        サポートされていない。


:unlo[ckvar][!] [depth] {name} ...              :unlockvar :unlo E1246
                        内部変数{name}をアンロックする。:lockvarの逆を行う。

                        {name} が存在しない場合:
                        - Vim9 script ではエラーになる。
                        - 旧来のスクリプトでは黙って無視される。

:if {expr1}                     :if :end :endif :en E171 E579 E580
:en[dif]                {expr1}が非ゼロと評価された場合に、対応する `:else` か
                        `:endif` までの命令を実行する。
                        短い記述でも動作するが、混乱を避け自動インデントを正し
                        く動作させるために常に `:endif` を使うことを推奨する。

                        バージョン4.5から5.0まで間のVimは、`: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
<
                        Vim9 script では、スクリプトの可読性向上のため
                        `:endif` は短縮できない。
                        NOTE: `:append` と `:insert` コマンドは `:if` と
                        `:endif` の間では正しく動かない。

                                                :else :el E581 E583
:el[se]                 対応する `:if` ブロックが実行されなかった場合には、こ
                        れに対応する `:else` か `:endif` までのコマンドが実行
                        される。
                        Vim9 script では、スクリプトの可読性向上のため
                        `:else` は短縮できない。

                                        :elseif :elsei E582 E584
:elsei[f] {expr1}       `:else` `:if` の省略形。`:endif` を付け加える (入れ子
                        にする) 手間を省くことができる。
                        Vim9 script では、スクリプトの可読性向上のため
                        `:elseif` は短縮できない。

: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
<
                        Vim9 script では、スクリプトの可読性向上のため
                        `:endwhile` は短縮できない。
                        NOTE: `:append` と `:insert` コマンドは `:while` と
                        `:for` ループの内側では正しく動かない。

:for {var} in {object}                                  :for E690 E732
:endfo[r]                                               :endfo :endfor
                        {object}の各要素に対し、`:for` と `:endfor` の間のコマ
                        ンドを繰り返す。{object}はリスト ListBlob、また
                        は文字列 String である。 E1177

                        変数{var}に各要素の値がセットされる。
                        Vim9 script ではループ変数がグローバル/ウィンドウ/タ
                        ブ/バッファ変数でない限り、未宣言である必要がある。

                        ループの内側のコマンドでエラーが検出されたときは
                        `endfor` の後から実行が継続される。
                        ループの内側で{object}を変更するとどの要素が使われるか
                        に影響を与える。それを望まない場合はコピーを作ること: >
                                :for item in copy(mylist)
<                       {object}が List でコピーを作らない場合、旧来のスクリ
                        プトではVimは現在の要素に対してコマンドを実行する前に、
                        List の次の要素への参照を保存する。そのため副作用な
                        しに現在の要素を削除することができる。それ以降の要素を
                        変更すると、それが見つからなくなる。つまり以下の例は動
                        作する(List を空にする非効率な方法): >
                                for item in mylist
                                   call remove(mylist, 0)
                                endfor
<                       Note List を並べ替える(例えばsort()やreverse()で)と
                        予期しない結果になることがある。
                        Vim9 script では index が使用される。現在の要素よりも
                        前の要素が削除された場合、次の要素はスキップされる。

                        {object} が Blob の場合、Vimは常にコピーを作成して繰
                        り返す。List とは異なり、Blob を変更しても繰り返し
                        には影響しない。

                        {object} が String の場合は各要素は1つの文字、それと
                        任意の結合文字による文字列になる。

                        Vim9 script では、スクリプトの可読性向上のため
                        `:endfor` は短縮できない。

:for [{var1}{var2}, ...] in {listlist}
:endfo[r]                                                       E1140
                        上の `: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` の間で使われた場
                        合、`:finally` から `:endtry` までの間のコマンドがまず
                        実行される。ループの内側で `:try` がネストしている場
                        合、全ての `:try` に対してこのプロセスが適用される。最
                        も外側の `:endtry` の後ループの開始位置まで戻る。

                        Vim9 script では、スクリプトの可読性向上のため
                        短縮形は `:cont` になる。
                                                :break :brea E587
:brea[k]                `:while` または `:for` ループの内側で使われたときは、
                        対応する `:endwhile` または `:endfor` の後のコマンドま
                        でスキップする。
                        ループの内側の `:try` と `:finally` の間で使われた場
                        合、`:finally` から `:endtry` までの間のコマンドがまず
                        実行される。ループの内側で `:try` がネストしている場
                        合、全ての `:try` に対してこのプロセスが適用される。最
                        も外側の `:endtry` の後ループの後までジャンプする。

                        Vim9 script では、スクリプトの可読性向上のため
                        `:break` は短縮できない。
:try                                            :try :endt :endtry
                                                E600 E601 E602 E1032
: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
<
                        Vim9 script では,、スクリプトの可読性向上のため
                        `:endtry` は短縮できない。

                                        :cat :catch
                                        E603 E604 E605 E654 E1033
:cat[ch] /{pattern}/    {pattern}にマッチする例外が発生し、より前の `:catch`
                        で捕捉されなかった場合、この `:catch` と同じ `:try` に
                        属する次の `:catch`, `:finally`, `:endtry` までの後続
                        のコマンドが実行される。そのような例外が発生しなかった
                        場合、それらのコマンドはスキップされる。
                        {pattern}が省略された場合は全てのエラーが捕捉される。
                        例: >
                :catch /^Vim:Interrupt$/         " 割り込み (CTRL-C) を捕捉
                :catch /^Vim\%((\a\+)\)\=:E/     " 全Vimエラーを捕捉
                :catch /^Vim\%((\a\+)\)\=:/      " 例外と割り込みを捕捉
                :catch /^Vim(write):/            " :writeにおける全エラーを捕捉
                :catch /^Vim\%((\a\+)\)\=:E123:/ " エラーE123を捕捉
                :catch /my-exception/            " ユーザー定義例外を捕捉
                :catch /.*/                      " 全てを捕捉
                :catch                           " /.*/と同じ
<
                        {pattern}を囲むのに/以外の文字を使うことができる。ただ
                        しその文字は特別な意味(例: '|' や '"' など)を持ってい
                        てはならず、{pattern}の内側に現れてはならない。 E1067
                        例外の情報は v:exception で得られる。
                        throw-variables も参照。
                        NOTE: エラーメッセージの本文によって ":catch" すること
                        は確実ではない。メッセージはロケールによって異なるから
                        である。
                        Vim9 script では、スクリプトの可読性向上のため
                        `:catch` は短縮できない。

                                        :fina :finally E606 E607
:fina[lly]              `:try` と `:finally` の間を抜ける前に必ず、このコマンド
                        から対応する `:endtry` の間のコマンドが実行される: つ
                        まり、正常に `:finally` まで進んだ場合、`:continue`,
                        `:break`, `:finish`, `:return` を使った場合、エラー・
                        割り込み・例外が発生した場合(:throwを参照)のいずれの
                        場合であっても。
                        Vim9 script では、スクリプトの可読性向上と `:final`
                        と混同するのを避けるため、 `:finally` は短縮できない。

                                                :th :throw E608 E1129
:th[row] {expr1}        {expr1}を評価し、例外として投げる。`:try` と `:catch`
                        の間で ":throw" が使われた場合、{expr1}にマッチする最初
                        の `:catch` までのコマンドはスキップされる。そのような
                        `:catch` がない場合、または `:catch` と `:finally` の間
                        で ":throw" が使われた場合、`:finally` から `:endtry` ま
                        でのコマンドが実行される。`:throw` が `:finally` の後
                        で実行された場合、`:endtry` までのコマンドはスキップさ
                        れる。":endtry" において、動的に囲んでいる次の `:try`
                        (これは関数呼び出しやスクリプトsourceも含めて探される)
                        から対応する `:catch` までに対しこのプロセスが再び適用
                        される。例外が捕捉されない場合、コマンドの処理は終了す
                        る。
                        例: >
                :try | throw "oops" | catch /^oo/ | echo "caught" | endtry
<                       Note: エラーによって行のパースがスキップされ、"|" によ
                        るコマンド区切りが解釈されないような場合は "catch" は
                        行を分けて書く必要がある。

                        Vim9 script では、スクリプトの可読性向上のため
                        `:throw` は短縮できない。

                                                        :ec :echo
:ec[ho] {expr1} ..      各{expr1}をスペースで区切って表示する。最初の{expr1}
                        表示は、常に新しい行から始まる。
                        :commentも参照。
                        改行が必要な場合 "\n" を使用する。カーソルを第1桁に
                        持って行くには "\r" を使用する。
                        色強調を行うにはコマンド `:echohl` を使用する。
                        コメント文を同じ行に続けることはできない。
                        例: >
                :echo "the value of 'shell' is" &shell
<                                                       :echo-redraw
                        このコマンドの後、再描画を行うと表示したメッセージが消
                        えてしまう。Vim は一連のコマンドが完了するまで再描画を
                        後回しにするため、この現象は頻繁に発生する。例えば、
                        `:echo` より前に実行したコマンドが後で再描画を引き起こ
                        し、メッセージが消えてしまうということがある(再描画は
                        しばしばユーザーが何か入力するまで後回しにされる)。こ
                        の問題を避けるには、`:redraw` を使って強制的に再描画す
                        ること。例: >
                :new | redraw | echo "there is a new window"
<

                                                        :echon
:echon {expr1} ..       改行を付けずに、{expr1}を表示する。:commentも参照。
                        色強調を行うにはコマンド `:echohl` を使用する。
                        コメント文を同じ行に続けることはできない。
                        例: >
                                :echon "the value of 'shell' is " &shell
<
                        Vimコマンドの `:echo` と、外部のシェルコマンドである
                        `:!echo` との違いに注意: >
                :!echo %                --> filename
<                       ":!" の引数は展開される。:_%を参照。 >
                :!echo "%"              --> filename or "filename"
<                       前の例のように働く。ダブルクォートが表示されるかどうか
                        は、使用している 'shell' に依存する。 >
                :echo %                 --> 何も表示されない
<                       '%' は式として不当な文字である。 >
                :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` に近い方法
                        で解析がされる。なんらかを表示する前に、まず最初に全て
                        の式が数値または文字列に評価されない場合は、string()
                        を使用して文字列に変換する。
                        強調を行うには `:echohl` コマンドを使う。
                        例: >
                :echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see."
<                       画面を再描画したときメッセージが消去されてしまうのを避
                        ける方法については:echo-redrawを参照。

                                        :echow :echowin :echowindow
:[N]echow[indow] {expr1} ..
                        :echomsg と同様だがメッセージポップアップウィンドウ
                        が使用可能であればそこにメッセージが表示される。これは
                        3秒間表示され hit-enter プロンプトを回避することを意
                        味する。表示中に非表示にしたい場合、ノーマルモードで
                        Esc を押す (それ以外の場合はビープになる)。消えてしまっ
                        た後でも `:messages` を使用することでテキストが確認で
                        きる。
                        [N] を与えることでウィンドウをその秒数表示させられる。
                        カウントを伴う最後の `:echowindow` 由来で、一度だけ使
                        用される。
                        メッセージウィンドウは Vim が +timer と +popupwin 機能
                        付きでコンパイルされた時に利用できる。

                                                        :echoe :echoerr
:echoe[rr] {expr1} ..   式をエラーメッセージとして表示し、そのメッセージを
                        メッセージ履歴message-historyに保存する。スクリプト
                        や関数の中で使用されたときは行番号が付け加えられる。
                        `:echomsg` コマンドと同様に引数の間にスペースが挿入さ
                        れる。try条件文の中で使用されたときは、このメッセージ
                        がエラー例外として投げられる。(try-echoerrを参照)
                        例: >
                :echoerr "This script just failed!"
<
                        単にメッセージを強調させたい場合には `:echohl` を使う
                        こと。ビープを鳴らしたいときには次のようにする: >
                :exe "normal \<Esc>"
<

:echoc[onsole] {expr1} ..                               :echoc :echoconsole
                        テスト用である: `:echomsg` のように動作するが、GUI で
                        実行中で端末から起動した場合、標準出力にテキストを書き
                        出す。

                                                        :eval
:eval {expr}            {expr} を評価し結果を破棄する。例: >
                                :eval Getlist()->Filter()->append('$')
<
                        結果の値は使用されないため、式には副作用があると想定さ
                        れる。この例では、`append()` 呼び出しはテキスト付きリ
                        ストをバッファに追加する。これは `:call` に似ている
                        が、どの式でも動作する。
                        Vim9 script では効果のない式はエラー E1207 になる。
                        これは間違いに気付くのに役立つはずだ。

                        このコマンドは `:ev` や `:eva` に短縮できるが、これら
                        は認識しにくいため、使用するべきでない。

                        このコマンドでは、"|" は式の一部として扱われるため、
                        "|" と他のコマンドを後ろに置けない。

                                                        :exe :execute
:exe[cute] {expr1} ..   {expr1}の評価結果の文字列をExコマンドとして実行する。
                        複数の引数は連結され、間にスペースが挿入される。余計な
                        スペースを入れたくない場合は ".." オペレータを使って文
                        字列を連結すること。
                        {expr1}は処理されたコマンドとして扱われ、コマンドライ
                        ン編集用のキーは認識されない。
                        コメント文を同じ行に続けることはできない。
                        例: >
                :execute "buffer" nextbuf
                :execute "normal" count .. "w"
<
                        ":execute" は '|' を受けつけないコマンドに、次のコマン
                        ドを続けて実行させるのにも使用できる。例: >
                :execute '!ls' | echo "theend"
<                       {訳注: 普通の使い方では ":!ls" の後には '|' を使って、
                        Exコマンドを続けることはできない}
                        また ":execute" は、Vim script 内でコマンド ":normal"
                        の引数に制御文字を書くことを避けるために役に立つ。 >
                :execute "normal ixxx\<Esc>"
<                       これで<Esc>文字を表す。expr-stringを参照。

                        ファイル名の中の特殊文字を正しくエスケープするように
                        注意すること。Vim コマンドに与えるファイル名をエス
                        ケープするには fnameescape() を使う。:! コマンドに
                        与えるときは shellescape() を使う。
                        例: >
                :execute "e " .. fnameescape(filename)
                :execute "!ls " .. shellescape(filename, 1)
<
                        Note: execute に渡す文字列はいかなるコマンドでも構わな
                        いが、"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 script 言語は例外処理機構を備えている。この節では例外処理をどのように行
うかについて説明する。

例外はエラー発生時や割り込み発生時にVimによって投げられる。それについては
catch-errorscatch-interruptを参照。ユーザーはコマンド:throwによって明示
的に例外を投げることができる。throw-catchを参照。


try 条件文                                     try-conditionals

例外を捕捉したり、例外を引き金として後始末のコードを実行することができる。try
条件文を使う事によってcatch節(これが例外を捕捉する)やfinally節(後始末のために
実行される)を指定する事ができる。
try条件文はコマンド:tryによって始まり、対応するコマンド:endtryによって終了
する。その間でコマンド:catchによりcatch節を定めたり、コマンド:finally
よってfinally節を定めることができる。catch節は1個もなかったり、複数個あっても
よい。しかしfinally節は1個までしか持てない。finally節の後にcatch節があってはな
らない。catch節とfinally節の前の部分はtryブロックと呼ばれる。

     :try
     :  ...
     :  ...                             try ブロック
     :  ...
     :catch /{pattern}/
     :  ...
     :  ...                             catch 節
     :  ...
     :catch /{pattern}/
     :  ...
     :  ...                             catch 節
     :  ...
     :finally
     :  ...
     :  ...                             finally 節
     :  ...
     :endtry

try条件文により、コードから発生する例外を監視したり、適切な対応を取ることがで
きる。tryブロック内で発生した例外は捕捉される。tryブロックとcatch節内で発生し
た例外は捕捉され、後始末が行われる。
tryブロックの実行中に例外が発生しなかった場合は、制御は (もしあれば) finally節
に移動する。その実行後に、スクリプトは ":endtry" の後の行から実行を継続する。
tryブロックの実行中に例外が発生した場合は、tryブロックの残りの行はスキップされ
る。例外はコマンド ":catch" の引数として指定された正規表現に照合される。最初に
マッチした ":catch" の後のcatch節が実行される。他のcatch節は実行されない。
catch節は次に ":catch", ":finally", ":endtry" が現れたところで終了する (どれで
もよい)。
":endtry" に達すると、スクリプトは次の行から通常通り実行が続けられる。
発生した例外が、コマンド ":catch" で指定されたどの正規表現にもマッチしないとき、
その例外はそのtry条件文で捕捉されず、どのcatch節も実行されない。finally節があ
るならば実行される。finally節の実行中は例外は後回しにされ、":endtry" のときに
実行される。そして ":endtry" の後のコマンドは実行されず、例外は他のどこかで捕
捉される。try-nestingを参照。
catch節の実行中に新たな例外が発生した場合は、そのcatch節の残りの行は実行されな
い。新しい例外は同じtry条件文のどの ":catch" コマンドの正規表現にも照合されず、
どのcatch節も実行されない。しかしfinally節があるならばそこが実行され、その間そ
の例外は保留される。":endtry" の後のコマンドは実行されない。新しい例外は他のど
こかで捕捉される。try-nestingを参照。
finally節の実行中に例外が発生した場合は、そのfinally節の残りの行は実行されない。
tryブロックやそのcatch節のどこかで例外が発生してからそのfinally節が実行されて
いた場合は、元の(保留されていた)例外は破棄される。":endtry" の後のコマンドは実
行されない。finally節で発生した例外は伝播し、他のどこかで捕捉される。
try-nestingを参照。

完全なtry条件文を囲む ":while" ループ内で、tryブロックやcatch節において
":break" や ":continue" が実行されたときもfinally節が実行される。
また、関数の中やsourceされたスクリプト中で、tryブロックやtry条件文のcatch節に
おいて ":return" や ":finish" が実行されたときもfinally節が実行される。finally
節の実行中は ":break", ":continue", ":return", ":finish" は保留され、":endtry"
に達したとき再開される。しかしこれらは、そのfinally節内で例外が発生したときは
破棄される。
完全なtry条件節を囲む ":while" ループ内での ":break" や ":continue"、または
finally節内で ":return" や ":finish" に出会ったときは、finally節の残りはスキッ
プされ、通常通り ":break", "continue", ":return", "finish" が実行される。もし
そのfinally節の前に、tryブロックやcatch節内で例外が発生したり、":break",
":continue", ":return", ":finally" が行われていた場合は、それらの保留されてい
た例外やコマンドは破棄される。

例として throw-catch と try-finally を参照。


try 条件文のネスト                                     try-nesting

try条件文は任意にネストさせられる。つまり、try条件文のtryブロック・catch節・
finally節のなかに別の完全なtry条件文を書くことができる。内側のtry条件文がtryブ
ロックで発生した例外を捕捉しなかったときや、catch節・finally節で新たな例外が発
生したときは、外側のtry条件文がそのルールにしたがって例外を捕捉する。内側の
try条件文が外側の条件文のtryブロックの中にある場合はcatch節が判定されるが、そ
うでない場合はfinally節のみが実行される。これはネストの仕方には関係ない。つま
り、内側のtry条件文が直接外側のtry条件文に含まれていてもよいし、外側がスクリプ
トをsourceしたり、内側のtry条件文を含む関数を呼び出していてもよい。

有効なtry条件文のどれも例外を捕捉しなかったときは、それらのfinally節が実行され
る。その後、スクリプトの実行は停止する。":throw" コマンドにより明示的に投げら
れた例外が捕捉されなかった場合は、エラーメッセージが表示される。Vimによって暗
黙的に投げられたエラーや割り込み例外については、通常通りエラーメッセージや割り
込みメッセージが表示される。

例として throw-catch を参照。


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

例外処理のコードはトリッキーになりがちである。何が起こっているか知りたいときは
スクリプトファイルをsourceするときに '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" を先に書くべきで
ある。次の順序で書くと無意味になってしまう: >

        :  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に保持されて
いる。Note "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 script言語には本物のrethrowはないが、代わりに "v:exception" を使うことがで
きる: >

        :function! Bar()
        :  try
        :    call Foo()
        :  catch /.*/
        :    echo "Rethrow" v:exception
        :    throw v:exception
        :  endtry
        :endfunction
<                                                       try-echoerr
Note この方法はVimのエラーや割り込み例外を "rethrow" するためには使えない。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を押してスクリプトを中断すると、設定が一貫しない状
態になってしまう。スクリプトの開発段階においても、エラーが発生したり、明示的に
例外を投げたが捕捉されなかった場合に、同じことが起こりうる。この問題は、try条
件文を使ってfinally節で設定を復元することで解決できる。finally節は、通常の制御
フロー・エラー時・明示的な ":throw" 時・割り込み時に実行されることが保証されて
いる。(Note 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
":continue", ":break", ":return", ":finish" などによってtryブロックやcatch節を
抜けるときも後始末処理が働く。
   例: >

        :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
NOTE: エラーメッセージの本文によって捕捉しようとしてはならない >
        :catch /No such variable/
こうすると英語の環境では動作するが、コマンド :languageにより他の言語を使って
いるユーザーの環境では動作しなくなる。しかし、コメントとしてメッセージテキスト
を引用することは役に立つ: >
        :catch /^Vim(\a\+):E108:/   " No such variable

エラーを無視する                                       ignore-errors

特定のコマンドで発生したエラーを捕捉すれば、エラーを無視することができる: >

        :try
        :  write
        :catch
        :endtry

しかしこの単純な形は使わないよう強く推奨されている。なぜなら、これはあなたが望
むより多くの例外を捕捉してしまうからである。":write" コマンドを使うと自動コマ
ンドが実行され、書き込みとは関係ないエラーが発生する可能性がある。例えば: >

        :au BufWritePre * unlet novar

このようなエラーの中には、スクリプトの作者が責任を負わないものもある: つまり、
スクリプトのユーザーがそのような自動コマンドを定義している場合である。その場
合、上の例のようにすると、ユーザーからエラーを隠してしまうことになる。エラーを
無視するには、次のようにした方がよい >

        :try
        :  write
        :catch /^Vim(write):/
        :endtry

これは書き込みエラーだけを捕捉する。つまり、あなたが意図的に無視したいエラーだ
けである。

自動コマンドを発生させないような1つのコマンドに対しては、":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"
        :    " 例外捕捉。次のプロンプトから継続する。
        :  endtry
        :endwhile

ここでCTRL-Cを押すとタスクに割り込むことができる。その後スクリプトは新しいコマ
ンドを要求する。プロンプトでCTRL-Cを押すとスクリプトが終了する。

スクリプト中の特定の行でCTRL-Cが押されたとき何が起こるかをテストするにはデバッ
グモードを使い、その行の上で>quit>interruptコマンドを使う。
debug-scriptsを参照。


全てを捕捉する                                 catch-all

次のコマンド >

        :catch /.*/
        :catch //
        :catch

は全てをエラー例外・割り込み例外・:throwコマンドにより明示的に投げられた例外
の捕捉する。これは、スクリプトのトップレベルで、予期しないことを捕捉するために
役に立つ。
   例: >

        :try
        :
        :  " ここで難しいことをする
        :
        :catch /MyException/
        :
        :  " 既知の問題を制御する
        :
        :catch /^Vim:Interrupt$/
        :    echo "Script interrupted"
        :catch /.*/
        :  echo "Internal error (" .. v:exception .. ")"
        :  echo " - occurred at " .. v:throwpoint
        :endtry
        :" スクリプトの終わり

Note: 全てを捕捉すると、期待していた以上のものを捕捉してしまうかもしれない。そ
れゆえ、":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

バッファに変更を行った後でこのスクリプトを数回sourceすると、1回目は次のように
表示される >
        File successfully written!
2回目は >
        Error on writing (file contents not changed)
3回目は >
        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
        :
        :  " 計算や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

エラー時やCTRL-Cを押したときにVim自身によって投げられる例外は平坦な階層になっ
ている: つまりこれらは全て "Vim" クラスに入っている。ユーザーは接頭辞 "Vim" を
つけた例外を投げることはできない。これらはVim用に予約されている。
Vimのエラー例外は失敗したコマンドの名前(わかっているならば)という付加情報がつ
いている。catch-errorsを参照。


変わった特性
                                                        except-compat
例外制御のコンセプトは、例外を引き起こしたコマンドは即座に異常終了し、制御が
finally節またはcatch節に移るという前提に基づいている。

Vim script言語では、エラーの後もスクリプトや関数が処理を続行する場合がある。
"abort" フラグのない関数や、":silent!" をつけて実行されたコマンドでは、制御は
次の行、そして関数の外へ移り、制御フローは最外側の ":endwhile" や ":endif" の
次の行へ移る。一方、エラーは例外と同様に捕捉できるべきである (つまり、即座に異
常終了することが要求される)。

この問題は、try条件文が有効なときだけエラーを例外に変換し、(":silent!" で抑制
されていない限り)即座に異常終了することで解決される。(エラー)例外は有効なtry条
件文でのみ捕捉可能であるため、これはなんら制約とはならない。エラーを捕捉せずに
即座に終了してほしいなら、単にcatch節を持たないtry条件文を使えばよい。(finally
節を指定すれば、終了の前に後始末処理を行うことができる)

有効なtry条件文がないとき、即座の異常終了でなく、通常の異常終了と継続が行われ
る。これによってVim6.1以前用に書かれたスクリプトの互換性を保証している。

しかし、有効なtry条件文の中から、例外処理コマンドを使っていない既存のスクリプ
トをsourceする(またはその関数の1つを呼ぶ)と、エラー発生時に既存のスクリプトの
制御フローが変わるかもしれない。エラー発生時に即座に異常終了し、新しい方のスク
リプト内でエラーを捕捉できる。しかしsourceされたスクリプトが ":silent!" コマン
ドでエラーメッセージを抑制していた場合(それが適切なスクリプトならv:errmsg
見ることでエラーを確認している)、実行パスは変わらない。そのエラーは例外に変換
されない(:silentを参照)。これが起こる残りのただ1つの原因は、エラーに関心を
払っていなく、エラーメッセージを表示させるスクリプトである。おそらく新しいスク
リプトからそのようなコードを使いたいとは思わないだろう。

                                                        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
元の例外は破棄され、代わりにエラー例外が投げられる。

{訳注: throw 4711により例外が発生したが、その後の catch /\(/ に構文エラーがあ
       るためエラー例外が発生し、最初の例外は破棄された。}

                                                        except-single-line
コマンド ":try", ":catch", ":finally", ":endtry" は1行の中に書くことができる。
しかし構文エラーがあったとき "catch" の行を認識するのが難しくなるので、避けた
方がよい。
   例: >
        :try | unlet! foo # | catch | endtry
この例は ":unlet!" の後に余計な文字があるためエラー例外を発生させる。そして
":catch" と ":endtry" が認識されないため、この例外は破棄され、"E488: Trailing
characters" のメッセージが表示される。

                                                        except-several-errors
1つのコマンドにより複数のエラーが発生した場合、普通は最初のエラーメッセージが
最も限定的であるため、それがエラー例外に変換される。
   例: >
        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を参照。

==============================================================================
9. 例                                                       eval-examples

16進数で表示する ~
>
  :" 関数 Nr2Bin() は数値の2進文字列表現を返す。
  :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

  :" 関数 String2Bin() は文字列中の各文字を2進文字列に変換して、ハイフン(-)で
  :" 区切って返す。
  :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"



行をソート(並べ替え)する (by Robert Webb) ~

以下は、指定した比較関数を使って行をソートする例である。 >

  :func SortBuffer()
  :  let lines = getline(1, '$')
  :  call sort(lines, function("Strcmp"))
  :  call setline(1, lines)
  :endfunction

ワンライナーにすると次のようになる: >
  :call setline(1, sort(getline(1, '$'), function("Strcmp")))

scanf() の代替 ~
                                                        sscanf
Vimにはsscanf()に相当する関数が無い。行の一部を取り出す必要がある場合には、
matchstr()やsubstitute()を使えば実現できる。以下の例は、"foobar.txt, 123, 45"
というような行から、ファイル名と行番号とカラム番号を取り出す方法を示している。
>
   :" 正規表現を設定
   :let mx='\(\f\+\),\s*\(\d\+\),\s*\(\d\+\)'
   :" 正規表現全体にマッチする部分を取り出す
   :let l = matchstr(line, mx)
   :" マッチ結果から各要素を取り出す
   :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を取り出す ~
                                                scriptnames-dictionary
`:scriptnames` コマンドを使用すると、読み込まれたすべてのスクリプトファイルの
リストを取得できる。 `getscriptinfo()` 関数もあるが、返される情報はまったく同
じではない。リストを操作する必要がある場合は、このコードをベースとして使用でき
る: >

    # SNR によってインデックス付けされたスクリプト辞書を作成または更新し、それ
    # を返す。
    def Scripts(scripts: dict<string> = {}): dict<string>
      for info in getscriptinfo()
        if scripts->has_key(info.sid)
          continue
        endif
        scripts[info.sid] = info.name
      endfor
      return scripts
    enddef

==============================================================================
10. Vim scriptバージョン        vimscript-version vimscript-versions
                                                        scriptversion
時間が経つにつれて多くの機能がVim scriptに追加された。これにはExコマンド、関
数、変数タイプなどが含まれる。それぞれの個々の機能は has() と exists()関数
でチェックできる。

時々、機能の古い構文がVimをより良くすることを妨げることがある。サポートが奪わ
れると、これは古いVim scriptを壊すだろう。これを明確にするために
:scriptversion コマンドを使うことができる。Vim scriptが古いバージョンのVimと
互換性がない場合、不可解な方法で失敗するのではなく、明示的なエラーを与える。

`:function` で定義された旧来の関数を Vim9 script で使用する場合、
scriptversion 4 が使用される。

                                                        scriptversion-1  >
 :scriptversion 1
<       これはオリジナルのVim scriptであり、:scriptversion コマンドを使用し
        ていないのと同じである。行の範囲について古い構文に戻るために使用するこ
        とができる。以下でサポートを検査する: >
                has('vimscript-1')

<                                                       scriptversion-2  >
 :scriptversion 2
<       "." による文字列連結はサポートされていない、代わりに ".." を使用するこ
        と。これにより、Dictメンバーアクセスと浮動小数点数に "." を使用するこ
        とによる曖昧さが回避される。".5" は数値 0.5 を意味する。

                                                        scriptversion-3  >
 :scriptversion 3
<       すべてのVimの定義済変数 vim-variable には "v:" という接頭辞を付けな
        ければならない。例えば "version" は v:version とは違うので、普通の変
        数として使うことができる。
        "count" やその他のいくつかの分かり切った名前でも同様である。

        以下でサポートを検査する: >
                has('vimscript-3')
<
                                                        scriptversion-4  >
 :scriptversion 4
<       先頭が 0 の数字は8進数として認識されない。"0o" もしくは "0O" は引き続
        き8進数として認識される。以前のバージョンでは以下が得られる: >
                echo 017   " 15 を表示 (8進数)
                echo 0o17  " 15 を表示 (8進数)
                echo 018   " 18 を表示 (10進数)
<       script version 4 では: >
                echo 017   " 17 を表示 (10進数)
                echo 0o17  " 15 を表示 (8進数)
                echo 018   " 18 を表示 (10進数)
<       数字の中に一重引用符を使用して読みやすくすることもできる: >
                echo 1'000'000
<       引用符は数字で囲まれている必要がある。

        以下でサポートを検査する: >
                has('vimscript-4')

==============================================================================
11. +eval機能が無効                             no-eval-feature

コンパイル時に+eval機能が無効とされている場合、全ての式評価(eval)コマンドは
提供されない。その場合、Vim script が全ての種類のエラーを引き起こすことを避
ける為、":if" と ":endif" は解釈される。":if" とそれに対応する ":endif" に挟ま
れた内容は無視される。":if" の後に続く引数も無視される。この ":if" コマンドは
ネスティングが可能である。しかし必ず行の先頭に書かれている必要がある。":else"
コマンドは認識されない。

+eval 機能が存在しなかった場合、どのようにコマンドが実行を免れるかの例: >

        :if 1
        :  echo "Expression evaluation is compiled in"
        :else
        :  echo "You will _never_ see this message"
        :endif

+eval 機能が無効になっている場合にのみコマンドを実行するには、2つの方法があ
る。最も簡単なのは、スクリプト(またはVim)を途中で終了することである: >
        if 1
           echo "commands executed with +eval"
           finish
        endif
        args  " command executed without +eval

スクリプトのロードを中止したくない場合は、次の例に示すようなトリックを使用する
ことができる: >

        silent! while 0
          set history=111
        silent! endwhile

+eval 機能が有効なとき、"while 0" のためにコマンドはスキップされる。+eval
機能がない場合、"while 0" はエラーとなり黙って無視されるため、コマンドが実行さ
れる。

==============================================================================
12. サンドボックス                              eval-sandbox sandbox

オプション 'foldexpr''formatexpr''includeexpr''indentexpr',
'statusline''foldtext' はサンドボックスの中で評価される。これによって、悪質
な副作用を持つ式からの保護がなされている。これによって、これらのオプションが
モードラインから設定された場合にある種の安全性がもたらされている。tagsファイル
からのコマンドが実行されたときとコマンドラインでのCTRL-R =に対してもサンドボッ
クスが使われる。
コマンド:sandboxに対してもサンドボックスが使われる。
                                                                E48
サンドボックス内では以下の事が禁止される:
        - バッファの変更
        - マッピング、自動コマンド、ユーザー定義コマンドの定義・変更
        - ある種のオプションの設定 (option-summaryを参照)
        - ある種のVim定義済変数(v:)の設定 (v:varを参照)  E794
        - シェルコマンドの実行
        - ファイルの読み書き
        - 他のバッファへの移動・ファイルを開く
        - Python, Perl等のコマンドの実行
これは100%安全と保証するものではない。しかし、ある種の攻撃を防ぐ事はできるはず
である。

                                                        :san :sandbox
:san[dbox] {cmd}        サンドボックス内で{cmd}を実行する。モードラインから設
                        定された可能性のあるオプションを評価するために使える。
                        例: 'foldexpr'.

                                                        sandbox-option
いくつかのオプションは式を含んでいる。その式を評価するときはセキュリティ上の危
険性を回避するためにサンドボックス内で行わねばならない。しかしサンドボックスに
は制限があるので、これはそのオプションが安全でない場所で設定されたときのみ行わ
れる。ここで「安全でない」とは次の場合をいう:
- カレントディレクトリの .vimrc や .exrc を source するとき
- サンドボックス内で実行している最中
- モードラインから設定された値
- サンドボックス内で定義された関数の実行

Note サンドボックス内でオプションの値を退避し、それから復元した場合、そのオプ
ションはやはりサンドボックス内で設定されたものとマークされる。

==============================================================================
13. テキストロック                                              textlock

いくつか状況においては、バッファを変更する・他のウィンドウへジャンプするなど、
Vimの現在の処理を混乱させたり破壊してしまうような動作は禁止される。これはVimが
実際に他の何かをしているときに起こることに対して当てはまる。例えば、
'balloonexpr' の評価は、マウスカーソルがある位置に留まっているどんなときにでも
起こりうる。

テキストロックが有効になっているときは、以下の事が禁止される:
        - バッファのテキスト変更
        - 他のバッファやウィンドウへの移動
        - 他のファイルを開く
        - ウィンドウを閉じたりVimを終了したり
        - その他

==============================================================================
14. Vim script ライブラリ                               vim-script-library

Vim には、ランタイムやスクリプト作成者が使用できる Vim script ライブラリがバン
ドルされている。現時点ではごく少数の関数しか含まれていないが、時間の経過ととも
に拡張される可能性がある。

関数は Vim9-script として使用可能である。旧来の Vim script (Vim 9.0 以外の
バージョンおよび Neovim で使用される) でも使用できる。

                                                        dist#vim dist#vim9
関数は、オートロードされたプリフィックス "dist#vim" (旧来の Vim script および
Neovim の場合) と、Vim9 script の場合 "dist#vim9" を使用する。

以下の関数が使用可能:

dist#vim#IsSafeExecutable(filetype, executable) ~
dist#vim9#IsSafeExecutable(filetype:string, executable:string): bool ~

この関数は、ファイルタイプと実行可能ファイルを受け取り、与えられた実行ファイル
を実行しても安全かどうかをチェックする。セキュリティ上の理由から、ユーザーは
Vim にランダムな実行可能ファイルを実行させたくない場合や、"<filetype>_exec" 変
数 (plugin_exec) を設定して特定のファイルタイプに対する実行を禁止している場
合がある。

true または false を返し、プラグインが指定された実行可能ファイルを実行する
必要があるかどうかを示す。次の引数を取る:

        引数            型 ~

        filetype        string
        executable      string

 vim:tw=78:ts=8:noet:ft=help:norl: