Input中心のブログ

efm-langserverの設定について今更ながらやってみた(Go言語)

November 19, 2019

efm-langserverが出たときにめっちゃ便利そうやんーと思っていたんですが、色々ハマったりして時間もなかったのでしばらく放置していましたが、ついに設定してみました。

efm-langserverとは

General purpose Language Server that can use specified error message format generated from specified command. This is useful for editing code with linter.

efm-langserverは特定のコマンドから生成されるエラーメッセージに特化したLanguage Serverです。 例えばlinterとかが例に入ります。

導入例

efm-langserverを導入する利点は以下のような点が挙げられると思います。

  • 言語のLSが存在しないが、Linterは存在する場合
  • LSはあるが、Linterを使いたい場合

1つ目の利用方法はefm-langserverのREADMEを見てもらえば出来ると思うので、今回は下について考えながら設定していきたいと思います。

なぜefm-langserverを利用するか?

linterのエラーを出力するプラグインとしてはALEが有名だと思います。 ALEはすごく便利なプラグインで、Linterさえ導入すればVimにエラー文などを出力してくれます。 しかし、便利な反面プラグインとして大きすぎるという欠点があります。

そこで今回はvim-lspだけで全てが完結するような設定を目指します。

早速設定

今回はGo言語の利用例について考えながらやります。 Go言語ではgoplsというLanguage Serverを使います。 また、efm-langserverで使うlinterとしてgolintを使用します。

早速設定

if executable('gopls')
    au User lsp_setup call lsp#register_server({
        \ 'name': 'go',
        \ 'cmd': {server_info->['gopls']},
        \ 'whitelist': ['go'],
        \ 'workspace_config': {'gopls': {
        \     'usePlaceholders': v:true,
        \     'completeUnimported': v:true,
        \   }},
        \ })
endif

if executable('efm-langserver')
  augroup LspEFM
    au!
    autocmd User lsp_setup call lsp#register_server({
        \ 'name': 'efm-langserver',
        \ 'cmd': {server_info->['efm-langserver', '-c='.$HOME.'/.config/efm-langserver/config.yaml', '-log='.g:log_files_dir.'/efm-langserver.log']},
        \ 'whitelist': ['go'],
        \ })
  augroup END
endif

1つ目がgoplsの設定で2つ目がefm-langserverの設定です。

そして、~/.config/efm-langserver/config.yamlに以下のような設定を行います。

languages:
  go:
    lint-command: 'golint -set_exit_status=1'
    lint-formats:
      - '%f:%l:%c:%m'

これで両立可能です! 以下の画像が実際の様子です。 関数のHellohelloがタイポしているので起こっているエラーがgoplsのエラーです。 Helloという公開関数に対してコメントを書きなさいと怒られているエラーがgolintのエラーです。 ちゃんと設定できてますね!

efm langserver

これで終わりでもいいのですが、efm-langserverについての補足を少しだけします。

linterのexitステータスは1である必要がある

efm-langserverはexistステータスに以上がある場合にエラーをlinterの内容を出力する設定になっています。 golintは何故かexitステータスがデフォルトだと0になるようになっているみたいなので、-set_exit_status=1というように指定する必要があります。

lint-formatsを設定する

lint-formatsはefm-langserverの設定でデフォルトだと、%f:%l:%m%f:%l:%c:%mの2つが設定されています。 この2つでパースするとgolintは両方の設定に成功してしまします。 そして、Diagnosticsが2つ送られて来てしまい、Diagnosticsが2つ存在してしまいます。 なので、lint-formats:で正しい方のフォーマットを指定しました。

ちなみに、エラーformatはVimのエラーフォーマット構文を使っているみたいなので、こちらを参考にしてください。

まとめ

goでgoplsの他にgolintのエラーも出るようになった!

( 2019/12/06 追記

11月末に取り込まれた変更によってexitステータスが0でも行けるようになりました。 その場合以下のような設定でいけます。

languages:
  go:
    lint-command: 'golint'
    lint-ignore-exit-code: true
    lint-formats:
      - '%f:%l:%c:%m'