yeet
This commit is contained in:
115
.config/emacs/modules/lang/clojure/README.org
Normal file
115
.config/emacs/modules/lang/clojure/README.org
Normal file
@@ -0,0 +1,115 @@
|
||||
#+TITLE: lang/clojure
|
||||
#+DATE: May 30, 2017
|
||||
#+SINCE: v2.0
|
||||
#+STARTUP: inlineimages nofold
|
||||
|
||||
* Table of Contents :TOC_3:noexport:
|
||||
- [[#description][Description]]
|
||||
- [[#maintainers][Maintainers]]
|
||||
- [[#module-flags][Module Flags]]
|
||||
- [[#plugins][Plugins]]
|
||||
- [[#hacks][Hacks]]
|
||||
- [[#prerequisites][Prerequisites]]
|
||||
- [[#features][Features]]
|
||||
- [[#keybindings][Keybindings]]
|
||||
- [[#configuration][Configuration]]
|
||||
- [[#troubleshooting][Troubleshooting]]
|
||||
|
||||
* Description
|
||||
This module adds support for the Clojure(Script) language.
|
||||
|
||||
+ Interactive development environment (~cider~): REPL, compilation, debugging,
|
||||
running tests, definitions & documentation lookup, code completion, and much
|
||||
more
|
||||
+ Refactoring (~clj-refactor~)
|
||||
+ Linting (~clj-kondo~), requires ~:checkers syntax~
|
||||
+ LSP support (~clojure-lsp~)
|
||||
|
||||
** Maintainers
|
||||
This module has no dedicated maintainers.
|
||||
|
||||
** Module Flags
|
||||
+ =+lsp= Enables LSP support, alongside Cider.
|
||||
|
||||
** Plugins
|
||||
+ [[https://github.com/clojure-emacs/cider][cider]]
|
||||
+ [[https://github.com/clojure-emacs/clj-refactor.el][clj-refactor]]
|
||||
+ [[https://github.com/borkdude/flycheck-clj-kondo][flycheck-clj-kondo]]
|
||||
|
||||
** Hacks
|
||||
+ Error messages emitted from CIDER are piped into the REPL buffer when it is
|
||||
first opened, to make them easier to notice.
|
||||
+ Disabled the help banner when opening the cider REPL.
|
||||
|
||||
* Prerequisites
|
||||
This module requires:
|
||||
|
||||
+ [[https://clojure.org/][clojure]]
|
||||
+ [[https://leiningen.org/][leiningen]] (REPL)
|
||||
+ [[https://github.com/borkdude/clj-kondo][clj-kondo]] (linter)
|
||||
+ With =+lsp=
|
||||
+ [[https://clojure-lsp.github.io/clojure-lsp/][clojure-lsp]]
|
||||
|
||||
|
||||
* TODO Features
|
||||
# An in-depth list of features, how to use them, and their dependencies.
|
||||
** Keybindings
|
||||
| Binding | Description |
|
||||
|---------------------+------------------------------------------------------|
|
||||
| =<localleader> '= | =cider-jack-in-clj= |
|
||||
| =<localleader> C= | =cider-connect-cljs= |
|
||||
| =<localleader> M= | =cider-macroexpand-all= |
|
||||
| =<localleader> R= | =hydra-cljr-help-menu/body= |
|
||||
| =<localleader> c= | =cider-connect-clj= |
|
||||
| =<localleader> e D= | =cider-insert-defun-in-repl= |
|
||||
| =<localleader> e E= | =cider-insert-last-sexp-in-repl= |
|
||||
| =<localleader> e R= | =cider-insert-region-in-repl= |
|
||||
| =<localleader> e b= | =cider-eval-buffer= |
|
||||
| =<localleader> e d= | =cider-eval-defun-at-point= |
|
||||
| =<localleader> e e= | =cider-eval-last-sexp= |
|
||||
| =<localleader> e r= | =cider-eval-region= |
|
||||
| =<localleader> e u= | =cider-undef= |
|
||||
| =<localleader> g b= | =cider-pop-back= |
|
||||
| =<localleader> g g= | =cider-find-var= |
|
||||
| =<localleader> g n= | =cider-find-ns= |
|
||||
| =<localleader> h a= | =cider-apropos= |
|
||||
| =<localleader> h c= | =cider-clojuredocs= |
|
||||
| =<localleader> h d= | =cider-doc= |
|
||||
| =<localleader> h j= | =cider-javadoc= |
|
||||
| =<localleader> h n= | =cider-find-ns= |
|
||||
| =<localleader> h w= | =cider-clojuredocs-web= |
|
||||
| =<localleader> i e= | =cider-enlighten-mode= |
|
||||
| =<localleader> i i= | =cider-inspect= |
|
||||
| =<localleader> i r= | =cider-inspect-last-result= |
|
||||
| =<localleader> m "= | =cider-jack-in-cljs= |
|
||||
| =<localleader> m= | =cider-macroexpand-1= |
|
||||
| =<localleader> n N= | =cider-browse-ns-all= |
|
||||
| =<localleader> n n= | =cider-browse-ns= |
|
||||
| =<localleader> n r= | =cider-ns-refresh= |
|
||||
| =<localleader> p d= | =cider-pprint-eval-defun-at-point= |
|
||||
| =<localleader> p D= | =cider-pprint-eval-defun-to-comment= |
|
||||
| =<localleader> p p= | =cider-pprint-eval-last-sexp= |
|
||||
| =<localleader> p P= | =cider-pprint-eval-last-sexp-to-comment= |
|
||||
| =<localleader> p r= | =cider-pprint-eval-last-sexp-to-repl= |
|
||||
| =<localleader> r B= | =+clojure/cider-switch-to-repl-buffer-and-switch-ns= |
|
||||
| =<localleader> r L= | =cider-load-buffer-and-switch-to-repl-buffer= |
|
||||
| =<localleader> r R= | =cider-restart= |
|
||||
| =<localleader> r b= | =cider-switch-to-repl-buffer= |
|
||||
| =<localleader> r c= | =cider-find-and-clear-repl-output= |
|
||||
| =<localleader> r l= | =cider-load-buffer= |
|
||||
| =<localleader> r n= | =cider-repl-set-ns= |
|
||||
| =<localleader> r q= | =cider-quit= |
|
||||
| =<localleader> r r= | =cider-ns-refresh= |
|
||||
| =<localleader> t a= | =cider-test-rerun-test= |
|
||||
| =<localleader> t l= | =cider-test-run-loaded-tests= |
|
||||
| =<localleader> t n= | =cider-test-run-ns-tests= |
|
||||
| =<localleader> t p= | =cider-test-run-project-tests= |
|
||||
| =<localleader> t r= | =cider-test-rerun-failed-tests= |
|
||||
| =<localleader> t s= | =cider-test-run-ns-tests-with-filters= |
|
||||
| =<localleader> t t= | =cider-test-run-test= |
|
||||
|
||||
* TODO Configuration
|
||||
# How to configure this module, including common problems and how to address them.
|
||||
|
||||
* TODO Troubleshooting
|
||||
# Common issues and their solution, or places to look for help.
|
||||
44
.config/emacs/modules/lang/clojure/autoload.el
Normal file
44
.config/emacs/modules/lang/clojure/autoload.el
Normal file
@@ -0,0 +1,44 @@
|
||||
;;; lang/clojure/autoload.el -*- lexical-binding: t; -*-
|
||||
|
||||
;;;###autoload
|
||||
(defun +clojure-cider-lookup-definition (identifier)
|
||||
"A lookup handler for `cider-mode'.
|
||||
|
||||
This is necessary to fix `cider-find-dwim's inability to capture the full symbol
|
||||
at point."
|
||||
(cider-find-dwim identifier))
|
||||
|
||||
|
||||
;;
|
||||
;;; Commands
|
||||
|
||||
;;;###autoload
|
||||
(defun +clojure/open-repl (&optional arg type)
|
||||
"Open a Cider REPL for clojure and return the buffer."
|
||||
(interactive "P")
|
||||
;; TODO Better error handling
|
||||
;; type is `clj' for clojure and `cljs' for clojurescript
|
||||
;; ... with no type specified, assume `clj'.
|
||||
(let ((type (or type 'clj)))
|
||||
(if-let (buffer (cider-current-repl type))
|
||||
(pop-to-buffer buffer)
|
||||
(let ((process (cond ((eq type 'clj) (cider-jack-in-clj arg))
|
||||
((eq type 'cljs) (cider-jack-in-cljs arg)))))
|
||||
(message "Starting CIDER server for the first time...")
|
||||
(while (and (process-live-p process)
|
||||
(not (cider-current-repl type)))
|
||||
(sit-for 1))
|
||||
(message "Starting CIDER server for the first time...done")
|
||||
(pop-to-buffer (cider-current-repl type))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +clojure/open-cljs-repl (&optional arg)
|
||||
"Open a Cider REPL for clojurescript and return the buffer."
|
||||
(interactive "P")
|
||||
(+clojure/open-repl arg 'cljs))
|
||||
|
||||
;;;###autoload
|
||||
(defun +clojure/cider-switch-to-repl-buffer-and-switch-ns ()
|
||||
"TODO"
|
||||
(interactive)
|
||||
(cider-switch-to-repl-buffer t))
|
||||
246
.config/emacs/modules/lang/clojure/config.el
Normal file
246
.config/emacs/modules/lang/clojure/config.el
Normal file
@@ -0,0 +1,246 @@
|
||||
;;; lang/clojure/config.el -*- lexical-binding: t; -*-
|
||||
|
||||
(after! projectile
|
||||
(pushnew! projectile-project-root-files "project.clj" "build.boot" "deps.edn"))
|
||||
|
||||
;; Large clojure buffers tend to be slower than large buffers of other modes, so
|
||||
;; it should have a lower threshold too.
|
||||
(add-to-list 'doom-large-file-size-alist '("\\.\\(?:clj[sc]?\\|dtm\\|edn\\)\\'" . 0.5))
|
||||
|
||||
|
||||
;;
|
||||
;;; Packages
|
||||
|
||||
(use-package! clojure-mode
|
||||
:hook (clojure-mode . rainbow-delimiters-mode)
|
||||
:config
|
||||
(when (featurep! +lsp)
|
||||
(add-hook! '(clojure-mode-local-vars-hook
|
||||
clojurec-mode-local-vars-hook
|
||||
clojurescript-mode-local-vars-hook)
|
||||
(defun +clojure-disable-lsp-indentation-h ()
|
||||
(setq-local lsp-enable-indentation nil))
|
||||
#'lsp!)
|
||||
(after! lsp-clojure
|
||||
(dolist (m '(clojure-mode
|
||||
clojurec-mode
|
||||
clojurescript-mode
|
||||
clojurex-mode))
|
||||
(add-to-list 'lsp-language-id-configuration (cons m "clojure"))))))
|
||||
|
||||
|
||||
(use-package! cider
|
||||
;; NOTE if `org-directory' doesn't exist, `cider-jack' in won't work
|
||||
:hook (clojure-mode-local-vars . cider-mode)
|
||||
:init
|
||||
(after! clojure-mode
|
||||
(set-repl-handler! '(clojure-mode clojurec-mode) #'+clojure/open-repl :persist t)
|
||||
(set-repl-handler! 'clojurescript-mode #'+clojure/open-cljs-repl :persist t)
|
||||
(set-eval-handler! '(clojure-mode clojurescript-mode clojurec-mode) #'cider-eval-region))
|
||||
|
||||
;; HACK Fix raxod502/radian#446: CIDER tries to calculate the frame's
|
||||
;; background too early; sometimes before the initial frame has been
|
||||
;; initialized, causing errors.
|
||||
(defvar cider-docview-code-background-color nil)
|
||||
(defvar cider-stacktrace-frames-background-color nil)
|
||||
(add-transient-hook! #'cider-docview-fontify-code-blocks (cider--docview-adapt-to-theme))
|
||||
(add-transient-hook! #'cider-stacktrace-render-cause (cider--stacktrace-adapt-to-theme))
|
||||
:config
|
||||
(add-hook 'cider-mode-hook #'eldoc-mode)
|
||||
(set-lookup-handlers! '(cider-mode cider-repl-mode)
|
||||
:definition #'+clojure-cider-lookup-definition
|
||||
:documentation #'cider-doc)
|
||||
(set-popup-rules!
|
||||
'(("^\\*cider-error*" :ignore t)
|
||||
("^\\*cider-repl" :quit nil :ttl nil)
|
||||
("^\\*cider-repl-history" :vslot 2 :ttl nil)))
|
||||
|
||||
(setq nrepl-hide-special-buffers t
|
||||
nrepl-log-messages nil
|
||||
cider-font-lock-dynamically '(macro core function var deprecated)
|
||||
cider-overlays-use-font-lock t
|
||||
cider-prompt-for-symbol nil
|
||||
cider-repl-history-display-duplicates nil
|
||||
cider-repl-history-display-style 'one-line
|
||||
cider-repl-history-file (concat doom-cache-dir "cider-repl-history")
|
||||
cider-repl-history-highlight-current-entry t
|
||||
cider-repl-history-quit-action 'delete-and-restore
|
||||
cider-repl-history-highlight-inserted-item t
|
||||
cider-repl-history-size 1000
|
||||
cider-repl-result-prefix ";; => "
|
||||
cider-repl-print-length 100
|
||||
cider-repl-use-clojure-font-lock t
|
||||
cider-repl-use-pretty-printing t
|
||||
cider-repl-wrap-history nil
|
||||
cider-stacktrace-default-filters '(tooling dup)
|
||||
|
||||
;; Don't focus the CIDER REPL when it starts. Since it can take so long
|
||||
;; to start up, you either wait for a minute doing nothing or be
|
||||
;; prepared for your cursor to suddenly change buffers without warning.
|
||||
;; See https://github.com/clojure-emacs/cider/issues/1872
|
||||
cider-repl-pop-to-buffer-on-connect 'display-only)
|
||||
|
||||
;; Error messages emitted from CIDER is silently funneled into *nrepl-server*
|
||||
;; rather than the *cider-repl* buffer. How silly. We might want to see that
|
||||
;; stuff and who's going to check *nrepl-server* on every startup? I've got a
|
||||
;; better idea: we copy these errors into the *cider-repl* buffer.
|
||||
(add-hook! 'cider-connected-hook
|
||||
(defun +clojure--cider-dump-nrepl-server-log-h ()
|
||||
"Copy contents of *nrepl-server* to beginning of *cider-repl*."
|
||||
(when (buffer-live-p nrepl-server-buffer)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(insert
|
||||
(with-current-buffer nrepl-server-buffer
|
||||
(buffer-string)))))))
|
||||
|
||||
;; When in cider-debug-mode, override evil keys to not interfere with debug keys
|
||||
(after! evil
|
||||
(add-hook! cider--debug-mode
|
||||
(defun +clojure--cider-setup-debug ()
|
||||
"Setup cider debug to override evil keys cleanly"
|
||||
(evil-make-overriding-map cider--debug-mode-map 'normal)
|
||||
(evil-normalize-keymaps))))
|
||||
|
||||
(when (featurep! :ui modeline +light)
|
||||
(defvar-local cider-modeline-icon nil)
|
||||
|
||||
(defun +clojure--cider-set-modeline (face label)
|
||||
"Update repl icon on modeline with cider information."
|
||||
(setq cider-modeline-icon (concat
|
||||
" "
|
||||
(+modeline-format-icon 'faicon "terminal" "" face label -0.0575)
|
||||
" "))
|
||||
(add-to-list 'global-mode-string
|
||||
'(t (:eval cider-modeline-icon))
|
||||
'append))
|
||||
|
||||
(add-hook! '(cider-connected-hook
|
||||
cider-disconnected-hook
|
||||
cider-mode-hook)
|
||||
(defun +clojure--cider-connected-update-modeline ()
|
||||
"Update modeline with cider connection state."
|
||||
(let* ((connected (cider-connected-p))
|
||||
(face (if connected 'warning 'breakpoint-disabled))
|
||||
(label (if connected "Cider connected" "Cider disconnected")))
|
||||
(+clojure--cider-set-modeline face label))))
|
||||
|
||||
(add-hook! '(cider-before-eval-hook)
|
||||
(defun +clojure--cider-before-eval-hook-update-modeline ()
|
||||
"Update modeline with cider state before eval."
|
||||
(+clojure--cider-set-modeline 'warning "Cider evaluating")))
|
||||
|
||||
(add-hook! '(cider-after-eval-done-hook)
|
||||
(defun +clojure--cider-after-eval-done-hook-update-modeline ()
|
||||
"Update modeline with cider state after eval."
|
||||
(+clojure--cider-set-modeline 'success "Cider syncronized")))
|
||||
|
||||
(add-hook! '(cider-file-loaded-hook)
|
||||
(defun +clojure--cider-file-loaded-update-modeline ()
|
||||
"Update modeline with cider file loaded state."
|
||||
(+clojure--cider-set-modeline 'success "Cider syncronized"))))
|
||||
|
||||
;; Ensure that CIDER is used for sessions in org buffers.
|
||||
(when (featurep! :lang org)
|
||||
(after! ob-clojure
|
||||
(setq! org-babel-clojure-backend 'cider)))
|
||||
|
||||
;; The CIDER welcome message obscures error messages that the above code is
|
||||
;; supposed to be make visible.
|
||||
(setq cider-repl-display-help-banner nil)
|
||||
|
||||
(map! (:localleader
|
||||
(:map (clojure-mode-map clojurescript-mode-map clojurec-mode-map)
|
||||
"'" #'cider-jack-in-clj
|
||||
"\"" #'cider-jack-in-cljs
|
||||
"c" #'cider-connect-clj
|
||||
"C" #'cider-connect-cljs
|
||||
"m" #'cider-macroexpand-1
|
||||
"M" #'cider-macroexpand-all
|
||||
(:prefix ("d" . "debug")
|
||||
"d" #'cider-debug-defun-at-point)
|
||||
(:prefix ("e" . "eval")
|
||||
"b" #'cider-eval-buffer
|
||||
"d" #'cider-eval-defun-at-point
|
||||
"D" #'cider-insert-defun-in-repl
|
||||
"e" #'cider-eval-last-sexp
|
||||
"E" #'cider-insert-last-sexp-in-repl
|
||||
"r" #'cider-eval-region
|
||||
"R" #'cider-insert-region-in-repl
|
||||
"u" #'cider-undef)
|
||||
(:prefix ("g" . "goto")
|
||||
"b" #'cider-pop-back
|
||||
"g" #'cider-find-var
|
||||
"n" #'cider-find-ns)
|
||||
(:prefix ("h" . "help")
|
||||
"n" #'cider-find-ns
|
||||
"a" #'cider-apropos
|
||||
"c" #'cider-clojuredocs
|
||||
"d" #'cider-doc
|
||||
"j" #'cider-javadoc
|
||||
"w" #'cider-clojuredocs-web)
|
||||
(:prefix ("i" . "inspect")
|
||||
"e" #'cider-enlighten-mode
|
||||
"i" #'cider-inspect
|
||||
"r" #'cider-inspect-last-result)
|
||||
(:prefix ("n" . "namespace")
|
||||
"n" #'cider-browse-ns
|
||||
"N" #'cider-browse-ns-all
|
||||
"r" #'cider-ns-refresh)
|
||||
(:prefix ("p" . "print")
|
||||
"p" #'cider-pprint-eval-last-sexp
|
||||
"P" #'cider-pprint-eval-last-sexp-to-comment
|
||||
"d" #'cider-pprint-eval-defun-at-point
|
||||
"D" #'cider-pprint-eval-defun-to-comment
|
||||
"r" #'cider-pprint-eval-last-sexp-to-repl)
|
||||
(:prefix ("r" . "repl")
|
||||
"n" #'cider-repl-set-ns
|
||||
"q" #'cider-quit
|
||||
"r" #'cider-ns-refresh
|
||||
"R" #'cider-restart
|
||||
"b" #'cider-switch-to-repl-buffer
|
||||
"B" #'+clojure/cider-switch-to-repl-buffer-and-switch-ns
|
||||
"c" #'cider-find-and-clear-repl-output
|
||||
"l" #'cider-load-buffer
|
||||
"L" #'cider-load-buffer-and-switch-to-repl-buffer)
|
||||
(:prefix ("t" . "test")
|
||||
"a" #'cider-test-rerun-test
|
||||
"l" #'cider-test-run-loaded-tests
|
||||
"n" #'cider-test-run-ns-tests
|
||||
"p" #'cider-test-run-project-tests
|
||||
"r" #'cider-test-rerun-failed-tests
|
||||
"s" #'cider-test-run-ns-tests-with-filters
|
||||
"t" #'cider-test-run-test)))
|
||||
|
||||
(:when (featurep! :editor evil +everywhere)
|
||||
:map cider-repl-mode-map
|
||||
:i [S-return] #'cider-repl-newline-and-indent
|
||||
:i [M-return] #'cider-repl-return
|
||||
(:localleader
|
||||
"n" #'cider-repl-set-ns
|
||||
"q" #'cider-quit
|
||||
"r" #'cider-ns-refresh
|
||||
"R" #'cider-restart
|
||||
"c" #'cider-repl-clear-buffer)
|
||||
:map cider-repl-history-mode-map
|
||||
:i [return] #'cider-repl-history-insert-and-quit
|
||||
:i "q" #'cider-repl-history-quit
|
||||
:i "l" #'cider-repl-history-occur
|
||||
:i "s" #'cider-repl-history-search-forward
|
||||
:i "r" #'cider-repl-history-search-backward
|
||||
:i "U" #'cider-repl-history-undo-other-window)))
|
||||
|
||||
|
||||
(use-package! clj-refactor
|
||||
:hook (clojure-mode . clj-refactor-mode)
|
||||
:config
|
||||
(set-lookup-handlers! 'clj-refactor-mode
|
||||
:references #'cljr-find-usages)
|
||||
(map! :map clojure-mode-map
|
||||
:localleader
|
||||
:desc "refactor" "R" #'hydra-cljr-help-menu/body))
|
||||
|
||||
|
||||
(use-package! flycheck-clj-kondo
|
||||
:when (featurep! :checkers syntax)
|
||||
:after flycheck)
|
||||
21
.config/emacs/modules/lang/clojure/packages.el
Normal file
21
.config/emacs/modules/lang/clojure/packages.el
Normal file
@@ -0,0 +1,21 @@
|
||||
;; -*- no-byte-compile: t; -*-
|
||||
;;; lang/clojure/packages.el
|
||||
|
||||
;; HACK Fix #5577. Paredit is a cider dependency. We install paredit ourselves
|
||||
;; to get it from emacsmirror, because the original upstream is a custom
|
||||
;; git server with shallow clones disabled.
|
||||
(package! paredit
|
||||
:recipe (:host github :repo "emacsmirror/paredit")
|
||||
:pin "8330a41e8188fe18d3fa805bb9aa529f015318e8")
|
||||
|
||||
;; HACK Forward declare these clj-refactor/cider deps so that their deps are
|
||||
;; byte-compiled first.
|
||||
(package! parseclj :pin "a8c4cf30fb68b66ae51541462a8b21753229a6e5")
|
||||
(package! parseedn :pin "e5ba280d1fb7b408d54062d4eac545326e850172")
|
||||
|
||||
;;; Core packages
|
||||
(package! clojure-mode :pin "e31186843d06ea86f3771244d1cde0112f9e2079")
|
||||
(package! clj-refactor :pin "12af23ad8b76519cb8b95eec4e8a5706d3186cd0")
|
||||
(package! cider :pin "af2e1649981729930efbbf58af232b3e413da0af")
|
||||
(when (featurep! :checkers syntax)
|
||||
(package! flycheck-clj-kondo :pin "d8a6ee9a16aa24b5be01f1edf9843d41bdc75555"))
|
||||
Reference in New Issue
Block a user