とほほのwww入門にあるプログラミング言語入門風の情報が欲しかったので、vimのヘルプからコピペ。
旧来の記載が残っているかも。
参考文献というかコピペ元
ライセンス
コピペ元のライセンスに従います。
vim script 実行方法
カレントバッファのスクリプトを実行
-
vim で対象スクリプトのファイルを開く
$ vim test.vim
-
カレントバッファのスクリプトを以下のコマンドで実行
:source %
コマンドラインから実行
$ vim -s test.vim
オートロードスクリプトを実行
-
autoload ディレクトリにスクリプトを置く
$ cp test.vim ~/.vim/autoload/
-
vim から以下のコマンドで実行
:call filename#function()
これらの関数は常にグローバルで、Vim9 script なら "g:" が必要:
:call g:filename#function()
コメント
# コメント
ヒアドキュメント
内部変数 {var-name} を文字列 {endmarker} で囲まれたテキスト行を含むリスト List に設定する。
var {var-name} =<< [trim] [eval] {endmarker}
text...
text...
{endmarker}
-
{endmarker} は空白を含んではならない
-
{endmarker} は小文字で始めることはできない
-
{endmarker} の行は他の文字を含めることができない
-
trim
がない場合、テキスト行内のすべての空白文字は保持される。 -
trim
が指定されている場合、最初の行のインデントがすべての行から取り除かれるlet text =<< trim END if ok echo 'done' endif END 結果: ["if ok", " echo 'done'", "endif"]
-
eval
が指定されない場合、リテラル文字列として扱われるが、
シングルクォートは除外され2重にする必要はない。 -
eval
が指定されている場合、{expr}
形式の任意の Vim の式が評価され、
結果が文字列補間のように式を置き換える。
サンプル
var lines =<< trim END
1行目
2行目
3行目
END
echo join(lines, "\n")
データタイプ
bool
number
float
string
blob
list<{type}>
dict<{type}>
job
channel
func
func: {type}
func({type}, ...)
func({type}, ...): {type}
void
tuple<a: {type}, b: {type}, ...> # まだサポートされてない
値
true, false # 真偽値
-123, 0x10, 0177 0o177 0b1011 # 数値
123.456, 1.15e-6, -1.1e3 # 浮動小数点
"hello, world", 'hello!' # 文字列
[1, 2, ['a', 'b']] # リスト
{'blue': "#00f", 'red': "#f00"} # 辞書
function("strlen") # 関数への参照
v:false, v:true, v:null # 特殊値
job_start()を参照 # ジョブ
ch_open() を参照 # チャンネル
0zFF00ED015DAF # Blog (バイナリラージオブジェクト)
変数、定数 (var, const, final)
var lnum = 1
変数とその値、両方を定数とするには、:const
を使用。
const myList = [1, 2]
myList = [3, 4] # エラー!
myList[0] = 9 # エラー!
myList->add(3) # エラー!
変数の変更のみを禁止するには、:final
を使用
final myList = [1, 2]
myList = [3, 4] # エラー!
myList[0] = 9 # OK
myList->add(3) # OK
演算子
式文法一覧、優先順位の低いものから高い順に:
expr2 ? expr1 : expr1 # if-then-else
expr2 ?? expr1 # Falsy演算子
expr3 || expr3 ... # 論理和
expr4 || expr4 ... # 論理積
expr5 == expr5 # 等しい
expr5 != expr5 # とくしくない
expt5 > expt5 # より大きい
expr5 >= expr5 # より大きいか等しい
expr5 < expr5 # より小さい
expr5 <= expr5 # 小さいか等しい
expr5 =~ expr5 # 正規表現にマッチする
expr5 !~ expr5 # 正規表現にマッチしない
expr5 ==? expr5 # 文字列として等しい(大文字/小文字区別無し)
expr5 ==# expr5 # 文字列として等しい(大文字/小文字区別有り)
expr5 is expr5 # 同一のリスト List、辞書 Dictionary またはBlob のインスタンス
expr5 isnot expr5 # 異なるリスト List、辞書 Dictionary またはBlob のインスタンス
expr6 << expr6 # ビット単位の左シフト
expr6 >> expr6 # ビット単位の右シフト
expr7 + expr7 ... # 足し算、リストまたはBlobの連結
expr7 - expr7 ... # 引き算
expr7 . expr7 ... # 文字列の連結
expr7 .. expr7 ... # 文字列の連結
expr8 * expr8 ... # 掛け算
expr8 / expr8 ... # 割り算
expr8 % expr8 ... # 剰余(割った余り)
<type>expr9 # 型のチェックと変換 (Vim9 のみ)
! expr9 # 論理否定
- expr9 # 単項のマイナス
+ expr9 # 単項のプラス
expr10[expr1] # 文字列のバイト、またはリストの要素
expr10[expr1 : expr1] # 文字列の部分文字列、またはリストの部分リスト
expr10.name # 辞書 Dictionary の要素
expr10(expr1, ...) # Funcref 変数による関数呼び出し
expr10->name(expr1, ...) # method 呼び出し
number # 数定数
"string" # 文字列定数。バックスラッシュは特別な意味を持つ
$"Hello, {name}!" # 文字列補間
'string' # リテラル文字列定数。'を含めるには2重にする
[expr1, ...] # リスト List
{expr1: expr1, ...} # 辞書 Dictionary
&option # オプション変数
(expr1) # 式の入れ子
variable # 内部変数
$VAR # 環境変数
@r # レジスタ 'r' の値
function(expr1, ...) # 関数呼出し
(args) => expr1 # Vim9 のラムダ式
代入
{var-name} = {expr1} # 内部変数{var-name}に式{expr1}の結果をセット
{var-name}[{idx}] = {expr1} # リストの要素に式{expr1}の結果をセット
{var-name}[{idx1}:{idx2}] = {expr1}
# リストListの一部を式{expr}の値で置き換え
{var} += {expr1} # {var} = {var} + {expr1}
{var} -= {expr1} # {var} = {var} - {expr1}
{var} *= {expr1} # {var} = {var} * {expr1}
{var} /= {expr1} # {var} = {var} / {expr1}
{var} %= {expr1} # {var} = {var} % {expr1}
{var} .= {expr1} # {var} = {var} . {expr1}
{var} ..= {expr1} # {var} = {var} .. {expr1}
${env-name} = {expr1} # 環境変数{env-name}に式{expr1}の結果をセット
@{reg-name} = {expr1} # 式{expr1}の結果をレジスタ{reg-name}に書きこむ
&{option-name} = {expr1} # オプション{option-name}に式{expr}の値をセット
リスト
var mylist = [1, two, 3, "four"]
var emptylist = []
var item = mylist[2] # 3番目の要素(3)を取得
var nestlist = [[11, 12], [21, 22], [31, 32]]
var longlist = [1, 2, 3] + [4, 5, 6] # リストの連結
var otherlist = longlist[:] # リストのコピー
var endlist = longlist[2:] # 2番目から最後まで
var shortlist = longlist[2:2] # 1個の要素からなるリスト
リストのアンパック
var [var1, var2] = mylist
変数の個数とリストの要素数が一致しないときはエラーになる。リストにある余分な要
素をまとめて受け取るには、";" と受け取る変数名を書いておく:
# 要素が 2 つしかないときでもエラーにはならない。"rest" は空リストになる。
var [var1, var2; rest] = mylist
リスト操作
var r = call(funcname, list) # 引数リストをつけて関数を呼び出す
if empty(list) # リストが空かどうか判定する
var l = len(list) # リストの要素数
var big = max(list) # リスト中の最大値
var small = min(list) # リスト中の最小値
var xs = count(list, 'x') # 'x' の出現回数を数える
var i = index(list, 'x') # 最初に 'x' が現れる位置のインデックス
var lines = getline(1, 10) # バッファから10行を取得
call append('$', lines) # バッファに行を追加する
var list = split("a b c") # 文字列を分割してリストにする
var string = join(list, ', ') # リストの要素を連結して文字列にする
var s = string(list) # リストの文字列表現
call map(list, '">> " .. v:val') # 各要素の前に ">> " をつける
辞書
var mydict = {1: 'one', 2: 'two', 3: 'three'}
var emptydict = {}
var nestdict = {1: {11: 'a', 12: 'b'}, 2: {21: 'c'}}
キーに対してループ
for key in keys(mydict)
echo key .. ': ' .. mydict[key]
endfor
キーでソートした順にループ
for key in sort(keys(mydict))
echo key .. ': ' .. mydict[key]
endfor
値に対してループ
for v in values(mydict)
echo "value: " .. v
endfor
キーと値の両方でループ
for [key, value] in items(mydict)
echo key .. ': ' .. value
endfor
辞書から要素を取り除く
var i = remove(dict, 'aaa')
unlet dict.aaa
unlet dict['aaa']
辞書操作関数
if has_key(dict, 'foo') # 辞書がキー "foo" の要素を持つなら真
if empty(dict) # 辞書が空なら真
var l = len(dict) # 辞書の要素数
var big = max(dict) # 辞書中の最大値
var small = min(dict) # 辞書中の最小値
var xs = count(dict, 'x') # 'x' の出現回数を数える
var s = string(dict) # 辞書の文字列表現
call map(dict, '">> " .. v:val') # 各要素の前に ">> " をつける
Blob
var b = 0zFF00ED015DAF
var b = 0zFF00.ED01.5DAF # 読みやすくするために、ドットをバイト間(16進文字のペア)に挿入
var b = readfile('image.png', 'B')
Blobのインデックス
var myblob = 0z00112233
var byte = myblob[0] # 1番目のバイトを取得: 0x00
var byte = myblob[2] # 3番目のバイトを取得: 0x22
var last = myblob[-1] # 最後のバイトを取得: 0x33
var byte = get(myblob, idx) # 無効なインデックスに対するエラーを回避
Blobの繰り返し
for byte in 0z112233
call Doit(byte)
endfor
Blobの連結
var longblob = myblob + 0z4455
var myblob += 0z6677
関数
def[!] {name}([arguments])[: {return-type}]
- {name} : 100バイト未満
- {reeturn-type} : 省略、あるいは
void
である場合は、何も返さないと想定される - {arguments} : 書式は以下の3つ
{name}: {type}
{name} = {value}
{name}: {type} = {value}
-
def
: 最大 50 階層のネストが可能 -
[!]
:!
を付けると既存の関数を上書きする
enddef
- 関数の終了
関数定義
def Add(x: number, y: number): number
return x + y
enddef
メソッド呼び出し
expr10->name([args])
これは次と同じである:
name(expr10 [, args])
あるメソッドが返す値を次のメソッドに渡して連鎖させることができる
mylist->filter(filterexpr)->map(mapexpr)->sort()->join()
ラムダの使用例:
GetPercentage()->{x -> x * 100}()->printf('%d%%')
ラムダ式 (クロージャ)
def Foo(arg: number): func
var i = 3
return (x) => x + i - arg
enddef
var Bar = Foo(4)
echo Bar(6) # 5
ラムダ式には {} に複数のステートメントを含むことができる:
var Lambda = (arg) => {
g:was_called = 'yes'
return expression
}
- いかなるコマンドも
{
の後ろに続けることはできない - 閉じの
}
は行の先頭
ラムダとクロージャのサポートは以下のように判定できる:
if has('lambda')
if - elseif - else - endif
var a = 5
if a == 5
echo "5"
elseif a == 4
echo "4"
else
echo "others"
endif
while - endwhile
let lnum = 1
while lnum <= line("$")
let lnum = lnum + 1
echo lnum
endwhile
for - endfor
for item in [1, 2, 3, 4, 5]
echo item
endfor
ループ制御(break, continue)
var n = 0
while (true)
n += 1
if n == 2
continue
endif
if n == 8
break
endif
echo n
endwhile
try - catch - finally - endtry
def Foo(value: any)
try
throw value
catch /^\d\+$/
echo "Number thrown"
catch /.*/
echo "String thrown"
finally
echo "finally"
endtry
enddef
call Foo(0x1267) # Number thrown
# finally
call Foo('string') # String thrown
# finally