概要
Vimの置換コマンド(:%s/{pattern}/{replacement}/g
)を素早く入力するためのシンプルなプラグインを作りました。置換コマンドのマッピングはvimrcに直接書いてしまっている人も多いかと思います。自分もそうだったのですが、個人的にファイルが長くなってきたのでプラグインに分離しました。
雛形挿入と検索結果抽出の2つの機能があり、タイプ数が減って少しだけストレスフリーになります。
ちなみに、このプラグインは独自のマッピングを一切追加しないので、自分でマッピングを定義しないと動きません。下のコードをvimrc(またはinit.vim)に貼り付けて、マッピングキーはお好みで設定してください。
nnoremap <expr> s substy#substitute_operator('\m')
noremap <expr> ss substy#substitute('\m', '', '')
noremap <expr> s/ substy#substitute('', @/, '')
noremap <expr> s? substy#substitute('', @/, @/)
noremap <expr> s"" substy#substitute('\m', @", '')
noremap <expr> sy substy#yank()
置換コマンドの雛形挿入
substy#substitute({magic}, {pattern}, {replacement}, [{flag}])
は、置換コマンドの雛形を挿入する関数です。ss
と打てば、いい感じのところにカーソルが移動するので、サッと入力を始めることができるようになります。
返す結果はモードの文脈によって変わります。
- ノーマルモード:
:%s/{pattern}/{replacement}/{flag}
- 文字選択モード:
:%s/{pattern}/{replacement}/{flag}
- 行選択モード, 矩形選択モード:
:'<,'>s/{pattern}/{replacement}/{flag}
ちなみにパターンが空文字列のときは、文字選択モードから呼び出すと選択テキストが入ります。
- 文字選択モード:
:%s/{選択テキスト}/{replacement}/{flag}
{pattern}
に$
や[
などの正規表現で使う文字が入っていると、意図しない置換になってしまうので、エスケープしてやる必要があります。エスケープするには、{magic}
に正規表現のマジックモードを指定します。指定できるのは、\v
(very magic), \m
(magic), \M
(nomagic), \V
(very nomagic), ''
(何もしない)です。
パターンに設定すると便利なのは、@"
(直前にヤンクしたテキスト), @*
(クリップボードの中身), @/
(直前に検索した正規表現)とかでしょうか。<C-r>
でも同じことできますが、タイプ数が減るところに価値があります。
オペレータ関数を定義しておくと、テキストオブジェクトをパターンに設定できるので便利です。例えばカーソル下の単語をパターンにしたいときはsiw
です。()
の内側をパターンにしたいならsi)
です。
返ってくる結果のイメージは下のようになります。
noremap <expr> ss substy#substitute('', '', '')
"=> (NORMAL) :%s/_//g
"=> (V-CHAR) :%s/{SELTEXT}/_/g
"=> (V-LINE) :'<,'>s/_//g
noremap <expr> ss substy#substitute('\m', '', '')
"=> (NORMAL) :%s/_//g
"=> (V-CHAR) :%s/{ESCAPE(SELTEXT)}/_/g
"=> (V-LINE) :'<,'>s/_//g
noremap <expr> ss substy#substitute('\v', '', '')
"=> (NORMAL) :%s/\v_//g
"=> (V-CHAR) :%s/\v{ESCAPE(SELTEXT)}/_/g
"=> (V-LINE) :'<,'>s/\v_//g
noremap <expr> s/ substy#substitute('', @/, '')
"=> (NORMAL) :%s/{@/}/_/g
"=> (V-CHAR) :%s/{@/}/_/g
"=> (V-LINE) :'<,'>s/{@/}/_/g
noremap <expr> s"" substy#substitute('\m', @", '')
"=> (NORMAL) :%s/{ESCAPE(@")}/_/g
"=> (V-CHAR) :%s/{ESCAPE(@")}/_/g
"=> (V-LINE) :'<,'>s/{ESCAPE(@")}/_/g
noremap <expr> s"" substy#substitute('\v', @", '')
"=> (NORMAL) :%s/\v{ESCAPE(@")}/_/g
"=> (V-CHAR) :%s/\v{ESCAPE(@")}/_/g
"=> (V-LINE) :'<,'>s/\v{ESCAPE(@")}/_/g
検索結果を抽出
substy#yank()
は、検索したあとに、マッチしたテキストだけを抜き出す(抽出する)関数です。検索結果を行として抽出してレジスタ(デフォルトで "
レジスタ)にヤンクします。VSCodeのマルチカーソル機能見ていて、Vimでも同じことやりたいなと思って作りました。
言葉だけで説明が難しいですが、とりあえず、何か検索したあとで syp
と打ってみれば、どんな機能かだいたい分かると思います。他のレジスタを使いたい場合は、"zsy
のようにレジスタを前置してください。行を制限したい場合は、行選択モードでsy
します。
サブマッチを抽出したい場合は、{count}
機能を使います。応用が広がりますね。
- 辞書のキーと値を抽出したい場合、
/\v(\w+)\s*:\s*(\w+)
を検索後、キーは1sy
、値は2sy
- HTMLのh1,h2...タグの中身を取り出したい場合、
/<h\d.\{-}>\(.\{-}\)<\/h\d>
を検索後、1sy
インストール
お好きなプラグインマネージャを使ってください。
https://github.com/tkhren/vim-substy
call dein#add('tkhren/vim-substy')
あまりいないと思いますがset nomagic
, set gdefault
を設定していると期待通りに動きません。
残りのヘルプはドキュメント(:h substy
)を参照してください。