hoge() で囲みたい症候群

この記事は Vim Advent Calendar 2013 91日目の記事になります。


みなさんは, 変数を hoge() で囲みたくなることはありませんか.
私の場合は必要になる hoge の種類が少ないので, vimrc に surround の設定を追加して対応していました.

b:surround_{char2nr("a")} = "hoge(\r)"

これだとドットの公式も使えるし, サクサク hoge() で囲えるわけです.

でも, 不満が2点あって,

  • 囲みたい対象が配列や関数な形式のときはどうすんべ
  • たまに hage でも囲みたいときがあるけど, vimrc に追加するのは面倒

そこで毎度の lingr で聞いてみました. (以下抜粋+勝手加工)

syngan
v[123] みたいなのを hoge(v[123]) と hoge() で囲うをたくさんやりたいのですが
この操作にドットの公式で実現するにはどうするのが正解ですか?

thinca
q
そのくらい複雑になるとマクロくらいしかないかと

syngan
そうですかぁ。。悲しい。。
マッピングされていない問題
ぬぅ。。録音が面倒で。。。

manga_osyo
ふと、hoge() を yank している場合、hoge({textobj}) みたいに貼り付ける operator があれば便利そうな気がしたけどピンポイントだなぁ

syngan
現時点で operator-surround は surround.vim でいうところの, b:surround_{char2nr("a")} = "hoge(\r)" みたいなのって実現できるんですか?

manga_osyo
let g:operator#surround#blocks = {
\ "-" : [
\ { 'block' : ['hoge(', ')'], 'motionwise' : ['char', 'line', 'block'], 'keys' : ['(', ')'] },
\ ]
\ }
で
( を append しようとすると hoge(foo) になる
http://lingr.com/room/vim/archives/2014/02/26#message-18446167

んで, マクロは面倒なので, これを解決するために, 2 つプラグインを作りました.

vim-operator-furround

上でおしょーさんが言っているのとは少し違いますが, hoge( を yank しているときに hoge() で囲うプラグインです. hoge[ とか hoge<, hoge{ など, yank している文字列の最後の文字をみて囲う方法が変わります.

LaTeX を書いているときに使ったのは, \verb|| で囲うバージョン.
何か所か, 囲うのが漏れていたので修正に便利でした.
LaTeX みたいなのだと, \begin{hoge} と \end{hoge} で囲みたいのでこういうのを変換できると便利なことはありそうな感じですが, これこそピンポイントすぎる気がしたので対応していません. 自分が使わないし.

簡単な使い方

繰り返しになりますが,

    map H <Plug>(opeartor-furround-append)

などとしておいて,

  : カーソル位置

I am a pen.

こういう状態のときに,
'hoge' または 'hoge(' が yank されている状態で, Hiw とすると

I am a hoge(pen).

'hoge[' が yank されている状態で, Hiw とすると

I am a hoge[pen].

レジスタ a に 'hoge<' が格納されている状態で "aHiw とすると

I am a hoge.

となります.

vim-textobj-postexpr

名前があれなんですが, v[123] とか f() みたいなのを対象とします.

以下のプラグインが近い動きをしてくれるのですがほしいものと違ったので作りました.

こんな感じで, name に対して [] とか () で続くもの, というイメージでしょうか.
postexpr-a は改行の先も見に行くようになっています.

  : カーソル位置
  : 範囲


printf("hoge\n", (sqrt(value[1,2][3]) + 1) + func[1,2](a, b, c));  " postexpr-i
printf("hoge\n", (sqrt(value[1,2][3]) + 1) + func[1,2](a, b, c));  " parameter-i

printf("hoge\n", (sqrt(value[1,2][3]) + 1) + func[1,2](a, b, c));  " postexpr-i
printf("hoge\n", (sqrt(value[1,2][3]) + 1) + func[1,2](a, b, c));  " parameter-i

printf("hoge\n", (sqrt(value[1,2][3]) + 1) + func[1,2](a, b, c));  " postexpr-i
printf("hoge\n", (sqrt(value[1,2][3]) + 1) + func[1,2](a, b, c));  " parameter-i

printf("hoge\n", (sqrt(value[1,2][3]) + 1) + func[1,2](a, b, c));  " postexpr-i
printf("hoge\n", (sqrt(value[1,2][3]) + 1) + func[1,2](a, b, c));  " parameter-i


func(value[1]
() + 2);  " postexpr-i
func(value[1]
() + 2);  " postexpr-a


func(value[1]
() + 2);  " postexpr-i
func(value[1]
() + 2);  " postexpr-a

まとめ

これでめでたくドットの公式を使って hoge() で囲えるようになりました。