この記事は Vim Advent Calendar 2019 向けに書かれました。
もう一つネタがあって記事を書いていたのですが、
なんか微妙な出来だったので Advent Calendar とは別として投稿しようかなと思っています。
はじめに
この記事は
- Vim を使っている
- vim-lsp を使っている
- TypeScript を書いている
- prettier/eslint を連携させたい!
な人向けの記事です。
本題
vim-lsp を使って TypeScript の開発をしているならば、
使っている言語サーバは typescript-language-server
ではありませんか?
よく出来ていますよね。快適です。
しかし、自分は下記の点が物足りませんでした。
Prettier でフォーマットできない
今どきのフロントエンドの現場であれば、Prettier を使うことが多いと思います。
当然ながら typescript-language-server
によるフォーマットは Prettier によるそれではありません。
eslint のエラーが検出できない
typescript-language-server
を使えば型エラーが即座にわかります。最高!
しかし、動作するコードでも lint を通らなければコミットはできません。
コードを書いている最中に unfixable な eslint エラーを知れたら嬉しいですよね。
解決方法
efm-langserver
、もしくは diagnostic-languageserver
を利用しましょう。
これらは linter/formatter などの CLI ツールを、LSP のインターフェースでラップしてくれる言語サーバです。
つまり、vim-lsp
から eslint
などを利用できるようになります。
しかし、はっきりいって設定はちょっと難しいです。
そのため、ここに eslint
向けの設定を書いてしまいます。
prettier
は eslint --fix
経由で実行することとしましょう。
eslint
経由で prettier
を走らせる方法は他の記事をご参照ください。
設定方法
diagnostic-languageserver のインストール
npm i -g diagnostic-languageserver
eslint_d のインストール
npm i -g eslint_d
※ これを入れると、リントのパフォーマンスが劇的に向上します。
vim-lsp に設定を追加
autocmd! vimrc User lsp_setup call lsp#register_server({
\ 'name': 'diagnostic-languageserver',
\ 'cmd': { info -> ['diagnostic-languageserver', '--stdio'] },
\ 'whitelist': [
\ 'typescript',
\ 'typescript.tsx',
\ 'typescriptreact',
\ 'javascript',
\ 'javascript.jsx',
\ 'javascriptreact',
\ ],
\ 'initialization_options': {
\ 'linters': {
\ 'eslint': {
\ 'sourceName': 'eslint',
\ 'command': 'eslint_d',
\ 'args': ['--stdin', '--stdin-filename=%filename', '--no-color'],
\ 'rootPatterns': ['.eslintrc', '.eslintrc.js'],
\ 'formatLines': 1,
\ 'formatPattern': [
\ '^\s*(\d+):(\d+)\s+([^ ]+)\s+(.*?)\s+([^ ]+)$',
\ {
\ 'line': 1,
\ 'column': 2,
\ 'message': [4, ' [', 5, ']' ],
\ 'security': 3
\ }
\ ],
\ 'securities': {
\ 'error': 'error',
\ 'warning': 'warning'
\ },
\ },
\ },
\ 'filetypes': {
\ 'javascript': 'eslint',
\ 'javascript.tsx': 'eslint',
\ 'javascriptreact': 'eslint',
\ 'typescript': 'eslint',
\ 'typescript.tsx': 'eslint',
\ 'typescriptreact': 'eslint',
\ },
\ 'formatters': {
\ 'eslint': {
\ 'rootPatterns': ['.eslintrc', '.eslintrc.js'],
\ 'command': 'eslint_d',
\ 'args': ['--fix', '--fix-to-stdout', '--stdin', '--stdin-filename=%filename'],
\ 'isStdout': v:true,
\ 'isStderr': v:true,
\ }
\ },
\ 'formatFiletypes': {
\ 'javascript': 'eslint',
\ 'javascript.tsx': 'eslint',
\ 'javascriptreact': 'eslint',
\ 'typescript': 'eslint',
\ 'typescript.tsx': 'eslint',
\ 'typescriptreact': 'eslint'
\ }
\ }
\ })
※ 完全におまじないですね。
※ diagnostic-languageserver 向けの設定しか提供できず悔しいです。
※ efm-langserver に関しても設定をいろいろ試している最中です。うまく動いたら移行予定だし、記事を書きます!
vim-lsp でフォーマットする
eslint
のエラーは勝手に表示されますが、フォーマットは下記のコマンドを実行する必要があります。
:LspDocumentFormat
まとめ
これで vim-lsp
を利用して、
- TypeScript の賢い補完や型チェック、定義ジャンプを利用する
- 合わせて、eslint による lint 結果を表示する
- Prettier でフォーマットをかける
をすべて同時に満たすことができます。
vim-lsp は一つの filetype に複数の言語サーバを走らせることが可能で、強みです。
これに対応しているのは、coc.nvim
と vim-lsp
くらいしか知りません。
この設定を行って快適なフロントエンド開発をやっていきましょう!
以下、ハマった点など
TypeScript/JavaScript 両方への対応
eslint
に STDIN 経由でファイルを渡した場合、そのテキストが TypeScript なのか JavaScript なのか eslint
さんには判別できません。
そのため、--stdin-filename
にファイル名を渡してやる必要がありました。
eslint
を毎回起動してるとめちゃくちゃ遅いし重い問題への対応
最初、eslint_d
を使わずに設定をしていましたが、死ぬほど遅かったです。
いろいろ調査していると、eslint_d
というものを見つけて組み合わせて解決しました。