VimでLaravelプロジェクトの補完を行う

Tags : Vim   Laravel   Composer  

VimでLaravelプロジェクトの補完を行う方法です。後は、Laravel用のスニペットを追加すればいけるかも知れません。私は、本格的用途にはVimを使用しないため、これ以上、補完には手を入れません。

今回、この目的のために、.vimrcを全部書き換えました。各プラグインの「デフォルト」状態に近いままです。そのうちいじってしまう可能性があるので、今のうちに公開しておきます。

if has('vim_starting')
    set nocompatible               " Be iMproved

    " Required:
    set runtimepath+=~/.vim/bundle/neobundle.vim/
endif

" Required:
call neobundle#begin(expand('~/.vim/bundle/'))

" Let NeoBundle manage NeoBundle
" Required:
NeoBundleFetch 'Shougo/neobundle.vim'

" My Bundles here:

NeoBundle 'Shougo/neocomplete'

NeoBundle 'Shougo/neosnippet'
NeoBundle 'Shougo/neosnippet-snippets'

NeoBundle 'Shougo/vimproc', {
            \ 'build' : {
            \     'windows' : 'make -f make_mingw32.mak',
            \     'cygwin' : 'make -f make_cygwin.mak',
            \     'mac' : 'make -f make_mac.mak',
            \     'unix' : 'make -f make_unix.mak',
            \    },
            \ }

NeoBundle 'Shougo/unite.vim'

NeoBundle 'm2mdas/phpcomplete-extended'
NeoBundle 'm2mdas/phpcomplete-extended-laravel'



" You can specify revision/branch/tag.
" NeoBundle 'Shougo/vimshell', { 'rev' : '3787e5' }

call neobundle#end()

" Required:
filetype plugin indent on

" If there are uninstalled bundles found on startup,
" this will conveniently prompt you to install them.
NeoBundleCheck




" NeoComplete setting
" Use neocomplete.
let g:neocomplete#enable_at_startup = 1
" Use smartcase.
let g:neocomplete#enable_smart_case = 1
" Set minimum syntax keyword length.
let g:neocomplete#sources#syntax#min_keyword_length = 3
let g:neocomplete#lock_buffer_name_pattern = '\*ku\*'
" Define dictionary.
let g:neocomplete#sources#dictionary#dictionaries = {
            \ 'default' : '',
            \ 'vimshell' : $HOME.'/.vimshell_hist',
            \ 'scheme' : $HOME.'/.gosh_completions'
            \ }
" Define keyword.
if !exists('g:neocomplete#keyword_patterns')
    let g:neocomplete#keyword_patterns = {}
endif
let g:neocomplete#keyword_patterns['default'] = '\h\w*'
" Plugin key-mappings.
inoremap <expr><C-g>     neocomplete#undo_completion()
inoremap <expr><C-l>     neocomplete#complete_common_string()
" <CR>: close popup and not CR.
inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
function! s:my_cr_function()
    return pumvisible() ? neocomplete#close_popup() : "\<CR>"
endfunction
" <TAB>: completion.
inoremap <expr><TAB>  pumvisible() ? "\<C-n>" : "\<TAB>"
" <C-h>, <BS>: close popup and delete backword char.
inoremap <expr><C-h> neocomplete#smart_close_popup()."\<C-h>"
inoremap <expr><BS> neocomplete#smart_close_popup()."\<C-h>"
inoremap <expr><C-y>  neocomplete#close_popup()
inoremap <expr><C-e>  neocomplete#cancel_popup()
" Enable omni completion.
autocmd FileType css setlocal omnifunc=csscomplete#CompleteCSS
autocmd FileType html,markdown setlocal omnifunc=htmlcomplete#CompleteTags
autocmd FileType javascript setlocal omnifunc=javascriptcomplete#CompleteJS
autocmd FileType python setlocal omnifunc=pythoncomplete#Complete
autocmd FileType xml setlocal omnifunc=xmlcomplete#CompleteTags
" Enable heavy omni completion.
if !exists('g:neocomplete#sources#omni#input_patterns')
    let g:neocomplete#sources#omni#input_patterns = {}
endif
let g:neocomplete#sources#omni#input_patterns.php = '[^. \t]->\h\w*\|\h\w*::'




