Clojure開発環境でのフォーマッターcljstyle設定まとめ: Spacemacs, IntelliJ IDEA (Cursive), VS Code (Calva), Vim (vim-iced)

お好みのエディタ/IDEに[Clojure](https://clojure.org/)開発環境を用意したら、ぜひファイル保存時に自動実行できるフォーマッターも設定しましょう。

他言語における[Prettier](https://prettier.io/)などと同様に、ファイルを保存するたびにフォーマットできると非常に快適です。

[Clojureのフォーマッターcljstyleの使い方 - TOYOKUMO Tech Blog](https://tech.toyokumo.co.jp/entry/format-clojure-code-using-cljstyle)という記事でも紹介されている、従来の[cljfmt](https://github.com/weavejester/cljfmt)よりも高速に動作し高機能な[cljstyle](https://github.com/greglook/cljstyle)を利用します。

本記事でも[Clojure開発環境での基本操作まとめ: Spacemacs, IntelliJ IDEA (Cursive), VS Code (Calva), Vim (vim-iced), rebel-readline](https://qiita.com/lagenorhynque/items/0b52575e90bad563e4bd)と同様に2020年時点でClojurianに特に人気のエディタ/IDEでの設定方法に絞って紹介します。

- [Spacemacs](https://www.spacemacs.org/) + [Clojure layer](https://github.com/syl20bnr/spacemacs/tree/develop/layers/+lang/clojure)
- [IntelliJ IDEA](https://www.jetbrains.com/ja-jp/idea/) + [Cursive](https://cursive-ide.com/)
- [VS Code (Visual Studio Code)](https://azure.microsoft.com/ja-jp/products/visual-studio-code/) + [Calva](https://marketplace.visualstudio.com/items?itemName=betterthantomorrow.calva)
- [Vim](https://www.vim.org/) + [vim-iced](https://github.com/liquidz/vim-iced)

他のエディタ/IDEをご利用の方はサポート状況と設定方法をご確認ください(cf. [Integrations](https://github.com/greglook/cljstyle/blob/master/doc/integrations.md))。

# 共通: cljstyleのインストールとデフォルト設定

macOSの場合、[Homebrew](https://brew.sh/index_ja.html)でインストールするのが簡単です。

```shell
$ brew install --cask cljstyle
```

また、デフォルトで適用したい設定を `~/.cljstyle` ファイルとして配置しておくと便利です。

例えば以下のように設定すると、およそ[The Clojure Style Guide](https://guide.clojure.style/)のレイアウトに沿った形でフォーマットされるようになります(※ バージョン[0.14.0](https://github.com/greglook/cljstyle/blob/master/CHANGELOG.md#0140---2020-11-07)で設定ファイルの記述形式が変更されているので注意)。

```clojure:~/.cljstyle
{:rules {:blank-lines {:max-consecutive 1
                       :padding-lines 1}
         :comments {:enabled? false}
         :functions {:enabled? false}
         :indentation {:indents {defspec [[:inner 0]]
                                 fdef [[:inner 0]]
                                 for-all [[:inner 0]]}
                       :list-indent 1}
         :namespaces {:indent-size 1}
         :types {:enabled? false}}}
```

`:rules > :indentation > :indents` の設定は必須ではありませんが、一例として私がプロジェクト横断でよく使う[clojure.spec](https://clojure.org/guides/spec)や[test.check](https://github.com/clojure/test.check)のマクロについて設定してあります。

特定のプロジェクト固有のフォーマット設定はプロジェクトルートディレクトリの `.cljstyle` ファイルで行うと良いでしょう。

# Spacemacs + Clojure layerの場合

[jstokes/cljstyle-mode](https://github.com/jstokes/cljstyle-mode)を利用することで、ファイル保存時に `cljstyle fix` 相当のコマンドが自動実行されるようにすることができます。

```emacs-lisp:~/.spacemacs
(defun dotspacemacs/layers ()
  (setq-default
   ...
   dotspacemacs-additional-packages '((cljstyle-mode :location (recipe :fetcher github :repo "jstokes/cljstyle-mode")))
   ...))

(defun dotspacemacs/user-config ()
  ...
  (add-hook 'clojure-mode-hook #'cljstyle-mode)
  ...)
```

動作例:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/dd6af80c-fe56-a8b5-69e8-f76f6e4738fc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/68bc4287-fa01-1013-da5a-893785031060.png)

# IntelliJ IDEA + Cursiveの場合

File Watchersを利用することで、ファイル編集時に `cljstyle fix` が自動実行されるように設定することができます。

- 1. (Ultimate Editionでない場合) [File Watchers](https://plugins.jetbrains.com/plugin/7177-file-watchers)プラグインをインストールする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/c768ca7b-24a2-a118-706a-d9674890471e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/ae245681-a8b6-fa2a-c990-5e690b2c25c2.png)

- 2. `Tools > File Watchers` でファイルタイプ `Clojure`, `ClojureScript`, `CLJC` に対するプロジェクト横断(Level: `Global`)の設定を追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/e9227db5-9c9f-4808-828f-3756383de6ad.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/60e035ed-1a1c-a465-0abf-3d43aae2fbd6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/04cc0b99-0383-1c2b-9dbe-9d31f657137b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/17e48d20-e184-b81f-257b-0b9592f41105.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/66ef5dc8-6373-b661-f0cc-776a73f33f23.png)

動作例:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/7d352145-91d2-a083-4e70-a828c5b2433c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/e4bcfd7f-22b5-40f3-96be-5f06bffc2fe9.png)

# VS Code + Calvaの場合

[Save and Run](https://marketplace.visualstudio.com/items?itemName=wk-j.save-and-run) (もしくはその他同種の拡張)を利用することで、ファイル保存時に `cljstyle fix` が自動実行されるように設定することができます。

例えばユーザ設定ファイル `settings.json` に以下のように設定すると、拡張子 `.clj`, `.cljc`, `.cljs` の任意のファイル保存時に `cljstyle fix <保存対象ファイル>` が実行されます。

```json:settings.json
{
  ...,
  "saveAndRun": {
    "commands": [
      {
        "match": "\\.clj[cs]?$",
        "cmd": "cljstyle fix ${file}",
        "useShortcut": false,
        "silent": true
      }
    ]
  }
}
```

動作例:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/3aa6ed26-24ae-2fff-91ba-a47b71887d54.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/7d758538-73b3-8979-b331-583f6de66717.png)

# Vim + vim-icedの場合

[vim-iced > 9. Formatting](https://liquidz.github.io/vim-iced/#formatting)を参考に以下のように設定すると、ファイル保存時に `cljstyle fix` 相当のコマンドが自動実行されるようにすることができます[^1]。

```vimscript:~/.vimrc
let g:iced_formatter = 'cljstyle'

aug MyClojureSetting
  au!
  au BufWritePre *.clj,*.cljs,*.cljc,*.edn execute ':IcedFormatSyncAll'
aug END
```

動作例:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/1a195d08-7d3f-5d71-a57a-7347bcbcd2c3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33430/1e9f335d-e287-e707-8941-e676d4b10811.png)

# Further Reading

- [Clojureのフォーマッターcljstyleの使い方 - TOYOKUMO Tech Blog](https://tech.toyokumo.co.jp/entry/format-clojure-code-using-cljstyle)
- [Clojure/ClojureScript関連リンク集 - Qiita > エディタプラグイン](https://qiita.com/lagenorhynque/items/68c314c288b75a9492ba#%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3)
- [Clojure開発環境での基本操作まとめ: Spacemacs, IntelliJ IDEA (Cursive), VS Code (Calva), Vim (vim-iced), rebel-readline - Qiita](https://qiita.com/lagenorhynque/items/0b52575e90bad563e4bd)
- [Clojure開発環境でのリンターclj-kondo, Joker設定まとめ: Spacemacs, IntelliJ IDEA (Cursive), VS Code (Calva), Vim (vim-iced) - Qiita](https://qiita.com/lagenorhynque/items/dd9d6a1d97cbea738bc0)
- [Clojureで快適なREPL駆動開発のために"reloaded workflow"を実践しよう - Qiita](https://qiita.com/lagenorhynque/items/a752ffae490e83ebe70d)

[^1]: vim-icedの作者 @uochan さんから、局所的に自動フォーマットする設定例も教えていただきました: [Format only current top form on writing a file](https://zenn.dev/uochan/scraps/f320460b49ddda#comment-9abdc0e5f0d2d9)