hamakou108 blog

PHP Conference Japan 2020 に「PHPer のための Vim 実践入門」というテーマで登壇した

Cover Image for PHP Conference Japan 2020 に「PHPer のための Vim 実践入門」というテーマで登壇した

この記事は Vim 2 Advent Calendar 2020 の20日目です。

12/12 に PHP Conference Japan 2020 に LT で登壇させていただいた。

19:06 辺りから。

PHPer のための Vim 実践入門 - Speaker Deck

テーマは「PHPer のための Vim 実践入門」ということで、かなり Vim に振り切った内容で話した。 時間の都合上 Plugin の紹介までしかできず、具体的な設定については殆ど触れていなかったので、今回は現時点での自分の dotfiles を紹介したいと思う。

リポジトリ

dotfiles は以下のリポジトリにまとめている。

hamakou108/dotfiles

README に雑に書いてあるが、まるっと設定を流用したい場合はリポジトリを clone して以下のスクリプトを実行する。

./bin/link.sh

このスクリプトは単にリポジトリ内の各設定ファイルへの symlink をホームディレクトリ等に作成する。 一応、既存の設定ファイルを上書きを避けるようにスクリプトを書いている(が、利用は自己責任で)。

また Vim の実装としては Neovim を利用しており、プラグインには Python と Node.js の neovim パッケージに依存しているものがある。 それぞれ環境を用意した上で、パッケージをインストールする。

pip install pynvim
npm install neovim

Plugins

プラグイン管理には dein.vim を利用している。 このプラグインの設定方法に関しては結構情報が多く、記事の趣旨から逸れそうなので割愛。

LSP

LSP 互換の開発補助プラグインは coc.nvim を使用しており、 PHP 開発用途として coc-phplscoc-snippets も使用している。 今回の登壇資料を準備している最中に知ったが、 Neovim の LSP Client は Neovim 本体の LSP [^1] 、 coc.nvim 、 vim-lsp の三国志時代になっているそうだ。 今後の展開から目が離せない。

Intelephense のライセンスキーの設定

登壇では言及していなかったが、実は coc-phpls をそのまま導入するだけでは PHP の補完機能をフルで利用することができない。 coc-phpls が裏で呼び出している Intelephense という Language Server は自動補完や定義ジャンプといった主要機能のみ無料で利用可能としており、シンボルのリネームなどの一部機能は有料 [^2] での提供となっている。 自分の場合はこのライセンスを購入しており、以下の環境変数に設定したライセンスキーの値を読む設定を行っている。

export PHP_INTELEPHENSE_LICENCE_KEY='YOUR_LICENCE_KEY'

あるいはもっと簡単な方法として以下のように coc-settings.json に記述することもできる。

PHP Intelephense の有償版を Neovim で使ってみる - Qiita

ただし自分のように dotfiles を公開している場合はライセンスキーもそのまま晒すことになるので、この方法は避けるべき。

キーマッピング

coc.nvim が紹介しているキーマッピング例はそのままだと他のプラグインに割り当てるキーマッピングとバッティングする可能性があったので少し変更している。 自分の場合は deris さんのキーマッピングに関する考察を参考に <Space> + [a-z] でプラグインの機能を呼び出すルールを採用しており、以下のように <Space> + c で coc の機能を呼び出すようにしている。

let mapleader = "\<Space>"
nnoremap [coc] <Nop>
nmap <Leader>c [coc]

" Show all diagnostics.
nnoremap <silent><nowait> [coc]a :<C-u>CocList diagnostics<cr>
" Manage extensions.
nnoremap <silent><nowait> [coc]e :<C-u>CocList extensions<cr>
" Show commands.
nnoremap <silent><nowait> [coc]c :<C-u>CocList commands<cr>
" Find symbol of current document.
nnoremap <silent><nowait> [coc]o :<C-u>CocList outline<cr>
" Search workspace symbols.
nnoremap <silent><nowait> [coc]s :<C-u>CocList -I symbols<cr>
" Do default action for next item.
nnoremap <silent><nowait> [coc]j :<C-u>CocNext<CR>
" Do default action for previous item
nnoremap <silent><nowait> [coc]k :<C-u>CocPrev<CR>
" Resume latest coc list.
nnoremap <silent><nowait> [coc]p :<C-u>CocListResume<CR>

File Tree

