basyura's blog

あしたになったらほんきだす。

補完候補を ランク > 長さ > 辞書順 の優先度でソートする

本家に取り込まれました。このソート順が嫌だって方は Lingr の vim 部屋へ・・・。



neocomplcache で辞書ファイルから補完候補を表示したい場合は、

g:neocomplcache_dictionary_filetype_lists

を指定する。java 用にクラスとメソッド名を登録したものを指定していてかなり便利。だけれど、補完候補があまり思うように表示されないなぁと前々から思っていた。辞書順(a to z)かと思えばそうでもなく、辞書ファイル(*.dict)の書いてる順番(上から下)っぽいけどそうでも無さそう。
例えば String を入力したくて

St

と打った場合、補完候補に

StringBuffer
String

の順に出ると困る。表示されている補完候補から選べばいいのだけど、そうでない場合は String を全部打ち込まないといけない。

String
StringBuffer

の順に出れば、String と入力したい場合、StringBuffer と入力したい場合のどちらにも対応できる。短い方が先に出るとうれしい。
また、長さが同じ

StringBuffer
StringReader

の様な場合は String に続いて R か B を入力しないといけないのでどっちでもいいのだけれど、辞書順(a to z)に並んだ方が綺麗かなと思う。

候補をソートしてるところ

autoload/neocomplcache.vim

" RankOrder."{{{
function! neocomplcache#compare_rank(i1, i2)
  return a:i2.rank - a:i1.rank
endfunction"}}}

sort を使って辞書をファイルの内容をなめつつ rank を比較するので、登録順っぽくなるけどそうとは限らないことが分かる。

ならここを書き変えればいいのでは

.vim/after/autoload/neocomplcache.vim

" RankOrder."{{{
function! neocomplcache#compare_rank(i1, i2)
  let diff = a:i2.rank - a:i1.rank
  if diff == 0
    let diff = len(a:i1.word) - len(a:i2.word)
    if diff == 0
      return a:i1.word > a:i2.word ? 1 : -1
    endif
  endif
  return diff
endfunction"}}}

実装がアレなのは置いとくとして、、、

ランク > 長さ > 辞書順(a to z)

の順番でソートし直すようにしてみる。加えて、候補はバッファの内容を優先した方が賢くやってくれるので

if !exists('g:neocomplcache_plugin_rank')
  let g:neocomplcache_plugin_rank = {}
endif
let g:neocomplcache_plugin_rank.buffer_complete = 90

としておく。
バッファにのってしまえば候補は賢く優先度を付けてくれるのだけれど、バッファに乗る前も割と思った様に補完してくれてる。今日、いろいろ書いた分に関してはいい感じで動いてる。
てことで、これで様子を見みる。