はじめに
phpファイルの保存時に
- Lint処理(php -l)
- コード整形
- コーディング規約チェック
を行うvimプラグインを作ってみた。
(もうあるかもしれませんが勉強も兼ねて。。。)
Lint or コーディング規約チェックでエラーがあればQuickFixにその内容が表示されます。
ちなみにコード整形はphp-cs-fixerのvimプラグインを使用しています。
コーディング規約はphpcsを裏でたたいている感じです。
公開されているphpcsプラグインもあったのですが、QuickFixただ表示させているだけで、
:ccで飛べなかったので、自作しました。
(見つけられてないだけで、探せばちゃんとしたのがあるかもしれませんが。。。)
phpcsの見た目汚いですが一応:ccでとびます。ファイル名が表示されている番号をccで指定してください。
事前準備
php-cs-fixerとphpcsを使うので、サーバーやVM等に落としておいてください。
一応リンク貼っておきます。Readmeの手順でやれば問題ないです。
php-cs-fixer
https://github.com/FriendsOfPHP/PHP-CS-Fixer
phpcs
https://github.com/squizlabs/PHP_CodeSniffer
phpcsはUbuntuには確かパッケージがあったと思うのでUbuntuの方はパッケージからインストールしてもよいと思います。ご自由にどうぞ。
あとは
php-cs-fixerのvim用のプラグインをインストールしておいてください
https://github.com/stephpy/vim-php-cs-fixer
コード
.vimrcでの設定とプラグインファイルのコードと2つ書きますが、
.vimrcにまとめて全部書いても動くのでご自由にどうぞ
" ---------------------------- php_cs_fixerプラグイン用の設定 ----------------------------
" @see https://github.com/FriendsOfPHP/PHP-CS-Fixer
" If php-cs-fixer is in $PATH, you don't need to define line below
let g:php_cs_fixer_path = "/usr/local/bin/php-cs-fixer" " define the path to the php-cs-fixer.phar
let g:php_cs_fixer_level = "psr2" " which level ?
let g:php_cs_fixer_config = "default" " configuration
"let g:php_cs_fixer_config_file = '.php_cs' " configuration file
let g:php_cs_fixer_php_path = "php" " Path to PHP
" If you want to define specific fixers:
let g:php_cs_fixer_fixers_list = "linefeed,short_tag,indentation"
let g:php_cs_fixer_enable_default_mapping = 1 " Enable the mapping by default (<leader>pcd)
let g:php_cs_fixer_dry_run = 0 " Call command with dry-run option
let g:php_cs_fixer_verbose = 0 " Return the output of command if 1, else an inline information.
" ---------------------------- php_cs用の設定 ----------------------------
let g:php_cs_fixer_use_flg = 1 " もし、php_cs_fixerプラグインを使いたくなければ0にしてください
let g:php_cs_use_flg = 1 " もし、php_csを使いたくなければ0にしてください
let g:php_cs_path = "/usr/bin/phpcs" " phpcsのパスを指定してください
let g:php_cs_standard = g:php_cs_fixer_level " PEARやPSR2等を指定してください
augroup PHP
autocmd!
" 書き込みのプレ処理
autocmd! BufWritePre *.php call PHPPre()
" 書き込みのポスト処理
autocmd! BufWritePost *.php call PHPPost()
" 書き込みのプレ処理
function! PHPPre()
endfunction
" 書き込みのポスト処理
" PHPLint
" コードの整形
function! PHPPost()
" php -lの実行結果を変数に代入
let l:php_lint_result = system('php -l '.bufname('%'))
" No syntax errorsの文字列がmatchするかチェック
let l:php_lint_err_check = matchstr(l:php_lint_result, 'No syntax errors')
" エラーがあるときだけLintの結果を出力する
if len(l:php_lint_err_check) == 0
" 半角スペースごとに配列を分割
let l:error_message_list = split(l:php_lint_result, ' ')
let l:line_flg = 0
let l:line_number = 0
" エラーメッセージからエラーの行数を拾う
" エラーメッセージのlineの後がエラーの行数みたい
for word in l:error_message_list
if l:line_flg == 1
let l:line_number = word
:break
else
if word == 'line'
let l:line_flg = 1
endif
endif
endfor
" QuickFixのリストの末尾にエラーの内容を追加する
let l:qflist = []
call add(l:qflist, {'filename': bufname('%'), 'type': 'i', 'lnum': l:line_number, 'col': 1, 'text': l:php_lint_result})
call setqflist(l:qflist)
" QuickFixを表示
:copen
else
" QuickFixを閉じる
:cclose
" php_cs_fixerを利用してコードを整形
if g:php_cs_fixer_use_flg == 1
call PhpCsFixer()
endif
" phpcsでコードチェック
if g:php_cs_use_flg == 1
call PhpCs()
endif
endif
endfunction
" php_cs_fixerの設定
function! PhpCsFixer()
" @see https://github.com/FriendsOfPHP/PHP-CS-Fixer
:call PhpCsFixerFixFile()
syntax on
endfunction
" php_csの設定
function! PhpCs()
" パスが通っているか確認のため確認用のphpcsコマンドをたたく
let l:check_phpcs = system(g:php_cs_path.' -i 1>/dev/null 2> /dev/null && echo $?')
" phpcsのパスが通っている場合はphpcsでチェック
if l:check_phpcs == 0
set errorformat+=\"%f\"\\,%l\\,%c\\,%t%*[a-zA-Z]\\,\"%m\"\\,%*[a-zA-Z0-9_.-\\,]
" phpcsコマンドをたたく
let l:phpcs_result = system(g:php_cs_path.' --standard='.g:php_cs_standard.' '.bufname('%'))
" phpcsチェックerrorの場合
if l:phpcs_result != ''
let l:i = 0
let l:qflist = []
" phpcsのエラーメッセージを改行ごとにsplit
let l:error_message_list = split(l:phpcs_result, "\n")
for message in l:error_message_list
" エラー内容を表すメッセージは | 行番号 | ERROR or Warning | 内容
" のフォーマットなので、|のある行を探す
let l:match_result = matchstr(message, '|')
if len(l:match_result) > 0
" split_message[0] 行番号
" split_message[1] ERROR or Warning
" split_message[2] 内容
let l:split_message = split(message, '|')
" split_message[0]には半角スペースが含まれるのでtrim
if len(substitute(l:split_message[0], " ","","g")) > 0
call add(l:qflist, {'filename': bufname('%'), 'text': l:split_message[1].l:split_message[2], 'lnum':substitute(l:split_message[0], " ","","g"), 'col': 1})
else
call add(l:qflist, {'filename': "", 'text': l:split_message[2], 'lnum':'', 'col': 1})
endif
endif
endfor
" QuickFixのリストの末尾にエラーの内容を追加する
call setqflist(l:qflist)
" QuickFix open
copen
else
" QuickFix close
cclose
endif
" phpcsのパスが通っていない場合はerror表示
else
echo 'Error! phpcs not found.'
endif
endfunction
augroup END
おわりに
一応g:php_cs_fixer_use_flgやg:php_cs_use_flg値で処理を通過させるさせないを制御できるようにしておきました。
簡単ですが以上です。
もしお役に立てれば幸いです。