はじめに
Vimmerの皆さんこんにちは。
Vimに慣れてくると、色々カスタマイズしたくなりますよね。
でも、プラグインを作るのは大げさだし…と思っている人には
.vimrcでVim Scriptを書いてみるのがおすすめです。
Vim Scriptとは
Vim script は Vim に組み込まれたスクリプト言語です。
vimを開き、 :help vim-script
と打ってみましょう。
はじめに
誰もが最初に触れる Vim script は vimrc ファイルです。Vim が起動するときに読
み込まれ、書かれているコマンドが実行されます。それにより好きなように設定を変更
できます。vimrc の中ではすべてのコロンコマンドが使えます (":" で始まるコマンド
のこと。Ex コマンドやコマンドラインコマンドと呼ばれることもある)。
(自分のVimはヘルプが日本語じゃないからやだ!という人はこちらをどうぞ→ Vimヘルプを日本語化!)
「誰もが最初に触れる Vim script は vimrc ファイルです。」ということで
実はVimを触っていれば自然とVim scriptにお世話になっているのです。
シンタックスハイライトに使うカラースキームも、もとを正せばVim script。
Vimが有りさえすれば、そこが実行環境。というわけで気軽に始めてみましょう。
こんな人向け
- Vimを触っていて、プラグインも使っているけど、もっと痒いところに手が届く自動化をしてみたい人
- もともと別のプログラム言語を触っているが、Vim scriptは触ったことがない人
今回やってみること
- Vim上でPHP lintを実行する
- lintでエラーが出た行数をハイライトしてみる
- 上記を保存時に実行できるようにする
環境
OS: Mac OS Sierra(10.12.6)
Vim: 8.0
1. Vim上でPHP lintを実行する
これはぶっちゃけいろんな人がやっていますので、
本能の赴くまま、無邪気に作って保存してみましょう。
function! PHPLint()
let result = system('php -l ' . bufname(""))
echo result
endfunction
→保存・コマンドモードで以下を実行
:source ~/.vimrc
<?php
$hoge = 1;
aaa // 明らかなシンタックスエラー
echo $hoge;
→保存
コマンドモードで
:call PHPLint()
を実行
すると、こんな表示が出ます
楽しい\(^o^)/
簡単な解説
関数はfunction ~ endfunction
で定義します。
コマンド・関数名 | 動き |
---|---|
letコマンド | let (変数名) = (値)で変数定義できます。 |
system()関数 | (組み込み)シェルコマンドを実行し、実行結果の文字列を返します。 |
echoコマンド | 引数の値を表示 |
これらのコマンドや関数については、:help let
など、コマンド・関数名などの前に :help
をつけて実行すると詳細なマニュアルが見られます。
2. lintでエラーが出た行数をハイライトしてみる
では、今度はエラーが出た行数をハイライトしてみましょう。
(Syntaxチェックは必ずしも正しい行数を出してくれるわけではないが、今回はlineを信じて表示する)
function! PHPLint()
let result = system('php -l ' . bufname(""))
let error_list = matchlist(result, '\(line \)\(\d\+\)', 1)
if empty(error_list)
echo "エラーはありませんでした"
return
endif
call matchaddpos("Error",[str2nr(error_list[2])])
echo result
endfunction
→保存・コマンドモードで以下を実行
:source ~/.vimrc
コマンド・関数名 | 動き |
---|---|
matchlist()関数 | (組み込み)正規表現でマッチした文字列のリストを返します。 |
str2nr()関数 | (組み込み)文字列を数値に変換した結果を返します。 |
matchaddpos()関数 | (組み込み)第二引数に指定された行数を強調表示する |
同じく、詳細は:help (関数名)
で確認!
matchstr()で PHPのSyntaxエラー
Parse error: parse error in test.php on line 6
Errors parsing test.php
のline XXX
のXXX
を正規表現で取得し、その行をハイライトしています。
おい、:sourceできないぞ
はい。こんな表示が出たかと思います
Error detected while processing /path/to/.vimrc:
line (行数):
E122: Function PHPLint already exists, add ! to replace it
関数は、function!で宣言しないと
再度:source
コマンドを実行する事ができません。
リローダブルなvimrcを書くには、
function! PHPLint()
...
endfunction
とする必要があります(後述のautocmdも同様)。
matchaddpos の第一引数について
:help matchaddpos
すると、以下のようなシグネチャになっています。
matchaddpos({group}, {pos}[, {priority}[, {id}[, {dict}]]])
matchadd
と同じである、ということで、matchadd
のマニュアルを読んでみると、
{group} = 構文グループ
だとわかりますが、構文グループとはなんぞや
ということで、さらに :help group
と実行してみると、謎が解けます。
構文グループとは、同じ種類の構文アイテムをグループ化したものである。構文グルー
プから強調グループにリンクされ、強調グループに対して色が設定される。構文グルー
プそれ自体は、色や属性を指定するものではない。
なるほど。と、その下を読み進めていると、構文グループが列挙してありました。
今回は下の方にあった、構文グループ ERROR
を選択し、
指定した行数を ERROR
と同じ強調色にしています。
こんな感じで、:help
を使いこなすにはちょっとしたコツが必要ですが
慣れてくるとスルメのようにいい味が出てくるマニュアルです。
気を取り直して
コマンドモードで
:call PHPLint()
を実行
すると、こうなります。
3. 上記を保存時に実行できるようにする
autocmd! BufWritePost *.php :call PHPLint()
→保存・コマンドモードで以下を実行
:source ~/.vimrc
例によって :help autocmd
してみると
:au[tocmd] [group] {event} {pat} [nested] {cmd}
コマンドの定義方法が出てきます。
(Vim script上でコロン(:)コマンドを書くときは、:は不要です。)
引数として必要なのは、{event}
と{pat}
と{cmd}
だということがわかります。
autocmd
はフックのようなものです。
{event}
で指定されたイベントが発生したとき、{pat}
で指定したファイルに対し、
{cmd}
で指定したコマンド/関数を実行します。
{event}
は、あらかじめVimに文字列で指定されています。
というわけで :help event
を見てみましょう。
いっぱい出てきました。
ここにあるイベント発生時に、任意のコマンドを実行できます。
BufWritePost
はバッファを保存した後のタイミングで実行するコマンドです。
test.php
を:w
で保存してみましょう。PHPLint()
が保存時に実行されているのがわかりますね。
おまけ:強調表示を消す方法
コマンド実行すると、強調表示されたままになってしまいます。
clearmatches()
を実行すると強調表示がクリアされるので、以下のようにすると
シンタックスエラーがなくなれば表示も消えます。
function! PHPLint()
let result = system( 'php -l ' . bufname(""))
let error_list = matchlist(result, '\(line \)\(\d\+\)', 1)
if empty(error_list)
call clearmatches() ' ←こいつを追加
echo "エラーはありませんでした"
return
endif
call matchaddpos("Error",[str2nr(error_list[2])])
echo result
endfunction
→保存・コマンドモードで以下を実行
:source ~/.vimrc
test.phpを正しく編集し、保存してみましょう。
強調表示が消えるはずです。
最後に
いかがでしたでしょうか?
今回は「作って覚える」ということで、細かい説明を省き
:help
を調べながら進めていきました。
Vim scriptと仲良くなるには、:help
と仲良くなるのが近道です。
楽しいVimライフを! & Merry Christmas!