vim の text-object をより便利に使えるプラグイン - surround.vim

http://www.vim.org/scripts/script.php?script_id=1697
vim7 から追加された text-object は大変便利で、今や手放せなくなっています。その text-object をより便利に使えるプラグイン、surround.vim が便利すぎるので紹介します。
いままで、text-object では (以下では、コードの『*』の位置に現在カーソルがあると考えてください。)

foo 'b*ar' baz

の位置にカーソルがあるとき、i' でシングルクオーテーションの中身を選択できたり、a' でシングルクオート含む部分を選択できました。しかし『'』そのものを削除したり、置換したりはできなく、ちょっと不便でした。しかし、surround.vim では

  • ds
  • cs
  • ys
  • vs

それぞれにコマンドを割り当てて、様々なことができるようになってます。たとえば

foo 'b*ar' baz

で『'』を削除したければ、ds' でできます。『'』を『"』に置換したければ、cs'" で、『'』を() に置換したければ cs') でできます。ruby 使ってると文字列リテラルを『'』を『"』に変える必要が結構出てくるんですが、この機能のおかげで簡単にできるようになりました。
ys を使うと、様々な位置から『'』や『()』などで囲むことができます。

a = Array.new *foo, bar

上記カーソル位置の時に、ys$) ( 『$)』で行末まで() で囲えと命令)すると、

a = Array.new *(foo, bar)

となって、後からでも『()』や『'』ですぐ囲うことができてかなり便利です。yss を使った場合、行全体がターゲットになるため、

foo b*ar baz

で yss' を押すと

'foo bar baz'

と行が『'』で囲われます。

また Visual Mode 時の選択範囲の外側を囲うことができるため、

my $foo = $self->method;
$foo->bar;

を選択して S{ で(大文字の S だとインデントも有効)

{
  my $foo = $self->method;
  $foo->bar;
}

となります。

XML タグの追加、削除

text-object には t でタグの選択機能がありますが、やはりこれもタグの内側のみ選択、などの機能でした。
しかし、surround.vim を使うと現在囲っているタグの削除ができます。

<div><p class="comment"><strong>f*oo</strong> bar</p></div>

の時に、dst を押すと

<div><p class="comment">*foo bar</p></div>

となります。ここでもう一度 dst を押すと

<div>*foo bar</div>

となります。もちろん外側のタグの置換もできて、ここで cst<p> と押すと

<p>*foo bar</p>

となります。またタグの追加簡単で、v で foo を範囲選択して、st<strong> で

<p>*<strong>foo</strong> bar</p>

になりますし、ys を利用して、ysst<div class="foo"> と押すと

<div class="foo"><p><strong>foo</strong> bar</p></div>

と割と自在にタグで囲むことができるようになります。

insert-mode で使う

insert-mode でも <C-G>S を押すと surround.vim を使うことができるため、たとえば <C-G>S<html><C-G>S<head> と入力すれば

<html>
  <head>
  *
</head>
</html>

ときちんと閉じタグが自動で入力され、されてさくさく書き始めることができます。

rhtml や php のタグの入力

surround.vim を拡張することで、簡単に rhtml でよく使うタグや php タグの入力ができるようになります。rails.vim を入れると勝手に rhtml 編集時に拡張してくれて、たとえば

link_to '/', *'top'

な時に yss= で

<%= link_to '/', 'top' %>

になったり、insert-mode で Se で

<% * -%>
<% end -%>

と非常によく使うひな形をすぐ入力できたりして便利です。php のタグの場合、~/.vimrc に

autocmd FileType php let b:surround_45 = "<?php \r ?>"

とか書いておくと、php の編集時に、たとえば

foo echo $bar baz

の echo $bar を範囲選択して s- で

foo <?php echo $bar;?> baz

とすることができます。

surround.vim を拡張する (gettext篇)

それでは、自分がよく使う入力を、surround.vim に登録してみましょう。上の rhtml や php の入力も拡張して行ってます。
surround.vim を拡張するには、グローバル変数 g:surround_アスキーコード にテンプレートを書き込めばOKです。vimアスキーコードを調べるには、調べたい文字の上にカーソルをあわせて :ascii と押すと調べられます。
最近 gettext を使う機会が増えてきて、 'foo' を _('foo') に、 "foo" を _("foo") に変更したいことがよくあるので、早速そのような動作をするように拡張してみましょう。
~/.vimrc に

let g:surround_103 = "_('\r')"  " 103 = g
let g:surround_71 = "_(\"\r\")" " 71 = G

これだけで完了です。これで、

foo 'b*ar' baz

が cs'g で

foo *_('bar') baz

などと簡単に gettext な syntax に置き換えることができます。それでもどばーと gettext に置換したいときは面倒なので利用してない g", g' *1 を nmap で定義しちゃいます。

nmap g' cs'g
nmap g" cs"G

これで、g' や g" で簡単に文字列リテラルを gettext な形式に置き換えることが可能になりました。

終わりに

surround.vim は久しぶりに Life Changing な plugin だったので、気に入ったら plugin の rate this script で Life Changing を押すと良いと思いました。

*1:g' はデフォルトで利用されているが使っていない