balloon-evalを使ってマウス位置を取得

ばよえ〜ん(訳:Vim Advent Calendar 2012への12回目の投稿です)
この記事はVim Advent Calendar 2012の129日目の記事になります。
128日目は@aoisensiさんのSteamerだけどVim初めたいけど…って人のための記事でした。
とてもVim意識の高い記事ですね。
新しい事を始める人が多いこの時期、上記の記事を参考にしてぜひVimに挑戦してはいかがでしょうか。


さて、JavaScriptでは現在のカーソルの位置を取得したり、onmouseover/onmouseoutなどのイベントを使うなど、マウスの位置に応じて様々な操作を行うことができます。
こういった処理はVimでは実現できるのでしょうか?
Vimはもともと端末で動くアプリケーションだったのだから、そのような処理は実装されていないのでは?と思われるかもしれません。
しかし、できるのです。
balloon-eval機能を使えば、それも可能になるのです。

balloon-evalとは

バルーンウインドウを表示する機能です。
GUI版でしか動きません。


文章で説明するより動くものを見た方が早いでしょう。
「:help 'balloonexpr'」にサンプルがあるのでそれを引用します。
以下のソースコードをファイルに保存して「:so {ファイル}」するか、
またはquickrun.vimが入っている場合、以下のソースコードをバッファに貼り付けて
「:QuickRun vim」するなどして、ソースコードを実行させてください。

function! MyBalloonExpr()
  return 'Cursor is at line ' . v:beval_lnum .
  \', column ' . v:beval_col .
  \ ' of file ' .  bufname(v:beval_bufnr) .
  \ ' on word "' . v:beval_text . '"'
endfunction
set bexpr=MyBalloonExpr()
set ballooneval

実行した後、マウスをバッファ上の単語の上に置くと、以下の画像のようになるはずです。

バルーンウインドウの表示をやめるには、「:set nobeval」とします。


ともあれ、この機能の使い道としては甚だ間違っていると言えなくもないですが、
balloon-evalを使えばv:beval_colとv:beval_lnumでマウス位置を取得可能なことが分かったかと思います。

デモプラグイン

tyru/bevaldemo.vim · GitHub

デモ用のプラグインを作ってみました。
LinuxのGTK2版で動作を確認しています。
「:BEvalDemoStart」で開始します。


しかし、もともとballoon-evalはマウス位置を取得するための機能ではないため、動作が非常に不安定です。
(試してみたところ、Vim +kaoriya 7.3.797 on Windows 7では動きませんでした)
また、実装がCursorハイライトグループを書き換えて戻さないなどの横暴さのため、
専用のVimを起動して試してみてください。


マウスをバッファ上で動かすと照準(のようなもの)が追従します。
左クリックでエフェクトがかかります。
このロジックを使えばリアルタイムでマウス位置を取得できるため、VimFPSということも可能になるはずです。
というより、正にVimFPSゲームを作ろうとしていたのですが、しんどすぎて諦めました。


前日の記事と微妙にかぶるネタですが、前日の記事は心構え編、この記事はfps.vimまでの道のり(試作)編、そして誰かがfps.vimを書く実践編までが一連の流れとなっております。*1
我こそはと思う方は挑戦してみてください。

*1:まぁもちろん意図した訳ではありません