Vim scriptを使って簡易なプラグインを作ってみよう
- ターミナルの操作方法
- 以下のバージョンのVimとNeovimを用意
- Vim scriptの基礎
- セッション管理のプラグインを作ってみよう
- Vim scriptはVim上で実行できるスクリプト言語
- Exコマンド(
:
で始まるコマンド)の集合体 - vimrcに記述しているのもVim script
- Vimのプラグインの多くはVim scriptで書かれている
以下の手順通りに実施してみてください。コマンドラインにgorilla
が表示されれば成功です。
sample.vim
を作成
$ mkdir sample
$ cd sample
$ vim sample.vim
- Vimで以下のコードを記述して保存
echo 'gorilla'
:source
でVim scriptを実行
:source sample.vim
Vim scriptでは"
がコメント行として解釈され処理をスキップします。
" この行は処理されない
" echo 'gorilla'
主に以下のデータを使用できます。
データ型 | 例 |
---|---|
数値 | 5 |
小数 | 5.5 |
文字列 | 'gorilla'、"gorilla" |
リスト | [1, 2, 3] |
辞書 | {'name': 'gorilla'} |
"
と'
で囲ったものは文字列になります。
"
はタブを表す\t
といった特殊な文字をタブとして出力しますが、'
は囲った文字列をそのまま出力するといった違いがあります。
sample.vim
の先程まで記述したコードを削除して、以下のコードを記述して実行してみてください。
echo 'hello\tgorilla'
echo "hello\tgorilla"
結果は以下になります。
hello\tgorilla
hello gorilla
let
を使っての宣言と値を代入する- 宣言済みの変数でも値を代入するときは
let
を使用しなければいけない
let name = 'gorilla'
" letがないのでエラーになる
name = 'cat'
- アルファベット、数字、アンダースコアを使用できる
- 数字で始まることはできない
" OK
let _a1 = 1
echo _a1
" NG
let 1a = 1
let a-b = 1
- 変数や後述する関数にはスコープがある
- 接頭子によってスコープが変わる
- 関数内で
l:
を省略した場合は暗黙的にローカル変数にアクセスする
接頭子 | スコープ |
---|---|
g: |
グローバルスコープ、どこからも利用可能 |
s: |
スクリプトスコープ、スクリプトファイル内のみ使用可能 |
l: |
ローカルスコープ、関数内のみ使用可能 |
a: |
関数の引数、関数内のみ使用可能 |
v: |
グローバルスコープ、Vimが予め定義している変数 |
{{key}: {value}}
の形になる{key}
は文字列でなければいけない
let animal = {'name': 'gorilla', 'age': 27}
" 結果 => {'age': '27', 'name': 'gorilla'}
echo animal
{dict}.{key}
{dict}[{key}]
get({dict}, {key}, {default})
let animal = {'name': 'gorilla', 'age': 27}
" 結果 => gorilla
echo animal.name
" 結果 => 27
echo animal['age']
" 結果 => banana
echo get(animal, 'name', 'banana')
{dict}.{key} = {expr}
{dict}[{key}] = {expr}
let animal = {}
let animal.name = 'gorilla'
let animal['age'] = 27
" 結果 => {'age': 27, 'name': 'gorilla'}
echo animal
- remove({dict}, {key})
call remove(animal, 'age')
" 結果 => {'name': 'gorilla'}
echo animal
[]
の中にカンマで区切って複数の要素を保持できるリストを作れる
let list = ['cat', 10, {'name': 'gorilla'}]
" 結果 => ['cat', 10, {'name': 'gorilla'}]
echo list
{list}[{idx}]
get({list}, {idx}, {default})
let list = ['cat', 10, {'name': 'gorilla'}]
" 結果 => cat
echo list[0]
" 結果 => 10
echo get(list, 1, 'NONE')
join({list}, {sep})
で{list}
を{sep}
で結合して1つの文字列を返す
let list = ['hello', 'my', 'name', 'is', 'gorilla']
" 結果 => hello my name is gorilla
echo join(list, ' ')
- if文の基本形は
if {expr} | endif
{expr}
が1の場合はtrue、0の場合はfalse
if {expr}
" do something
elseif {expr}
" do something
else
" do something
endif
- Vim scriptで主な比較演算子は次の通り
ignorecase
の設定次第で動きが変わる演算子がある- 基本的に
#
がつく大文字小文字考慮の比較演算子を使うと良い
ignorecase 次第 |
大小文字考慮 | 大小文字無視 | 意味 |
---|---|---|---|
== |
==# |
==? |
等しい |
!= |
!=# |
!=? |
等しくない |
> |
># |
>? |
より大きい |
>= |
>=# |
>=? |
より大きいか等しい |
< |
<# |
<? |
より小さい |
<= |
<=# |
<=? |
より小さいか等しい |
is |
is# |
is? |
同一のインスタンス |
isnot |
isnot# |
isnot? |
異なるのインスタンス |
- メモリ上にロードされたファイルのこと
- バッファには名前と番号があり、名前はファイル名で、番号は作成された順で割り当てられる
- バッファは
:bwipeout
で明示的に削除するかVimを終了しなければメモリに残る
bufexists({expr})
で{expr}
のバッファがあるかを確認できる{expr}
が数値の場合はバッファ番号、文字列の場合はバッファ名とみなされる
set buftype={type}
でバッファのタイプを設定できる- 一時的に使うバッファは
nofile
というタイプするのが一般的 - 詳細は
:h buftype
を参照
- カレントバッファからテキストを取得するには
getline({lnum}, {end})
を使用する{end}
を指定しない場合は{lnum}
で指定した行だけを取得する
" 結果 => 1行目のテキストが出力される
echo getline(1)
" 結果 => 1~3行目のテキストがリストで取得できる
echo getline(1, 3)
- カレントバッファにテキストを挿入するには
setline({lnum}, {text})
を使用する {text}
はリストの場合は、{lnum}
行目とそれ以降の行に要素が挿入される
" 結果 => 1行目に my name is gorilla が挿入される
call setline(1, 'my name is gorilla')
" 結果 => 1行目がmy、2行目がnameが挿入される
call setline(1, ['my', 'name'])
- ウィンドウはバッファを表示するための領域
- ウィンドウにはIDが割り当てられます。
- 複数のウィンドウで複数のバッファを表示できます。
:q
といったコマンドではウィンドウを閉じるだけなのでバッファは残る
winnr()
で現在のウィンドウIDを取得できる- 引数を受け取ることもできるので詳細は
:h winnr()
を参照
win_gotoid({expr})
で{expr}
のIDのウィンドウに移動
bufwinid({expr})
で{expr}
のバッファが表示されているウィンドウのIDを取得
- 関数は
function
とendfunction
で囲い、処理はその間に記述
function! Echo(msg) abort
echo a:msg
endfunction
exists({expr})
で関数があるかをチェックできる- 関数をチェックするとき
{expr}
は関数名の前に*
をつける
if exists('*readdir')
" do something
else
!
は同名の関数がある場合は上書きするabort
は関数内でエラーが発生した場合、そこで処理を終了する- Vim scriptはデフォルトでエラーがあっても処理が継続されるため基本的に
abort
をつける
- 引数を使用するときは
a:
スコープ接頭子を付ける必要がある
return {expr}
で{expr}
の評価結果を返すことができる
" 結果 => gorillaが返る
function! MyName() abort
return 'gorilla'
endfunction
execute {expr} ..
で{expr}
の評価結果の文字列をExコマンドとして実行できる- 複数の引数がある場合、それらはスペースで結合される
" 結果 => godzilla
execute 'echo' '"godzilla"'
" 結果 => gorilla godzilla
execute 'echo' '"gorilla"' '"godzilla"'
system({expr}, {input})
で{expr}
の評価結果の文字列を外部コマンドとして実行できる{input}
は省略可能で指定した場合はその文字列をそのままコマンドの標準入力として渡される
" 結果 => my name is gorilla
echo system('echo "my name is gorilla"')
" 結果 => my name is gorilla
echo system('cat', 'my name is gorilla')
{ args -> expr }
という形でLambdaを書くことができる
let F = {a, b -> a - b}
" 結果 => [1, 2, 3, 4, 7]
echo sort([3, 7, 2, 1, 4], F)