Как заставить работать автокомплит и сниппеты в виме?

Для автокомплита использую YouCompleteMe, а для сниппетов vim-snipmate. Хочется повесить оба плагина на Tab, что-бы был какой-то "умный" перебор вариантов. Если есть сниппет, то пишем сниппет, если нет, то листаем автокомплит.
Подскажите, можно ли такое реализовать?
  • Вопрос задан
  • 1018 просмотров
Решения вопроса 1
Такое совмещение можно получить в связке neocomplete.vim + ultisnips.

Для neocomplete нужен Vim собранный с поддержкой Lua (почему выбран Lua объясняется здесь). Сборка и компиляция под Linux вполне обычное и не сложное дело, а для Windows можно найти готовую сборку с актуальной версии билда (1, 2, 3 и сам Lua). UltiSnips требует поддержки python, причем вроде только 2-й версии.

При настройке neocomplete нужно добавить ultisnips в качестве источника:
let g:neocomplete#sources = {
  \ '_':          ['buffer', 'file/include'],
  \ 'javascript': ['omni', 'file/include', 'ultisnips', 'tag']
  \}

И сделать так, чтобы поиск в нем начинался с первого символа, а найденное для наглядности было всегда сверху:
call neocomplete#custom#source('ultisnips', 'rank', 100)
call neocomplete#custom#source('ultisnips', 'min_pattern_length', 1)

Если для ручного автодополнения используется Tab, то советую воспользоваться функцией, которая позволит сохранить обычную работу Tab'а с учетом наличия строк и пробелов:
inoremap <silent> <Tab> <C-r>=<SID>neoComplete("\<Tab>")<CR>
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<C-x>\<C-o>"

function! s:neoComplete(key)
  if pumvisible()
    return "\<C-n>"
  endif
  let [curPos, lineLength] = [getcurpos()[4], col('$')]
  let isText = curPos <= lineLength
  let isStartLine = curPos <= 1
  let isBackspace = getline('.')[curPos-2] =~ '\s'
  if isText && !isStartLine && !isBackspace
      return neocomplete#helper#get_force_omni_complete_pos(neocomplete#get_cur_text(1)) >= 0
          \ ? "\<C-x>\<C-o>\<C-r>=neocomplete#mappings#popup_post()\<CR>"
          \ : neocomplete#start_manual_complete()
  endif
  return a:key
endfunction

Для раскрытия сниппетов UltiSnips советую использовать почти аналогичную функцию: (пример с тильде)
inoremap <silent> ` <C-r>=<SID>ultiComplete("\`")<CR>
xnoremap <silent> ` :<C-u>call UltiSnips#SaveLastVisualSelection()<CR>gvs
snoremap <C-c> <Esc>

function! s:ultiComplete(key)
  if len(UltiSnips#SnippetsInCurrentScope()) >= 1
    let [curPos, lineLength] = [getcurpos()[4], col('$')]
    let isBackspace = getline('.')[curPos-2] =~ '\s'
    let isStartLine = curPos <= 1
    let isText = curPos <= lineLength
    if isText && !isStartLine && !isBackspace
      return UltiSnips#ExpandSnippet()
    endif
  endif
  return a:key
endfunction

В UltiSnips вроде имеется поддержка сниппетов в формате SnipMate, а кроме этого указывается что плагин работает с YouCompleteMe. Но этого я давно не проверял, считая на сегодня плагин YouCompleteMe — излишним нагромождением, а SnipMate вовсе мертвым, авторы которого когда-то так и не смогли договориться, кто кого должен форкнуть.

При необходимости дополню ответ. Но можно просто посмотреть как это сделано у меня.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы