hamakou108 blog

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

December 20, 2020

この記事は 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 でした。

Written by Kosuke Hamada. You should follow him on Twitter

© 2021, Built with Kosuke Hamada