goplsをdaemon化して使う

普段コードは vim + vim-lsp で書いていて Go を書く時は language server として gopls を使っている。

engineering.mercari.com

このイベントに参加した時に gopls が daemon で起動できるのを知って、今回 Macdaemon 化して使用することにした。

公式のdaemonについてのドキュメントはこちら

github.com

ドキュメントにあるようにホスト側は下記のようなコマンドで起動する。

$ gopls -listen=:37374 -logfile=auto -debug=:0

エディタ側は下記のようなコマンドで先ほど起動したホストのポートを使用する。

$ gopls -remote=:37374 -logfile=auto -debug=:0 -rpc.trace

試しにターミナルを二つ開いてホスト側を起動して、エディタ側のコマンドを実行するとホスト側には Session 1: connected のように接続されたことがわかるようにログが出力される。

Macでデーモン化する

Macには標準でlaunchdというスクリプトの起動や停止などサービスを管理してくれるフレームワークを使う。

スクリプトとしては今回は下記を用意した。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.hatappi.gopls-daemon</string>

    <key>RunAtLoad</key>
    <true/>

    <key>KeepAlive</key>
    <dict>
      <key>SuccessfulExit</key>
      <false/>
    </dict>

    <key>OnDemand</key>
    <false/>

    <key>EnvironmentVariables</key>
    <dict>
      <key>PATH</key>
      <string>/usr/bin:/bin:/usr/sbin:/sbin</string>
    </dict>

    <key>ProgramArguments</key>
    <array>
      <string>gopls</string>
      <string>-listen=:37374</string>
      <string>-logfile=auto</string>
      <!--
      <string>-debug=:0</string>
      -->
    </array>
  </dict>
</plist>

とりあえず雰囲気で書きつつ launchctl load で読み込みつつ起動するように調整していきました。
ファイルの置き場所としては公式のドキュメントをみて今回はログイン中のユーザー時のみ起動したかったので ~/ライブラリ/LaunchAgents に配置した。

launchctl list | grep gopls などで起動を確認しつつデーモン側の作業は完了。

vim-lsp側の設定

https://github.com/prabirshrestha/vim-lsp/wiki/Servers-Go
vim-lsp側は公式のwikiを参考しつつ、先ほど起動したデーモンを指定するように設定する。

if executable('gopls')
    au User lsp_setup call lsp#register_server({
        \ 'name': 'gopls',
        \ 'cmd': {server_info->['gopls', '-remote=:37374']},
        \ 'whitelist': ['go'],
        \ })
    autocmd BufWritePre *.go LspDocumentFormatSync
endif

最後に

今のところは問題なく動いている。
これでしばらく使ってみる。