Vim
vimscript

Vimコマンドを自作してみる、という今年の目標を達成するためにVim scriptに触り始めてみたら、かなり楽しいー!(コマンドでの引数の受け取り方)

最初に

今年密かに立てた目標の一つがVim scriptを書いてみること。Vimで自作コマンドを作ってみること。
Vimを使っていながらこれらのことを敷居の高いものと勝手に感じていた自分を見直すため、Vimで基本的な部分を調べながらサンプルを書いてみました。
(今回は主に、関数における引数の受け取り方について調べました)

なお、これは個人的な備忘録(個人的学習ノート)となります。

ここである程度、基本的な事柄に触れたら、vim-jpのドキュメントを一通り読んでみて理解を深めていこうと思います!

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

コマンドラインコマンドを定義してみる

作業ディレクトリ内で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の自作関連は遠目に見ているだけでしたが、今年は自分からも積極的に作っていけたらと思います。

参照

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

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

vim-jp >> Hack #158: ユーザコマンドを定義する

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

引数が 0 or 1 個の関数を呼ぶExコマンドを定義する方法

はじめてのvimscriptとvimプラグインの作成

VimScriptざっくりチュートリアル(関数編)