最初に
今年密かに立てた目標の一つがVim scriptを書いてみること。Vimで自作コマンドを作ってみること。
Vimを使っていながらこれらのことを敷居の高いものと勝手に感じていた自分を見直すため、Vimで基本的な部分を調べながらサンプルを書いてみました。
(今回は主に、関数における引数の受け取り方について調べました)
なお、これは個人的な備忘録(個人的学習ノート)となります。
ここである程度、基本的な事柄に触れたら、vim-jpのドキュメントを一通り読んでみて理解を深めていこうと思います!
コマンドラインコマンドを定義してみる
作業ディレクトリ内でsample.vim
という名前で作成し、下記のように記述してみます。
command! -nargs=0 Test echo "This is Test!"
同じディレクトリ名でもう一つVimを開き、:source sample.vim
と打ってファイルを読み込んでから、:Test
とVim内で打つと、This is Test
と表示されます。
とやっても良いのですが、
sample.vim
を開いているエディター内で:source sample.vim
を打てば、自分を読み込んでそのまま:Test
と打てるようです。楽ちん!
ちなみにcommand!
とやると、コマンドを再定義することになり、既存のコマンドの内容が上書きされることになります。
上の処理を実行したあとで、Testコマンドをcommandに書き換えて、再度:source sample.vim
を打つと、既にコマンドがあります、というエラーが表示されます。
基本となる関数の作成
処理する内容にもよりますが、処理内容はだいたい関数化するようです。
基本的な関数の呼び方は下記の通り。
command! -nargs=0 Hello call Hello()
function! Hello()
echo "Hello!!"
endfunction
ちなみに関数名をs:Hello
とした場合はローカル関数になるようです。
関数の引数について
引数を一つ取りたい場合
引数を取る関数を作成する場合、下記のように引数部分に<f-args>
を使うようです。
また、関数内で引数として取得した変数についてはa:
が付くようなので、こちらも忘れないように気をつけます。
command! -nargs=1 Hi call Hi(<f-args>)
function! Hi(name)
echo "Hi " . a:name
endfunction
以上の関数を記述した後、vim内で自身を読み込み(:source sample.vim
)、コマンドを打ってみると下記のようになります。
:Hi Merry
" => Hi Merry
引数を0、もしくは1つ、取りたい場合
引数を0 or 1つで取りたい場合は-nargs=?
とするようです。
この場合、関数での引数は可変長引数である...
に変更する必要が出てきます。
(名前付き引数では、渡されないとエラーとなります。)
なお、取得した引数については、
a:0
で引数の数、
a:1
で引数の中身を取得できるようです。
command! -nargs=? Hi call Hi(<f-args>)
function! Hi(...)
if a:0 >= 1
echo "Hi " . a:1
echo a:0
echo a:1
else
echo "Hi..."
end
endfunction
実際に実行してみた結果は下記。
:Hi Merry
" => Hi Merry
" => 1
" => Merry
引数を一つだけ取りたい場合
-nargs=1
とするようです。
この場合、引数を付けないと"引数が必要です"とエラーが表示されます。
command! -nargs=1 Hi call Hi(<f-args>)
function! Hi(name)
echo "Hi " . a:name
endfunction
関数の引数を可変長引数にしても、同じように書けるようです。
(もちろん、引数は付けないとエラー)
command! -nargs=1 Hi call Hi(<f-args>)
function! Hi(...)
echo a:0
echo "Hi " . a:1
endfunction
もっとたくさんの引数を取りたい!
-=nargs=*
で取れるようです。
関数の引数は可変長引数とし、
a:0で引数の数、
a:nでn番目の引数、
a:000ですべての引数の配列を取得できるようです。
command! -nargs=* Hey call Hey(<f-args>)
function! Hey(...)
if a:0 >= 1
echo "name count : " . a:0
let res = ["Hey! "]
let nlist = a:000
for n in nlist
call add(res, n)
endfor
echo join(res)
else
echo "Hey..."
end
endfunction
for文を使いたくて上のように書いてしまいましたが、extend関数を使えば、リストにリストを連結することができるようなので、下記のような書き方がベターですかね。
command! -nargs=* Hey call Hey(<f-args>)
function! Hey(...)
if a:0 >= 1
echo "name count : " . a:0
let res = ["Hey! "]
call extend(res,a:000)
echo join(res)
else
echo "Hey..."
end
endfunction
実行結果は、下記のようになります。
:Hey
" ⇒ Hey...
:Hey Merry Atom Bob
" ⇒ Hey! Merry Atom Bob
引数を1個以上パターン
-nargs=+
を使うよう。
引数なしだとエラーになります。
command! -nargs=+ HeyHey call HeyHey(<f-args>)
function! HeyHey(...)
if a:0 >= 1
echo "name count : " . a:0
let res = ["Hey! "]
call extend(res,a:000)
echo join(res)
else
" 引数なしはエラーになるため、ここには到達しない
echo "Hey..."
end
endfunction
可変長引数じゃないパターン
command! -nargs=+ HeyHey2 call HeyHey2(<f-args>)
function! HeyHey2(n1, n2, n3)
let res = ["HeyHey! ", a:n1, a:n2, a:n3]
call extend(res,a:000)
echo join(res)
endfunction
ひとまず今回はここまで。
実際に触れてみることで、一気に身近に思えてきました!
今まではVimの自作関連は遠目に見ているだけでしたが、今年は自分からも積極的に作っていけたらと思います。
参照
vim-jp >> Hack #158: ユーザコマンドを定義する