「実践Vim」を読んでみた感想と Vim script 初心者講座

vim
この記事は Vim Advent Calendar 2012 350日目の記事になります。久しぶりに読書感想文を書きます。

photo-credit: syui



目次


# 項目
01 「実践Vim」を読んだ感想
02 Vim script 初心者講座
02-01 実践Vimを読んで、気になった操作
02-02 気になった操作を Vim script で簡易化
02-03 先ほど書いた Vim script の[大まかな]解説
02-04 先ほど書いた Vim script の[細かな]解説
02-05 ハマりやすいポイント
02-06 他の言語のインターフェイス



「実践Vim」を読んだ感想


良い本だと感じた理由


「実践Vim」という極めて有益な本があります。

http://tatsu-zine.com/books/practical-vim


まだ、最初のほうしか読んでいませんが、これは、非常に良い本だと思いました。


非常に良い本だと感じた理由は、主に、2つあります。


分かりやすい


この本を非常に良い本だと感じた理由の1つ目は、非常に分かりやすいという点です。


具体的には、目次、表題がTips形式で書かれているため、「何をするのか」が把握しやすいです。


また、懇切丁寧な操作手順の説明と表が載せられているため、「どうすればいいのか」も非常に明確です。

キーストローク バッファの内容
{start} var foo = 1
A;<ESC> var foo = 1;
* 参考までに、表の一部を参照。


このように、「何を、どうすればいいのか」を適切な形で表現してくれているので、非常に分かりやすいと感じました。


面白い


この本を非常に良い本だと感じた2つ目の理由は、非常に面白いという点です。


もしソフトウェアの操作を説明するだけの本なら、実は、表題と表だけで十分だと私は思います。


そして、表題と表だけという簡易な形式は、一読了解にする効果があり、効率も良いでしょう。


しかし、この本では、表題と表以外のところにもたくさんの文章が書かれています。


文章は、個人的な価値観の説明から、なぜその操作方法を選んだのかを説明するためのものが多い印象です。


ちなみに、 Vim というエディタ(メモ帳のようなもの)は、一つのことを実現するにも、たくさんのやり方があります。


このように、分量のある本は、多くに、説得のために使われる文章の割合が多いと私は感じています。


では、なぜ説得のための文章が必要なのでしょう。


それは、説得のための文章がないと面白くないからです。


たしかに、淡々とやり方だけを書いたり、言葉の意味だけを説明したりするリファレンス系の本のほうが、分かりやすく、効率も良いでしょう。


これは、必要ない記述を載せていないからだと考えられます。


しかし、それでは、面白く無いし、最後まで読むことが難しくなるのではないかと思います。


この本は、一定の割合で、説得のための文章に紙面が割かれていますし、その文章の質が良いので、非常に面白いと感じました。


普段、本などを全く読まない頭の悪い私でも、この本は面白いと感じることから、何とか最後まで読めそうな気がします。


参考までに、本文の一部を引用してみました。

 ドットコマンドは、Vimの機能を呼び出す1キーコマンドのなかで筆者の一番のお気に入りといえるかもしれない。2番目に好きなのは*コマンドだ。


 Vim初心者にとっては、ノーマルモードがデフォルトなのが解せない。...(略)。なぜ、ノーマルモードがデフォルトなのか、その理由を説明するところから始めよう。


 画家が絵筆を持ってカンバスと対峙する時間がどのくらいのものか、考えてみよう。確かに、それは画家次第なのだが、カンバスに向かう時間が、その人の仕事時間の半分もあるなんてことになったら、筆者はびっくりだ。



Vim script 初心者講座


はじめに


「実践Vim」は非常に良い本です。この本を読んでみて、少し真似でもしてみようと思いました。


「Vim script 超初心者講座」を書いてみたいと思います。


もちろん、私自身がかなりの初心者ですし、何をしているのか全く訳が分かっていません。


よって、何か間違いがあればご指摘いただけるとありがたいです。


実践Vimを読んで、気になった操作


