さめたコーヒー

kbaba1001's blog.

Clojure開発環境をVS Code でつくる

たぶんClojureを書いている人はEmacsを使っている人が多いと思いますがVS Codeも結構書きやすいと思うので僕がやっている方法について書きます。

使用するエクステンション:

Calva について

Calva は Emacs でいう Cider、IntelliJ でいう Cursive のようなエクステンションです。主に次のようなことができます。

  • REPL を VS Code 内で起動したり、ターミナルなどで起動したREPLに接続する
  • inline や file、 namespace単位でのコードの実行
  • テストの実行
  • code formatting
  • 関数の定義場所にジャンプ
  • Paredit
  • ClojureScript も対応

かなり包括的にサポートされています。しばらく前まで Calva 関係のエクステンションはいくつかに分かれていましたが、近頃統合されて一つになりました。

REPLを起動するとこのようになります。

Calva の詳しい使い方は公式サイトを御覧ください。

marketplace.visualstudio.com

Clojure Warrior

Clojure のカッコを色付してコードを読みやすくしてくれるエクステンション。たまにカッコの数でコンパイルエラーしてしまうのであると便利。

VS Code - remote containers

Clojureの実行環境を Docker で用意して、 VS Code - remote containers をつかって container の中で開発をできるようにします。 僕は近頃は Docker を使った開発ばかりしています。何かしらのライブラリも Docker Image で公開されて、Image を取得するだけで使えるようになっていることも増えました。 本当に便利になりました。

remote containers エクステンションは Docker を用いた開発を更に便利にするものです。 通常、 Docker を用いた開発では docker コマンドや docker-compose コマンドを使ってコンテナを立ち上げて、portなどを使って外部からコンテナにアクセスして利用します。 例えば、remote containers を使わずに docker で動いている REPL に calva でアクセスするには docker-compose run clojure repl などのようにして nREPL を起動して、その port 番号を calva に渡して接続します。 しかしこの方法では calva jack-in REPLの機能が使えないため、REPLの中で補完を行うなどのことができません。 どうしても docker や docker-compose コマンドを使いたいコマンドの前につける必要があるため、エクステンションの機能をフル活用することが難しいことが多いのです。 remote containers はこの問題を解決します。

remote containers は Docker container 内で VS Code が動いているかのようにしてくれます。たとえば、remote containers を使っているときに VS Code でターミナルを立ち上げると、 Docker container のシェルが起動します。

VS Code - remote containers で Clojure 環境を作る

remote containers 用の設定をリポジトリ内に作る必要があります。 .devcontainer ディレクトリを作成して次のファイルを用意します。今回は PostgreSQL を利用する Web サーバーを想定しています。

.devcontainer/
  * Dockerfile  
  * devcontainer.json  
  * docker-compose.yml

devcontainer.json

{
  "name": "simple clojure rest",
  "dockerComposeFile": [
    "docker-compose.yml"
  ],
  "service": "app",
  "workspaceFolder": "/simple-clojure-rest",
  "extensions": [
    "betterthantomorrow.calva",
    "tonsky.clojure-warrior",
    "mtxr.sqltools"
  ],
  "settings":{
    "calva.jokerPath": "/usr/bin",
    "parinfer.defaultMode": "disabled",
    "calva.autoAdjustIndent": true,
    "calva.lintOnSave": true,
    "editor.tabSize": 2,
    "files.insertFinalNewline": true,
    "files.trimFinalNewlines": true,
    "terminal.integrated.shell.linux": "/bin/bash"
  }
}

devcontainer.json は remote containers の設定を記述するための json です。今回は docker-compose を使いたいので、 dockerComposeFile で docker-compose.yml ファイルを指定します。 これは複数指定することもできます。配列の後に指定したほうの yml でそれ以前の yml の Key-Value がオーバーライドされます。これにより、プロジェクト用の docker-compose.yml とは別に VS Code remote containers 専用の設定を別の yml に定義してオーバーライドすることもできます。(今回はやってません)

service は docker-compose 内の使いたい service 名を指定します。今回は app という service 内で Clojure のコードを書いていけるようにします。

extensions は remote containers を立ち上げたときにインストールする VS Code のエクステンションを指定できます。これにより remote containers を起動するだけでエクステンションを含めた開発環境が構築されます。

settings は remote containers を立ち上げた環境用の設定を記述します。 extensions で入れたエクステンション用の設定も記述できます。

devcontainer.json の詳細は次を参照してください。もちろん docker-compose を使わずに Dockerfile から環境を構築することもできます。

code.visualstudio.com

Dockerfile

FROM clojure:openjdk-8-lein-2.9.1

# setup environment variables
ENV LANG C.UTF-8
ENV DEBIAN_FRONTEND noninteractive
ENV JOKER_VERSION 0.12.5
ENV SHELL /bin/bash

RUN apt-get update \
    && apt-get -y install --no-install-recommends apt-utils 2>&1 \
    #
    # Verify git, process tools, lsb-release (common in install instructions for CLIs) installed
    && apt-get -y install git procps lsb-release \
    #
    # Clean up
    && apt-get autoremove -y \
    && apt-get clean -y \
    && rm -rf /var/lib/apt/lists/* \
    #
    # install joker
    && wget https://github.com/candid82/joker/releases/download/v${JOKER_VERSION}/joker-${JOKER_VERSION}-linux-amd64.zip \
    && unzip joker-${JOKER_VERSION}-linux-amd64.zip \
    && rm joker-${JOKER_VERSION}-linux-amd64.zip \
    && chmod a+x joker && mv joker /usr/bin

# Switch back to dialog for any ad-hoc use of apt-get
ENV DEBIAN_FRONTEND=dialog

clojure の公式 Image をベースにして環境を作ります。git、procps、lsb-release は remote container を使うために必要なのでインストールします。

Calva は joker を使って Lint ができるので joker をインストールします。 github.com

docker-compose.yml

version: '3'
services:
  db:
    image: postgres
    ports:
      - 5432:5432
    volumes:
      - /var/lib/postgresql/data
  app:
    build:
      context: ../
      dockerfile: .devcontainer/Dockerfile
    command: sleep infinity                                       # 起動したコンテナを終了させないためのコマンド
    ports:
      - 3000:3000
    depends_on:
      - db
    volumes:
      - ~/.gitconfig:/root/.gitconfig                            # remote container内でgitを使うためホストの設定をコピーする
      - ..:/simple-clojure-rest
      - lib_data:/root/.m2/repository
    environment:
      - FOO=bar

volumes:
  lib_data:

debug

残念ながら Calva は VS Code の debugger 機能に対応していません。 一応、 VS Code の debugger で Clojure をデバッグできるエクステンションもあるのですが、開発が盛んではなく現在はうまく動かないようです。

github.com

仕方がないので break point を設定したりすることは諦めて print デバッグ的な方向でデバッグを行っています。 これ系は色々ありますが、僕は次が気に入っています。

github.com

REBL というのもあるようなのでそれでもいいかも

tech.uzabase.com

おまけ: SQLTools

marketplace.visualstudio.com

VS Code のエクステンションで使えるGUI SQL Client。MySQLやPostgreSQLなど複数のDBに対応しており便利。