#-*- mode: org -*-
#+TITLE: Emacs Setup for the Clojure Programming Language
#+AUTHOR: Volker Edelmann
#+EMAIL: vedelmann@gmx.de
#+STARTUP: indent
#+OPTIONS: toc:nil
#+OPTIONS: ^:{}
#+begin_src emacs-lisp
;; -*- coding: utf-8; lexical-binding: t -*-
#+end_src
Clojure belongs to the LISP family, therefore a Tree-sitter-grammar is obsolete.
Editing is done using LISP centered editing.
Development workflow is REPL driven development.
Environment setup:
#+begin_src emacs-lisp
(env-setup "clojure")
#+end_src
* Tree-sitter
#+begin_src emacs-lisp
(require 'clojure-ts-mode)
(push '(clojure-mode . clojure-ts-mode) major-mode-remap-alist)
#+end_src
* Editing
#+begin_src emacs-lisp
(use-package smartparens
)
#+end_src
#+begin_src emacs-lisp
(use-package rainbow-delimiters
)
#+end_src
* Folding
* Linting
Linters: joker, clj-kondo
#+begin_src emacs-lisp
#+end_src
(use-package flymake-joker)
Joker not tried.
#+begin_src emacs-lisp
(use-package flycheck-clj-kondo)
#+end_src
* Language Server
CIDER provides all I need.
Links from people using clojure language server:
- https://manueluberti.eu/posts/2023-03-25-clojure-lsp/
- https://emacs-lsp.github.io/lsp-mode/tutorials/clojure-guide/
- https://metaredux.com/posts/2023/12/23/cider-clojure-lsp-sitting-on-a-tree.html
* Major Mode
#+begin_src emacs-lisp
(use-package clojure-ts-mode
:hook
(clojure-ts-mode . yas-minor-mode)
(clojure-ts-mode . eldoc-mode)
(clojure-ts-mode . smartparens-mode)
(clojure-ts-mode . subword-mode)
(clojure-ts-mode . flycheck-mode)
(clojure-ts-mode . rainbow-delimiters-mode)
)
#+end_src
* REPL
#+begin_src emacs-lisp
(use-package cider
:config
(setq nrepl-log-messages t)
(add-hook 'before-save-hook 'cider-format-buffer t t)
:bind (
:map cider-mode-map
("C-c d" . cider-doc)
("C-c D" . cider-apropos-select)
("C-c p" . er/mark-paragraph)
("C-c f" . er/mark-defun)
("C-c s" . er/mark-symbol)
("C-+" . expreg-expand)
("C--" . expreg-contract)
("C-c C-f" . cider-eval-function-at-point)
("C-c C-s" . cider-eval-sexp-at-point)
("C-c C-l" . cider-eval-list-at-point)
("C-c C-n" . cider-repl-set-ns)
("S-<return>" . cider-eval-sexp-at-point)
("C-<return>" . cider-eval-dwim)
("M-<return>" . cider-insert-last-sexp-in-repl)
("C-M-x" . nil)
nil
)
:hook
(cider-repl-mode . eldoc-mode)
(cider-repl-mode . smartparens-mode)
(cider-repl-mode . subword-mode)
(cider-repl-mode . rainbow-delimiters-mode)
;; ((cider-mode eglot-managed-mode) . eglot-disable-in-cider)
)
#+end_src
* Hydras
#+begin_src emacs-lisp
(use-package cider-hydra
:hook
(clojure-ts-mode . cider-hydra-mode)
)
#+end_src
* Refactoring
#+begin_src emacs-lisp
(use-package clj-refactor
:hook
(clojure-ts-mode . clj-refactor-mode)
)
#+end_src
* TODO Debugging
* Literate Programming
... with org-mode
#+begin_src emacs-lisp
(require 'org)
(require 'ob-clojure)
(setq org-babel-clojure-backend 'cider)
(require 'cider)
#+end_src
* Documentation
use Hydra
* UI
#+begin_src emacs-lisp
(major-mode-hydra-define clojure-ts-mode nil
("General"
(
("l" flycheck-list-errors "linter window" :exit t)
("+" yas-insert-snippet "code snippets")
)
"Eval"
(
("b" cider-eval-buffer "buffer")
("f" cider-eval-defun-at-point "function")
("r" cider-eval-region "region")
("x" cider-eval-dwim "dwim")
)
"REPL"
(
("n" cider-repl-set-ns "set namespace")
("j" cider-jack-in-clj "start clojure repl")
("J" cider-jack-in-cljs "start clj-script repl")
)
"Test"
(
)
"Doc"
(
("d" cider-doc "clojure doc")
("a" cider-apropos-select "clojure apropos ...")
("w" cider-clojuredocs-web "clojure docs web")
("j" cider-javadoc "java doc")
)
)
)
#+end_src