" NeoSnippet setting
" Plugin key-mappings.
imap <C-k>     <Plug>(neosnippet_expand_or_jump)
smap <C-k>     <Plug>(neosnippet_expand_or_jump)
xmap <C-k>     <Plug>(neosnippet_expand_target)
" SuperTab like snippets behavior.
imap <expr><TAB> neosnippet#expandable_or_jumpable() ?
imap <expr><TAB> neosnippet#expandable_or_jumpable() ?
            \ "\<Plug>(neosnippet_expand_or_jump)"
            \: pumvisible() ? "\<C-n>" : "\<TAB>"
smap <expr><TAB> neosnippet#expandable_or_jumpable() ?
            \ "\<Plug>(neosnippet_expand_or_jump)"
            \: "\<TAB>"
" For snippet_complete marker.
if has('conceal')
    set conceallevel=2 concealcursor=i
endif




" phpcomplete-extended setting
" Composer command name
let g:phpcomplete_index_composer_command = 'composer'
" PHP omni completion.
autocmd  FileType  php setlocal omnifunc=phpcomplete_extended#CompletePHP

使用しているプラグインです。

  • NeoBundle - プラグイン管理
  • neocomplete - 補完
  • neosnippet - スニペット
  • neosnippet-snippets - 上記データー
  • vimproc - プロセス起動
  • unite.vim - 情報表示・操作
  • phpcomplete-extended - composerプロジェクトの補完
  • phpcomplete-extended-laravel - 上記Laravel用プラグイン

一番最後のプラグインを入れるには?と依存を追っかけて、入れていったのですが、動作しないため、.vimrcを書き換えたわけです。上記上から6つ、残りの2つは同じ作者さんですから、きちんと最新版で入れれば、問題なく動作します。

vimのプラグインの他に、neocompleteが使用している言語Luaをインストールする必要があります。MACで入れる方法は検索すれば見つかるでしょう。Linuxの場合はデフォルトでインストールされていることは無いと思いますが、標準リポに含まれている可能性が高いでしょう。

phpcomplete-extended

Composerプロジェクトからvimを起動すると、先ずcomposer -o dump-autoloadを実行し、それで生成されたオートロード用のファイルから、補完用のインデックスファイルを作成します。Composerの起動コマンドがcomposer.pharがデフォルトです。私はcomposerにリネームしているため、それを指定しています。

ポイントはComposerプロジェクトのルートディレクトリーでvimを起動する必要があることです。

そして、Laravelの場合、ファサードが存在するため、デフォルトではNot Foundでインデックスが作成されません。そのため、Laravel用の拡張が必要となります。

なお、現時点ではPSR-4に対応していないかも知れません。標準のディレクトリー構造以外だと上手く動かないかも知れません。インストールしたてのプロジェクトであれば動作しますが、PSR-4構造で、標準のディレクトリー構造を変更しているプロジェクトでは、インデックスファイル作成時にエラーで止まってしまいます。

unite.vimとの連携

上記の2プラグインは、unite.vimとも連携します。そのため、必須ではありませんがunite.vimを入れておくと便利です。

何が補助されているかは、:Unite sourceで確認してもらえばよいのですが、一覧にしておきます。

  • phpcomplete/files - phpcompleteがインデックスしたファイルの一覧
  • phpcomplete/extends - 指定したクラスを拡張している候補らしいが、使い方は未調査
  • phpcomplete/implements - 指定したクラスを実装している候補らしいが、使い方は未調査
  • phpcomplete/vendors - vendor下の名前空間と対応するディレクトリーの一覧
  • laravel/facades - 認識されているファサード
  • laravel/ioc - iocの登録内容
  • laravel/models - モデル一覧
  • laravel/routes - ルートの一覧

インデックスがすぐに更新されるわけでないため、Laravel関連の情報は、リアルタイムに情報が反映されないようです。情報を更新するには手動でインデックスファイルを再生成する必要があります。今後に期待しましょう。

:PHPCompleteExtendedGenerateIndex
他のプラグイン

日本人の方が作成されています。情報もたくさんあります。検索してください。

デフォルトから変更しているのは、neocompleteで候補をEnterで押した場合に、補完されずに改行されるデフォルト動作から、補完し、その文字列の後にカーソルが移るだけの動作にしています。(neocompleteのReadmeのコメントで説明されている内容そのままです。)

注意点

最初のチャレンジでは上手く行かず、時間が取られました。

結局、一度マシンを落とし、後ほど再チャレンジした時点で、上手く動作するようになっていました。

もし、上手く行かない場合、再起動はいつでも早めに試してみる価値のある一手です。その間、コーヒーでも一杯、いかがでしょうか?