Vim - vim-lsp で Typescript 開発環境を構築する
tips vim · lsp · typescript
Language server + Vim 8.1 + vim-lsp 構成で Typescript 向けの開発環境を構築した時の作業ログ
コード補完やフォーマットなどの開発支援を受けられる環境を構築する

注意 (2020-01-07 追記)
先日(2019-12-25)、[prabirshrestha/vim-lsp] のメンテナでもある mattnさん が vim-lsp の導入を補助する プラグイン mattn/vim-lsp-settings を公開されました。
書いた。 / “vim-lsp の導入コストを下げるプラグイン vim-lsp-settings を書いた。 - Qiita” https://t.co/uM6OGZ6j2Q
— mattn (@mattn_jp) December 24, 2019
当記事にて触れている内容のほとんどは このプラグイン を導入することで、自動で解決できます。vim-lsp-settings をキーワードにこの記事にたどり着く方が一定数いらっしゃる様です。その方々は、mattnさんの 記事 を参照ください。
なお、vim-lsp の設定を自前で管理したい。という方には役にたつ内容もあるかも?しれません。
モチベーション
ここ最近のお仕事は主に Golang で CLIツール やら WebAPI を書いている。 開発環境を色々と試した結果、 Vim 8.1 + golang.org/x/tools/cmd/gopls 1 + [prabirshrestha/vim-lsp] で落ち着いた。
これを機に 趣味で Typescript を書く際にも Vim で開発したなったので環境を構築してみた。
なお、基本的には vim-lsp/wiki に記載されている内容を参考にしている。
language server のインストール
世の中には Typescript 向けの language-server 実装は複数ある。 microsoft.github.io のimplementers/servers によると、 以下の2つが候補だろうか
実装内容に若干の差はある様だが、とりあえず深入りせず、 vim-lsp/wiki にておすすめされている theia-ide/typescript-language-server を導入してみる。 npm にて導入が可能とのことなので、以下でグローバルにインストール:
$ npm install -g typescript typescript-language-server
インストールが成功すると、 tsserver コマンドおよび typescript-language-server コマンドが実行可能となっているはず。
micheam:~$ which tsserver
/usr/local/bin/tsserver
micheam:~$ which typescript-language-server
/usr/local/bin/typescript-language-server
micheam:~$ typescript-language-server --version
0.3.8
language server の登録
Language server が実行可能となったので、クライアント (Vim) 側の設定に入る。 前述の通り、今回は language server client に vim-lsp を採用している。
vim-plug での管理の場合 .vimrc に追加の上、 :PlugInstall を実行:
" .vimrc
Plug 'prabirshrestha/async.vim'
Plug 'prabirshrestha/vim-lsp'
Plug 'prabirshrestha/asyncomplete.vim'
Plug 'prabirshrestha/asyncomplete-lsp.vim'
続いて、 vim-lsp に対して language server を登録する。 .vimrc に記述しても良いが、今回は 他の language server 設定とまとめて管理したかったので プラグインとして切り出した。 micheam/vim-lsp-settings アーカイブ済み 2020-01-07追記
" 一部を抜粋
if executable('typescript-language-server')
    augroup LspTypeScript
        au!
        autocmd User lsp_setup call lsp#register_server({
                    \ 'name': 'typescript-language-server',
                    \ 'cmd': {server_info->[&shell, &shellcmdflag, 'typescript-language-server --stdio']},
                    \ 'root_uri':{server_info->lsp#utils#path_to_uri(lsp#utils#find_nearest_parent_file_directory(lsp#utils#get_buffer_path(), 'tsconfig.json'))},
                    \ 'whitelist': ['typescript'],
                    \ })
        autocmd FileType typescript setlocal omnifunc=lsp#complete
    augroup END :echomsg "vim-lsp with `typescript-language-server` enabled"
else
    :echomsg "vim-lsp for typescript unavailable"
endif
ちなみに
vim-lsp/wiki では vim-lsp-typescript という、 typescript language server を vim-lsp に自動登録するプラグイン を導入することがおすすめされているようだ。 私自身は、言語ごとの設定を1 箇所にまとめたかったので、自前で設定することとした。
動作の確認
ここまで設定を行うと、以下のGIFにあるようなコード補完やフォーマットが可能となる。
(再掲)

README によると、theia-ide/typescript-language-server は lsp で規定されている全ての機能を実装済みとのこと。

そのため、 vim-lsp で定義されているコマンドを実行するか、好みのキーにマッピングするのが良いだろう。
Vim-lsp の提供するコマンド
:h vim-lsp-commands から抜粋して意訳したものを一応記載しておくが、
詳細については vim-lsp#suported-commands もしくは Vimヘルプ を参照のこと。
| コマンド | 概要 | 
|---|---|
| :LspCodeAction | ファイル修正のために適用可能なコマンドのリストを取得する(quick fix) | 
| :LspDocumentDiagnostics | カレントドキュメントを診断する | 
| :LspDeclaration | 宣言に移動する | 
| :LspDefinition | 定義に移動する | 
| :LspDocumentFormat | ドキュメント全体をフォーマットする | 
| :LspDocumentFormatSync | LspDocumentFormatと同じ。ただし処理が終了するまで操作をブロックする | 
| :LspDocumentRangeFormat | 選択範囲をフォーマットする | 
| :LspDocumentSymbol | カレントドキュメント内のシンボルを取得する | 
| :LspHover | hover 情報を取得し、プレビューウィンドウに表示する | 
| :LspNextError | 次の診断エラーにジャンプする | 
| :LspNextReference | カーソル下のシンボルの次の参照へジャンプする | 
| :LspPreviousError | 前の診断エラーにジャンプする | 
| :LspPreviousReference | カーソル下のシンボルの前の参照へジャンプする | 
| :LspImplementation | インターフェースの全ての実装を捜索する | 
| :LspReferences | 全ての参照を捜索する | 
| :LspRename | シンボルをリネームする | 
| :LspTypeDefinition | 型の定義へ移動する | 
| :LspWorkspaceSymbol | ワークスペース内のシンボルを検索し表示する | 
| :LspStatus | 登録済み language server 全てのステータスを表示する | 
コマンドのキーマッピング
特によく使うコマンドのマッピング例を以下に記載する。ここら辺は各人のお好みで。
nmap <buffer> <F12> <Plug>(lsp-definition)
nmap <buffer> <C-]> <Plug>(lsp-definition)
nmap <buffer> K <Plug>(lsp-hover)
nmap <buffer> <C-n> <plug>(lsp-next-error)
nmap <buffer> <C-p> <plug>(lsp-previous-error)
nmap <buffer> <S-F12> <plug>(lsp-references)
nmap <buffer> <S-F6> <plug>(lsp-rename)
nmap <buffer> =- <plug>(lsp-document-format)
nmap <buffer> <F11> <plug>(lsp-implementation)
nmap <buffer> <F2> <plug>(lsp-type-definition)
以下に置いてある
micheam/vim-lsp-settings/ftplugin/typescript.vim アーカイブ済み 2020-01-07 追記
おわり
- 
ちなみに、Bingoの作者 が拡張した機能拡張バージョンを使用している。(早く本体に取り込まれたらいいのに) [prabirshrestha/vim-lsp]: https://github.com/prabirshrestha/vim-lsp ↩︎