「実践Vim」を読んで気になったのは、 A{char}<ESC>という行末に任意の文字を挿入する操作です。


これについては、 teol.vimというプラグインもありますので、個人的には、気にも止めなかったし、知りもしなかった操作でした。


キーストローク バッファの内容
{start} var foo = 1
A;<ESC> var foo = 1;
* {start}=スタート、 {char}=任意の文字


Aコマンドは、現在の行の末尾に追加を行う操作です。具体的には、 $aの複合コマンドになります。


気になった操作を Vim script で簡易化


ここで、上に挙げた気になった操作を Vim script で簡易化してみます。以下を~/.vimrc~/.vim/plugin/test_hello.vimなどに書き込んでみてください。もし該当ファイルがなければ、ファイルを作るところから始めます。


function! TestHello(char)
  " let key = 'A' . a:char
  call feedkeys("A" . a:char . "\<ESC>")
endfunction!

command! -bar -nargs=* TestHello call TestHello(<f-args>)
nnoremap <silent> <Leader>; :TestHello ;<CR>

参考:
http://vim-jp.org/vimdoc-ja/


ちなみに、toel.vimという便利なプラグインもあります。


先ほど書いた Vim script の大まかな解説


上の例では、 まず、functionで命令の集まりを作りました。この命令の集まり(命令群)を関数と言うことがあります。functionからendfunctionまでに書いた命令群は、ノーマルモードから:call TestHello {char}と入力することでを呼び出せるようになります。





参考:
function(組み込み関数)
命令群の記述方法


そして、次に、 commandでコマンドを作り、 :TestHello {char}と入力することで先ほど function で作った命令群を呼び出せるようにしました。作成するコマンドは、最初は大文字でなければいけなかったような気がしますので、注意が必要です。





参考:
コマンド定義(command)


最後に、 nnoremapでキーマップを設定し、 , + ;を押すと、 :TestHello ;を入力した時と同じことができるようにしました。ちなみに、,は、<Leader>ですので、注意してください。これは、キーボードによって表記が変わってきます。





参考:
キーマッピング(nnoremap)

モードに対応するコマンド


コマンド N I C V
map/noremap - -
nmap/nnoremap - - -
imap/inoremap - - -
cmap/cnoremap - - -
vmap/vnoremap - - -
map!/noremap! - -
* N=ノーマル, I=インサート, C=コマンド, V=ビジュアル。(これらは、すべてモードを示すものです。)

mapオプション


<silent> コマンドラインへの表示をなしにする
<unique> すでにキーマップが存在する場合は、上書きしない
<buffer> バッファローカルなキーマッピングを定義する
<expr> 文字列を評価し、評価した結果をマップ先とする


先ほど書いた Vim script の細かな解説


function! TestHello(char)
  " let key = 'A' . a:char
  call feedkeys("A" . a:char . "\<ESC>")
endfunction!

command! -bar -nargs=* TestHello call TestHello(<f-args>)
nnoremap <silent> <Leader>; :TestHello ;<CR>


