📝Clojure Emacs開発環境まとめ
Clojure開発環境(IDE)としてのEmacs設定まとめ.
- Emacsに限定しないものは別ノート: 📝Clojure 開発環境
- ✅Clojure: 文芸的プログラミング with org-babel
🔧Emacs CIDER
EmacsでClojure開発をするときのデファクトスタンダード.
Quick References
よくつかうもの.
- C-c l ’ cider-jack-in REPL起動 & 接
- C-c C-zで REPL - Editor間を移動.
- C-c C-c で現在の定義を評価.
- C-c C-e でフォームの末尾の手前から評価.
- C-c M-p で現在の定義をREPLに送信.
- M-. 定義に移動.
- C-c c D: xref-find-reference. その関数を参照元を探す.
- C-c C-d C-d documentをみる.
- jack-inしている状態で2charくらい打ち込んで C-iで補完候補がでる.
- C-c M-i で cider-inspectorを起動, defの中身が別バッファに表示される.
- C-c SPC: clojure-align, alignを自動整形.
- Evaluation
- M-x cider-pprint-last-eval-to-comment
- 式の評価結果がコメントとして書かれる.
- Design Journalとしては便利な機能かも.
- C-u C-x C-e でも可能.
- M-x cider-pprint-defun-to-comment
- これはフォームの先頭で評価すると次の行に結果表示.
- M-x cider-pprint-last-eval-to-comment
- cider-repl-set-ns: namespaceをreplに設定.
✅定義へジャンプする(cider-find-var/cider-pop-back)
関数/定数の定義にジャンプ. go to definitionをCIDERでやる.
- cider-find-var (M-.) ジャンプ.
- Emacsの汎用IFであるxref-find-definitionsも同じ挙動.
- cider-pop-back (M-,) 戻る
似たような機能なのであまり使わないが, cider-apropos/cider-apropos-selectをつかうと関数定義をみることができる. aproposはClojureの組込み関数.
✅namespaceから定義を取り除く(cider-undef)
namespaceからdefで定義した定数を排除したいとき, cider-undef(C-c C-u)をつかうと定義を解除することができる.
基本的にはdefをすれば上書きできるのだが, namespaceのrequireで独自に名前をasでつけている場合とかにそこそこつかうやつ.
tips: cider-jack-inでカスタムの依存を設定
一応cider-jack-inをすると依存関係をよろしく解決してくれるが, productionに含めないdevelopmentの依存関係は自動で解決されない.
.dir-locals.elに cider-clojure-cli-global-optionsやcider-clojure-cli-aliasesに追加の設定を書く.
例えば, deps.ednのaliasに :devのような定義があれば,
((clojure-mode . ((cider-clojure-cli-aliases . "dev"))))
ref: Practicalli: CIDER jack-in to Clojure CLI projects from Spacemacs
✅REPLの履歴をつかう(cider-repl-history)
REPLに入力したフォームはM-pで遡ることができる.
また C-c M-p(cider-repl-history)で過去の履歴をリスト表示できる.
✅変数定義の中身をみる(cider-inspect)
C-c C-eでフォームを評価して中身をみるのもいいが, ciderには cider-inspectという機能がある.
これを調べたい変数の上で実行(C-c M-i)すると, 別バッファに中身が表示される.
✅関数の参照をみる(Find References)
関数を呼び出してる参照元を一覧表示して移動する.
- cider-xref-fn-refs (C-c C-? r)
- cider-xref-fn-refs-select (C-c C-? C-r)
LSPのように静的解析ではないので若干時間かかる. C-?はボタン押しにくいかも, Ctrl+Shiftが必要.
似たような機能で以下もある. ソースを参照せずにdocのみ見たい場合にrefよりも高速に検索が終わる.
- cider-xref-fn-deps (C-c C-? d)
- cider-xref-fn-deps-select (C-c C-? C-d)
ref. CIDER Docs
ソースコードの規模によるかもしれないが, projectile + ripgrepのほうが検索が速いかも.
M-x cljr-find-usageがciderのxrefよりも高速で動作する. こっちがいい.このreferenceに関してはciderはおそすぎる. LSPとの併用がいいかも. しかしそもそも利用しているPCがボロいことが原因かも. お金溜まったら新しいPC買ってLSPも導入したい. ソレまで我慢.
✅CIDERとドキュメント連携
CIDERからドキュメントをクイックリファレンスできる.
- cider-doc: 関数のdocstringを表示
- cider-javadoc: Javadocを表示
- cider-clojuredocs: Clouredocsを表示.
よく使うのはClojuredocs. cider-clojuredocsをすると別バッファで clojuredocs 内の関数定義を参照できる. Clojureの初学ではライブラリをGoogleで検索することが多いが(このサイトも含めて)いい加減な記事も多いので, cider-clojuredocsをつかう習慣を心がけること.
clojure-projectの外からnREPLをつかうには?
例えばClojureによるデータ分析のためのorg-fileをclojureのコードとは別のプロジェクトで管理するとき.
接続先のREPLを起動してcider-connectをつかう. そして接続できたら in-ns でnamespaceを移動する(これをしないと, org-edit-modeでnamespaceがuserのまま).
✅cider-connectでのport固定
固定ポート自体はnREPLのオプションから指定.
:main-opts ["-m" "nrepl.cmdline"
"-b" "0.0.0.0"
"-p" "12345"
"--middleware" "[cider.nrepl/cider-middleware,refactor-nrepl.middleware/wrap-refactor]"]
cider-connectの接続先の候補に固定したportを表示する(ref).
(setq cider-known-endpoints '(("localhost" "0.0.0.0" "12345")))
✅REPLでたくさん出力してEmacsフリーズを防ぐ
(setq cider-print-quota 1024)
ref. Pretty-printing :: CIDER Docs
✅REPLで無限ループを評価してハングからの復旧(cider-interrupt)
CIDER上で変な評価をした結果REPLがハングすることがよくある. 通常REPLを再起動すれば直る.
大体の場合, REPLのハングの原因はループしていて, Thread中のループを外部Threadカラ止めるにはJavaのInterruptを叩くしかない.
しかし, M-x cider-interrupt(C-c C-b)を実行すると, これをやってくれるようだ.
✅クラスパスをチェックする
M-x cider-classpathで利用しているパッケージのクラスパスの一覧を表示.
なんかパッケージ読み込み周りでエラーするときにつかう. ちゃんと読み込めているか, パッケージのバージョンはなにで依存関係は, などなど.
🔧clojure-lsp
EmacsからClojureのLSPを使うためのEmacs Package.
同じことはCIDERでもclojure-lspでもできるがclojure-lspのほうがCPU使用率が高いとか. エラー解析はどちらもclj-kondoに依存している.
🆚CIDER vs clojure-lsp
つかった感想としては, CIDERとclojure-lspは共存可能であり, さらにいえば定義参照やジャンプ系はLSPが優れているので両方有効にしたほうがいい.
追記, 保存のたびに解析処理が走るのがどうも嫌なのでLSPは外した. PCのスペックが高いならば両方Onでもいいかも. わたしのPCだとどうも気になる.
Structural Editing
Doom Emacs Clojure Module
以下の3つのパッケージこ梱包されている.
- cider
- clj-refactor
- flycheck-clj-kondo
Emacs Tips for Clojure
ファイル内のシンボルや関数を検索
M-x imenuが便利.
関数定義などを気軽にリストアップ. これはCIDERにはなく, Emacs組込み機能.
References
- 🔗SpacemacsでClojureを書くために僕が行った設定 - ayato-p
- 昔のわたしの記事,もう情報が古い(2016)