yomi322 さんの neco-tweetvim に neocomplete 版の source を追加しました。
@ の後で screen name の補完、# の後で tag の補完をします。
neocomplete/sources/tweetvim_name_complete.vim
let s:source = { \ 'name' : 'tweetvim_name_complete', \ 'rank' : 200, \ 'kind' : 'manual', \ 'filetypes' : { 'tweetvim_say' : 1 }, \ } function! s:source.get_complete_position(context) return neocomplete#tweetvim#get_complete_position( \ a:context, '@', g:neocomplete#auto_completion_start_length) endfunction function! s:source.gather_candidates(context) return neocomplete#tweetvim#gather_candidates(a:context, 'screen_name') endfunction function! neocomplete#sources#tweetvim_name_complete#define() return s:source endfunction
継承をいい感じで使えるといいんですけど、案が浮かばなかったので screen_name と tag 共通のものを別にくくり出す方式で。
対象の source と、補完位置 (get_complete_position) と、候補を返す (gather_candidates) というのを実装すれば OK。
neocomplete/tweetvim.vim
screen_name と tag の共通部分。
function! neocomplete#tweetvim#get_complete_position(context, char, start) let col = col('.') let pos = 0 while 1 let idx = stridx(a:context.input, a:char, pos + 1) if idx == -1 || idx >= col break endif let pos = idx endwhile let pos = matchend(a:context.input, a:char, pos) let text = eval("a:context.input[" . string(pos) . ":" . string(pos + a:start) . "]") let text = substitute(text, ' ', '', 'g') let pos = len(text) < a:start ? -1 : pos return pos endfunction function! neocomplete#tweetvim#gather_candidates(context, key) let cache_key = 'keywords_' . a:key if !exists('s:' . cache_key) let s:[cache_key] = map(tweetvim#cache#get(a:key), \ "{ 'word' : v:val, 'menu' : '[tweetvim]' }") endif "return filter(copy(get(s:, cache_key)), 'v:val.word =~ "' . a:context.complete_str . '"') return copy(get(s:, cache_key)) endfunction
@ or # より後ろにカーソルがあって、一定の長さ (g:neocomplete#auto_completion_start_length) 以上なら補完候補を返す (返しているつもり)。
source.kind が manual の場合は入力のたびに get_complete_position が呼ばれるって理解でいいんだろうか。このへんがよく分からんかった。get_complete_position が -1 以外を返すまでは呼ばれるって動きだろうか。
あとは、plugin 側で絞るべきなのか neocomplete に絞ってもらうのか、どちらが良いのかよく分からなかったので、ユーザ定義の matcher で絞ってもらうように、plugin 側では特に絞らずに返却。文脈にそって絞って欲しい場合は plugin 側で filter すべきなんだろうな、きっと。
まぁ、if_lua 化によって多少の無茶は許されるはず・・・と(ちがう)。
まとめ
わざわざ plugin を作らなくても、候補の dictionary があるのなら
if !exists('g:neocomplete#sources#dictionary#dictionaries') let g:neocomplete#sources#dictionary#dictionaries = {} endif let g:neocomplete#sources#dictionary#dictionaries.tweetvim_say = $HOME . '/.tweetvim/screen_name'
とするだけで良いのであった。