{keyword} 説明
function 関数と言って、命令の集まりをひとまとめにしておくために使います。
function! 「!」は、古いものを新しいものに書き換えるときに使います。つまり、上書きです。よく使うことがあります。ただし、「:!」というコマンドは、シェルで実行するということになります。意味が全く違うので、注意してください。
endfunction 先ほど説明した function の終わりを知らせます。つまり、 function を使ったら、これは必ず書かないといけません。
TestHello 関数の名前です。この部分は自分で考えたものをつけます。
(char) 一つの引数を使用します。複数使用する場合は、(char, str, args)というようにします。使用する文字列は自分で決めます。引数というのは、コマンドの後に使う文字列や数字のことを言います。例えば、「$ cd ~/home」というコマンドでは、「~/home」の部分が引数です。数字からは始められなかったような気がしますので、注意が必要です。
let key 変数といって、空箱のようなものを用意します。ここで、「let」が空箱を用意するよという合図で、「key」が空箱になります。空箱には文字列や数字を入れておくことができ、後で繰り返し使うことが出来ます。
" let key コメントアウトと言って、「"」を文頭につけることで、それ以降に書いた命令がスキップされます。スキップというのは、つまり実行されません。よく補足説明などを記述する際に利用されます。
'A' 「let = xxx」で作った空箱に「A」という文字列を入れるときは、「'」で囲みます。
. スペースがあるので注意です。イメージでは、「_._」となっていて、この場合、「_」がスペースです。これは、代入の際、文字列をつなげるときに使います。
a:char 引数といって、コマンドのあとに続けた数字や文字列を代入するときなどに使います。「function! TestHello(char)」が引数です。ちなみに、代入というのは、「入れ替える」、「足す」というような意味。他の内部変数については、こちらが参考になります。
call feedkeys() キーマッピングを呼び出すための命令です。ここで、「call feedkeys("A")」とすれば、ノーマルモードで「A」を押したことになります。ちなみに、「call」から続く命令群は、ノーマルモードで「:call xxxx」と入力することで呼び出せます。
\<ESC> 「Ctrl+a」キーや「Enter」キーなどは1文字だけでは表現できないため、<C-a>、<CR>などと表現されます。ちなみに、<ESC>キーの前にある「\」は、 特殊文字を使えるようにするためのものです。
-bar コマンドの後ろに | を使って他のコマンドを続けて書くことを許可するオプションです。
-nargs=* 引数を使えるようにするために設定します。詳しくはリンク先でお願いします。
<f-args> コマンドから関数に引数を渡すときに使います。
<silent> コマンドラインに表示しない時に使います。その他、「<buffer>」などがあり、「<buffer>」は、コマンドラインに表示するときに使います。「<buffer>」は特に、引数をその場で決めたいときなどに便利です。上の例では、「nnoremap <buffer> <Leader> :TestHello<Space>」とすることで、行末に何を入れるか自分で決められます。

* {char}=任意の文字列、{keyword}=キーワード


ハマりやすいポイント


コマンド名は、組み込みコマンドと区別が付くように大文字で始めなくてはいけません。また、コマンド名には英数字のみ使用できます。

正誤 具体例
command! -bar -nargs=* Testhello call TestHello()
command! -bar -nargs=* testhello call TestHello()

内部変数の名前には文字と、数字とアンダーバー('_')を使うことができる。しかし数字で始めることはできない。波括弧を使うこともできる。

正誤 具体例
let x = a:sev_uil
let x = a:7uil


参考:
http://vim-users.jp/2010/06/hack158/
http://vim-jp.org/vimdoc-ja/eval.html#E704


他の言語のインターフェイス


Vim scriptでは、他の言語のインターフェイスを使うことが出来ます。他の言語のインターフェイスを使うことができるというのは、 Vim script 内で他の言語の書き方ができるということです。


使える言語としては、LuaPythonRuby などです。これは、おすすめ順に並べています。


ただし、前提として、当該言語のインターフェイスを使えるようにコンパイルされていなければなりません。ちなみに、コンパイルとは、コンピュータ上で実行可能な形式に変換することを言います。コンピュータで使用するソフトウェアというのは、通常、そのコンピュータが読める形にしないと実行できるようになりません。


コンパイルされているかどうかは、以下のコマンドで判明します。

$ vim --version

+perl +python +ruby +lua/dyn +tcl



Pythonインターフェイス


" VimScript
function Fuga()
    python <<EOM
print "fuga"
EOM
endfunction

python <<EOMから EOMで囲った部分に Python コードを記述します。


注意点として、 EOMの前に空白があると Python ブロックの終了と見なされません。

正誤 具体例
EOM
 EOM


参考:
http://vim-users.jp/tag/python/


リンク


if_lua
if_python
if_ruby


さいごに


Vimの基本操作に関しては、「実践Vim」でなんとかなるかもしれません。


しかし、私は、ヘルプを読んでも、ブログ記事を読んでも、 Vim script については、全くもって、さっぱりわからないので、「実践Vim script」が発売されるといいですね。


「実践Vim script」が発売される日を楽しみにしてます。