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

ref.vim の内部構造を大幅に書き換えた

ref.vim の内部構造が全然別物になった。

とは言ったものの、使う側からするとあまり変化はない。
普通の人は内部構造なんて興味ないと思うので、先にそれ以外で変更した部分を挙げておく。

外見的な変更点

ref#jump()

前からあったんだけど、ドキュメントには書いてなかった。今回使い方を変えてドキュメントにも書くようにした。いるかわからんけど、以前から勝手に使ってた人は使い方が変わってるので注意。
これを使うとカーソル位置からキーワードを拾って ref を開けるので、例えば

nnoremap <silent> <Space>K :<C-u>call ref#jump('normal', 'alc')<CR>
vnoremap <silent> <Space>K :<C-u>call ref#jump('visual', 'alc')<CR>

などとしておけばどこでも K で辞書が引ける。
さらに ref#jump() は 'operatorfunc' としても振る舞うことが可能。誰得。

detect を本体に統合した

detect って言う怪しいソースがあったんだけど、うまく動作してなかったのと本体から参照している部分があって気持ち悪かったので本体に統合してしまった。
結果、detect と言う名前のソースは使えなくなったんだけど、ref#detect() とかもあるしまあ困らんだろうという判断。

各ソースも地味に更新
  • alc
    • 結果をキャッシュできるようにした。
      • デフォルトでは無効なので g:ref_alc_use_cache を 1 にする。
  • man
    • LANG 環境変数を変更するオプション(g:ref_man_lang)を追加。
  • perldoc
    • 補完候補を出す際、オプションでパッケージ単位で候補を出せるようにするオプション(g:ref_perldoc_complete_head)を追加。
      • つまり、候補がいきなりフルパッケージ名で出ずに、IO:: や HTTP:: で止まるようになる。:: まで入れてさらに補完すると続きがでる。
      • 言うまでもなく ku-ref とは相性が悪い。
  • pydoc
    • perldoc と同じようなのを追加。
  • refe
    • refe2 に対応。
    • RSense の型推論を使ってカーソル下のキーワードを引けるようにした。
      • 当然 RSense 必須。

refe2 なんだけど、ここにあるやつを前提で作ってみた。
ただ、refe1 と違ってクラスの説明ページにメソッド一覧がない。ないのも不便なので検索を利用してメソッド一覧を出してる。
が、{クラス名}# とか {クラス名}. で検索してるんだけど、なんか出てこないメソッドがよくある。この検索どうなってるんだろう。
あと仕組み上継承したメンバは出せないです。この辺よくわかってなくてかなり適当。refe2 ってこういうものなの?誰かご存知の方教えてください><


あと RSense の方も割と適当です。
型推論するには対象の式の末尾にカーソルを持っていかなくちゃいけないみたいなんだけど、正確に調べるのも無理なので現状では多分識別子の上だろってことにして単語の末尾に移動してる。
また、単語の前が . だった場合は、多分メソッド呼び出しだろってんでその前の型を推論してそのメソッドのページを開こうとする。
設定例。

let g:ref_refe_rsense_cmd = expand('~/src/rsense/bin/rsense')
let g:ref_refe_rsense_cmd = ['ruby', expand('~/src/rsense/bin/rsense')]

これとは別に、数値、文字列、シンボル、正規表現リテラル上の場合は Vim の syntax を利用して飛ぶようにした。この場合 RSense 自体呼ばれない。

内部構造の変更点

で、内部構造の話だけど、ぶっちゃけてしまうと ku 0.3 のをパクった。つまり、

  • プラグインは所定の位置にautoload関数群として定義する

という方式から、

  • プラグインは関数などを持った辞書で、それを本体に登録する

という方式に変更した。
ただし、ku 0.3 は関数は function() で作ったものを登録しているが ref.vim では辞書関数を使ってる。こっちの方が楽だったので。

変更したのは以下の点で新しい方式の方が優れていると感じたから。

管理する範囲が狭まる

所定の位置の関数だと、プラグインの関数を呼び出す度に、その関数が存在するかチェックする必要がある。
これは動的に変わる。
また、利用可能なプラグインのリストが欲しい場合は glob() 等でファイルシステムを走査する必要がある。

どこからでも追加できる

プラグインは単なる辞書なので、例えば 1 つのファイルで複数プラグインを定義したり、 vimrc で独自のプラグインを定義して追加することも可能になる。

変更もしようと思えばできる

例えば、以下のようなこともやろうと思えばできるわけです。

let alc = ref#available_sources('alc')
function! alc.complete(query)
  return split(ref#system(['look', a:query]).stdout, "\n")
endfunction

alc を look コマンドで補完する。ちなみに実際にやってみたんだけど候補が多すぎて微妙だったのでやめた。

長い関数名を書かなくて済む

ref#plugin_name#function_name() とか、結構長い。まあ ref はまだ短いのでマシなんだけど。プラグイン名が長いと大変になる。



まあでも、デメリットがないわけではない。

追加する必要がある

どこで定義しようが追加する必要がある。そのため ku 0.3 では plugin/ku/source/{source}.vimプラグインとなる辞書を生成+登録している。
ただ、私は plugin にゴミみたいなファイルが増えるのが嫌だったので、1 つ特殊なルールを設けた。それは、

オートロード関数 ref#{source-name}#define() は、autoload/ref.vim が読み込まれ
る際に自動的に呼ばれ、戻り値がソースとして登録されます。

:help ref-autoload

というもの。結局 autoload のファイルを走査してしまっているけど、初回のみなのでいいでしょってことで。

デバッグしづらい

これは辞書関数を使った場合の話なので ku 0.3 の場合は関係ない。
辞書関数ほんとデバッグしづらいよね…。でも書きやすいんだよなぁ。

その他の変更

ref#system() の戻り値が変わってるので注意。詳細は :help で。