📝Clojure Emacs開発環境まとめ

Clojure開発環境(IDE)としてのEmacs設定まとめ.

🔧Emacs CIDER🔧clojure-lspの二択.

🔧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
      • これはフォームの先頭で評価すると次の行に結果表示.
  • 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

https://clojure-lsp.io/

EmacsからClojureのLSPを使うためのEmacs Package.

同じことはCIDERでもclojure-lspでもできるがclojure-lspのほうがCPU使用率が高いとか. エラー解析はどちらもclj-kondoに依存している.

🔖LSP

🆚CIDER vs clojure-lsp

つかった感想としては, CIDERとclojure-lspは共存可能であり, さらにいえば定義参照やジャンプ系はLSPが優れているので両方有効にしたほうがいい.


追記, 保存のたびに解析処理が走るのがどうも嫌なのでLSPは外した. PCのスペックが高いならば両方Onでもいいかも. わたしのPCだとどうも気になる.

Structural Editing

📝Structural Editing

Doom Emacs Clojure Module

hlissner/doom-emacs · GitHub

以下の3つのパッケージこ梱包されている.

  • cider
  • clj-refactor
  • flycheck-clj-kondo

Emacs Tips for Clojure

ファイル内のシンボルや関数を検索

M-x imenuが便利.

関数定義などを気軽にリストアップ. これはCIDERにはなく, Emacs組込み機能.

References