Open3

Vimのビルトイン補完をぜんぶ動かして候補をまとめられるかと思ったけど無理だった

kawarimidollkawarimidoll

https://zenn.dev/kawarimidoll/articles/62029b8be10ac9

ここで補完をフォールバックできるようにしたので「各補完を表示させて、候補を集めて、一つの補完ウィンドウにまとめて出せばよいのでは?」と思ったけど無理だった
途中でfeedkeysを挟むため普通のcompletefuncの仕組みに乗せることができない

頑張ったのがこれ

let s:sid = expand("\<SID>")
let s:cmp_list = []

function! s:start() abort
  let s:cmp_list = []
  call feedkeys($"\<c-x>\<c-f>\<cmd>call {s:sid}f_cmp()\<cr>", 'ni')
endfunction

function! s:f_cmp() abort
  let file_items = complete_info(['items']).items
  call map(file_items, "{'word':v:val.word, 'menu':'file'}")
  call extend(s:cmp_list, file_items)
  if &filetype == 'vim'
    call feedkeys($"\<c-x>\<c-z>\<c-x>\<c-v>\<cmd>call {s:sid}v_cmp()\<cr>", 'ni')
  else
    call feedkeys($"\<c-x>\<c-z>\<c-x>\<c-o>\<cmd>call {s:sid}o_cmp()\<cr>", 'ni')
  endif
endfunction

function! s:v_cmp() abort
  let vim_items = complete_info(['items']).items
  call map(vim_items, "{'word':v:val.word, 'menu':'vim'}")
  call extend(s:cmp_list, vim_items)
  call feedkeys($"\<c-x>\<c-z>\<c-x>\<c-o>\<cmd>call {s:sid}o_cmp()\<cr>", 'ni')
endfunction

function! s:o_cmp() abort
  let omni_items = complete_info(['items']).items
  call map(omni_items, "{'word':v:val.word, 'menu':'omni'}")
  call extend(s:cmp_list, omni_items)
  call feedkeys($"\<c-x>\<c-z>\<c-x>\<c-k>\<cmd>call {s:sid}k_cmp()\<cr>", 'ni')
endfunction

function! s:k_cmp() abort
  let dict_items = complete_info(['items']).items
  call map(dict_items, "{'word':v:val.word, 'menu':'dict'}")
  call extend(s:cmp_list, dict_items)
  call feedkeys($"\<c-x>\<c-z>\<c-x>\<c-u>", 'ni')
endfunction


function! Completefunc(findstart, base) abort
  if a:findstart
    return mi#cmp#findstart()
  endif
  return s:cmp_list
endfunction

set completefunc=Completefunc
inoremap <c-x><c-u> <cmd>call <sid>start()<cr>

kawarimidollkawarimidoll

vimの関数補完が(終わりで表示されるのでオートクローズできないかと思ったけど無理だった

  function! s:auto_close_paren() abort
    if slice(get(v:completed_item, 'word', ''), -1) ==# '('
      call feedkeys(")\<left>", 'ni')
    endif
  endfunction
  autocmd CompleteDone * call s:auto_close_paren()

なぜかというと一つ候補を選択した段階でCompleteDoneが発火してキーが入力され補完が終了してしまうため2番目以降の候補を選択することができない

kawarimidollkawarimidoll

辞書キーワード補完をomnifunc的にできるかと思ったけど無理だった

function! mi#cmp#dict_completefunc(findstart, base) abort
  if a:findstart
    return mi#cmp#findstart()
  endif

  let base = substitute(s:cmp_info.lastword, "'", "''", 'g')

  let compl_list = mi#cmp#dict_keywords()

  " if empty(base)
    return compl_list
  " endif

  " Filter the list based on the first few characters the user entered
  " return filter(deepcopy(compl_list), "v:val =~# '^" . escape(base, '\\/.*$^~[]') . ".*'")
endfunction

function! mi#cmp#dict_keywords() abort
  if exists('s:dict_keywords_cache')
    return s:dict_keywords_cache
  endif
  let dict_path_list = split(&dictionary, ',')
  let keywords = []
  for dict_path in dict_path_list
    try
      let lines = readfile(dict_path)
      call extend(keywords, map(lines, "{'word':v:val, 'menu':'dk-" .. dict_path->substitute('.*/', '', '') .. "'}"))
    catch
      echomsg v:exception
    endtry
  endfor
  call uniq(sort(keywords))
  let s:dict_keywords_cache = keywords
  return s:dict_keywords_cache
endfunction

表示はできたのだが絞り込みが遅くて使用に耐えなかった