ファイルツリーのプラグインは defx.nvimdefx-iconsdefx-git を使用している。

defx-icon でアイコンを表示するには Nerd Font が必要。 Mac の場合は Homebrew でインストールして、ターミナルのフォントに設定することで利用できる。

brew tap homebrew/cask-fonts
brew cask install font-hack-nerd-font

またキーマッピングは <Space> + f を設定している。 基本的にはドキュメントにあるキーマッピング例をそのまま利用していますが、以下のようにファイルツリーの開き方に応じて幾つかコマンドを用意しておくと便利。

nnoremap [defx] <Nop>
nmap <Leader>f [defx]
nmap <silent> [defx]c :<C-u>Defx -columns=git:icons:filename:type `expand('%:p:h')` -search=`expand('%:p')`<CR>
nmap <silent> [defx]r :<C-u>Defx -columns=git:icons:filename:type<CR>

Test

テストのプラグインは vim-test を使用している。 こちらはテストランナーも自動で検知してくれる素晴らしいプラグインで、あまり多くの設定を書く必要はない。

キーマッピングは <Space> + t を設定している。 テストスコープごとにキーマッピングを割り当てている。

nnoremap [vim-test] <Nop>
nmap <Leader>t [vim-test]
nmap <silent> [vim-test]n :TestNearest<CR>
nmap <silent> [vim-test]f :TestFile<CR>
nmap <silent> [vim-test]s :TestSuite<CR>
nmap <silent> [vim-test]l :TestLast<CR>
nmap <silent> [vim-test]v :TestVisit<CR>

Git

Git のプラグインは vim-gitgutterfugitive.vimgv.vim を使用している。

キーマッピングは <Space> + g を設定している。 ただ Git 系の機能は比較的呼び出し頻度が高く、もっと少ないタイプで呼び出せるようにしたいと思っている。 例えば hunk の diff を見るためだけに <Space> + g + h + p と4つのキーを打つ必要があるので、ちょっとイケてない。

個々の機能の呼び出しのキーマッピングは Woody さんの Git プラグイン紹介を参考に以下のように設定している。

nnoremap [git] <Nop>
nmap <Leader>g [git]

" vim-gitgutter
nmap [git]hs <Plug>(GitGutterStageHunk)
nmap [git]hu <Plug>(GitGutterUndoHunk)
nmap [git]hp <Plug>(GitGutterPreviewHunk)

" fugitive.vim
nmap <silent> [git]a :<C-u>Gwrite<CR>
nmap <silent> [git]b :<C-u>Gblame<CR>
nmap <silent> [git]c :<C-u>Gcommit<CR>
nmap <silent> [git]d :<C-u>Gvdiff<CR>
nmap <silent> [git]f :<C-u>Gfetch<CR>
nmap <silent> [git]g :<C-u>Ggrep
nmap <silent> [git]m :<C-u>Gmerge
nmap <silent> [git]p :<C-u>Gpush<CR>
nmap <silent> [git]r :<C-u>Grebase -i<CR>
nmap <silent> [git]s :<C-u>Gstatus<CR>

" gv.vim
nmap <silent> [git]la :<C-u>GV<CR>
nmap <silent> [git]lc :<C-u>GV!<CR>

終わりに

PHP Conference Japan 2020 で披露した Vim 拡張の具体的な設定内容について紹介した。 登壇の最後に「LSP と Plugins を駆使すれば Vim でも PHP の開発は十分可能」と発言したが、 PhpStorm などと比較するとまだまだ改善の余地はあるのでこれからも拡張を続けたい。 プラグイン自作が必要な匂いもしてきたので、来年は小さなものから開発に挑戦しようかな...という気持ち。

また公式な場での登壇は今回が初めてだったが、参加者同士のコミュニケーション用に開設されていた Discord チャンネル上では思ったよりも反響があって非常に嬉しかった。 今後も( Vim に限らず)参加者の方に面白いと思ってもらえるようなプレゼンをしていきたい。

あと蛇足になりますが、今回の登壇資料の作成には Marp という Markdown からスライドを生成するツールを使用した。 スライド中にプラグインや参考サイトはリンクとして作っておいたが、今回の記事を書く際にそれらをそのままコピペすることができ、意図せず非常に重宝した。 今後も積極的に使っていこうかなと思う 😎

[^1]: 2020年12月19日時点では nightly [^2]: 2020年12月19日時点で ¥1,200