読者です 読者をやめる 読者になる 読者になる

clever-f.vim でカーソルの横移動を便利にする

Vim

この記事はVim Advent Calendar 2012 291 日目の記事になります.徐々に気温も秋らしくなり,終わりが見えてきてますね.

この記事では,Vimf キーを拡張する clever-f.vim というプラグインを紹介します. 今まで tekkoc さんや thinca さんに紹介していただいたのですが,自分で紹介していなかったのと,色々と機能追加をしたので今回最新の内容で紹介することにしました.

Vimf{char},使ってますか?

Vim での横移動は何を使っているでしょうか?hl での1文字ずつの移動や wb での単語単位での移動など色々ありますが,個人的におすすめなのが fF です.

Vimf{char} キーは,{char} に任意の1文字が入り,現在のカーソル行内で右方向に 最初に現れる {char} に移動します.また,; で直前の検索を繰り返すことができ,行き過ぎた場合などは , で戻ることができます. また,それ以外にも逆方向に動く F{char} や,{char} の手前まで移動する t{char} および T{char} といったマッピングが Vim のデフォルトで用意されています.

(赤字がカーソル位置)

poyo hoge huga

  ↓fh

poyo hoge huga

  ↓;

poyo hoge huga

行が長いときや,行内に記号が多い時,lw による移動よりもかなり少ない打鍵数で目的の位置まで移動できますが,

  • ; で繰り返す必要が生じたときに意識的に f から ; にキーを押し変えないといけない
  • f,; というとても押しやすい位置のキーを3つも使ってしまう

という問題があります.特に後者の理由で f,; を潰してしまっている設定もよく見ます.

f{char} による移動を強力にする clever-f.vim

clever-f.vim

clever-f.vim は前章の f の機能を強化するためのプラグインです.最初に f{char} で移動したあと,そのまま f で順方向,F で逆方向に直前の移動を繰り返すことができます.これにより,目的の任意の箇所に f{char}ff... で到達することができますし,カーソルを進めすぎた場合でも F で戻ることができます.また,;, は使わないので,自分の好きな他のマッピングに使うことができます.さらに,オリジナルのf と違い,w と同様に行をまたいで移動できます.もちろん,F{char}t{char}T{char} でも同じ挙動が実装されています.

なお,連続で f{char} を入力することはできなくなりますが,f{char} を繰り返したい場合はそうそう無い上,hl で1文字分でもカーソルを動かせば良いのであまり問題にはなりません.

screen shot

; による繰り返しの面倒くささから最初は nnoremap ff ; という単純なマッピングをしていたのをプラグイン化し,thinca さんの魔改造などを経てそれなりにしっかりした作りになっていると思います.

clever-f.vim の挙動をカスタマイズする

clever-f.vim では,変数を設定することで検索の挙動をカスタマイズすることができます.clever-f.vim の検索のデフォルトの挙動は行をまたいで移動できる点を除いてオリジナルの f と同じになっているので,.vimrc で自分好みにカスタマイズするようにします.

ignore case,smart case

一般的に大文字の入力にはシフトを押さないといけないため,f{大文字} は少し不便です.なので,clever-f.vim では大文字小文字を区別せずに検索することができます. すべての場合に大文字小文字を無視したい場合は g:clever_f_ignore_case1 に,大文字を入力した時のみ大文字小文字を区別したい場合は g:clever_f_smart_case1 にすると有効になります.

migemo っぽい検索

f マッピングの問題点として,アルファベットと記号しか入力できないという点が挙げられます.しかし,日本語の文章であっても f{char} で移動したいと感じることがあります. そこで,clever-f.vim では migemo っぽい検索を実装しています. migemo とは,ローマ字の入力で日本語を検索するためのツールです.clever-f.vim では migemo で生成した正規表現をプラグイン内に持っており,例えば fm と入力すると にマッチするような検索ができます.この機能は g:clever_f_use_migemo1 にすると有効になります.なお,cmigemo などのツールは不要です.fのあとのアルファベット1文字だけでマッチさせるので予想外の文字にマッチしたりすることもありますが便利です.

migemo screen shot

行をまたいで検索しない

前章でも書いたように,clever-f.vim は行を超えて {char} を検索しますが,オリジナルの f の挙動に合わせて現在行のみで検索したい場合もあります. その場合は g:clever_f_across_no_line1 に設定します. 細かい話ですが,上記の migemo 検索を有効にしている場合,migemo 検索が現在行にマルチバイト文字があるときのみ有効になるなど,少し挙動が賢くなったりもします.

fF の検索方向を固定する

f{char} のあとの繰り返しは f が順方向,F が逆方向となっており,F{char} で検索すると左方向(順方向)への繰り返しは f,右方向(逆方向)への繰り返しはF となります. これは,順方向のほうが押す頻度が多いため,押しやすい f を使うようにしているためです. ですが,f は必ず右方向に移動,F は必ず左方向に移動するようにしたほうが挙動が単純になり分かりやすいのも事実なので,g:clever_f_fix_key_direction1 に設定するとそのような挙動にすることもできます.

任意の記号にマッチする文字を設定する

記号はシフトキーを押しながら入力しなければならなかったり,距離が遠かったりで押すのが面倒なことが多々あります. そこで clever-f.vim では任意の記号にマッチする文字を設定できます.例えば let g:clever_f_chars_match_any_signs = ';' とすると,f; で任意の記号にマッチします.

any signs screen shot

類似のプラグイン

カーソル移動系のプラグインの中で,clever-f.vim に近いものをピックアップして比較してみました.

vim-easymotion

vim-easymotion は 画面上にラベルを散りばめ,行きたいラベルを入力することでカーソルを移動させるプラグインです. 「なんとなくこの辺りに行きたい」ときにとても便利です. clever-f.vim が横方向の移動を行うのに対し,vim-easymotion は縦,斜めなどもカバーしていますが,clever-f.vim は目的位置の文字だけを見て f{char}ff... と入力するのに対して vim-easymotion は ラベルを出す→どのラベルが一番行きたい場所に近いか判断するラベルを入力する というステップを踏むため,若干面倒です. 使ってみた感覚としては,少し遠目のところに飛びたいときに便利ですが,横移動では clever-f.vim のほうが考えることが少なく便利なので使い分けると良い感じです.

vim-seek

2文字入力してカーソルを移動するプラグインです.s{char}{char} で移動します.当然,2文字入力する分手間がかかりますが,一発でジャンプできる可能性は高くなります. 一発で目的位置までジャンプすることを想定しているためか繰り返しが実装されていないのと,勝手に多くのマッピングを定義するのが難点だと感じました.

まとめ

f{char} マッピングを強化する clever-f.vim を紹介しました.手前味噌ですが,3ワード以上離れていればとりあえず f を押すといった感じで使っていて,これを使い始めてから横方向の移動がかなり改善したように感じますし,是非試していただけると良いと思います.カーソル移動はコーディングの効率に直結すると思っているので,これからも改善していきたいです.