[clojure] Add lsp server support
This commit is contained in:
parent
77d84b14e0
commit
6d39cd5548
|
@ -13,6 +13,7 @@
|
|||
- [[#install][Install]]
|
||||
- [[#add-the-clojure-layer-manually][Add the Clojure Layer manually]]
|
||||
- [[#pretty-symbols][Pretty Symbols]]
|
||||
- [[#optional-lsp-server][Optional LSP server]]
|
||||
- [[#enabling-automatic-linting][Enabling Automatic Linting]]
|
||||
- [[#enable-clj-kondo-linter][Enable clj-kondo linter]]
|
||||
- [[#enable-joker-linter][Enable joker linter]]
|
||||
|
@ -75,10 +76,11 @@ and a full suite of tooling for Clojure development.
|
|||
The following Spacemacs layers should also be added for a complete experience.
|
||||
- auto-completion
|
||||
- syntax-checking (provides flycheck for linter support)
|
||||
- LSP
|
||||
|
||||
*** Other optional features
|
||||
- Refactoring via [[https://github.com/clojure-emacs/clj-refactor.el][clj-refactor]]
|
||||
- Debugging with [[https://github.com/clojure-emacs/sayid][sayid]] (beta)
|
||||
- Debugging with [[https://github.com/clojure-emacs/sayid][sayid]]
|
||||
|
||||
*** References
|
||||
- [[https://docs.cider.mx/cider/][CIDER documentation]]
|
||||
|
@ -111,6 +113,33 @@ Or set this variable when loading the configuration layer:
|
|||
'((clojure :variables clojure-enable-fancify-symbols t)))
|
||||
#+END_SRC
|
||||
|
||||
** Optional LSP server
|
||||
Traditionally the clojure developing environment is working
|
||||
exclusively with an external server called CIDER.
|
||||
This has some drawbacks especially that most features require
|
||||
a working REPL session in the background. Newer layers work
|
||||
with a standard LSP server providing standard
|
||||
bindings for most features. In addition =lsp-UI= provides a more
|
||||
modern UI for visualising linter results and providing
|
||||
code actions.
|
||||
|
||||
The server is automatically activated when you have the =lsp-layer=
|
||||
installed in your dotfile. Alternatively you can force a
|
||||
certain backend by setting the =clojure-backend= variable
|
||||
in your dotfile:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(setq-default dotspacemacs-configuration-layers
|
||||
'((clojure :variables clojure-backend 'lsp)))
|
||||
#+END_SRC
|
||||
|
||||
The server is started automatically when a supported file is opened.
|
||||
It will also provide a flycheck integration via =lsp-flycheck= which
|
||||
will run the configured linter from your project config.
|
||||
See [[https://github.com/snoe/clojure-lsp][here]] for details. The server is installed automatically
|
||||
in your emacs directory however if this does not work
|
||||
it can also be installed manually from [[https://github.com/snoe/clojure-lsp/releases/latest/download/clojure-lsp][here]].
|
||||
|
||||
** Enabling Automatic Linting
|
||||
[[https://github.com/borkdude/clj-kondo][clj-kondo]], [[https://github.com/candid82/joker][joker]] and [[https://github.com/clojure-emacs/squiggly-clojure][squiggly-clojure]] provide automated linting via =flycheck=.
|
||||
These packages are disabled by default as they require the relevant linter binaries
|
||||
|
|
|
@ -28,3 +28,8 @@
|
|||
|
||||
(defvar clojure-enable-linters nil
|
||||
"If non-nil, enable clojure linters.")
|
||||
|
||||
(defvar clojure-backend nil
|
||||
"The backend to use for IDE features.
|
||||
Possible values are `lsp' and `cider'.
|
||||
If `nil' then 'cider` is the default backend unless `lsp' layer is used")
|
||||
|
|
|
@ -9,30 +9,43 @@
|
|||
;;
|
||||
;;; License: GPLv3
|
||||
|
||||
(defun spacemacs//clojure-backend ()
|
||||
"Return selected backend."
|
||||
(if clojure-backend
|
||||
clojure-backend
|
||||
(cond
|
||||
((configuration-layer/layer-used-p 'lsp) 'lsp)
|
||||
(t 'cider))))
|
||||
|
||||
(defun spacemacs//clojure-setup-backend ()
|
||||
"Conditionally setup clojure backend."
|
||||
(pcase (spacemacs//clojure-backend)
|
||||
(`lsp (lsp))))
|
||||
|
||||
(defun clojure/fancify-symbols (mode)
|
||||
"Pretty symbols for Clojure's anonymous functions and sets,
|
||||
like (λ [a] (+ a 5)), ƒ(+ % 5), and ∈{2 4 6}."
|
||||
(font-lock-add-keywords mode
|
||||
`(("(\\(fn\\)[[[:space:]]"
|
||||
(0 (progn (compose-region (match-beginning 1)
|
||||
(match-end 1) "λ")
|
||||
nil)))
|
||||
("(\\(partial\\)[[[:space:]]"
|
||||
(0 (progn (compose-region (match-beginning 1)
|
||||
(match-end 1) "Ƥ")
|
||||
nil)))
|
||||
("(\\(comp\\)[[[:space:]]"
|
||||
(0 (progn (compose-region (match-beginning 1)
|
||||
(match-end 1) "∘")
|
||||
nil)))
|
||||
("\\(#\\)("
|
||||
(0 (progn (compose-region (match-beginning 1)
|
||||
(match-end 1) "ƒ")
|
||||
nil)))
|
||||
("\\(#\\){"
|
||||
(0 (progn (compose-region (match-beginning 1)
|
||||
(match-end 1) "∈")
|
||||
nil))))))
|
||||
`(("(\\(fn\\)[[[:space:]]"
|
||||
(0 (progn (compose-region (match-beginning 1)
|
||||
(match-end 1) "λ")
|
||||
nil)))
|
||||
("(\\(partial\\)[[[:space:]]"
|
||||
(0 (progn (compose-region (match-beginning 1)
|
||||
(match-end 1) "Ƥ")
|
||||
nil)))
|
||||
("(\\(comp\\)[[[:space:]]"
|
||||
(0 (progn (compose-region (match-beginning 1)
|
||||
(match-end 1) "∘")
|
||||
nil)))
|
||||
("\\(#\\)("
|
||||
(0 (progn (compose-region (match-beginning 1)
|
||||
(match-end 1) "ƒ")
|
||||
nil)))
|
||||
("\\(#\\){"
|
||||
(0 (progn (compose-region (match-beginning 1)
|
||||
(match-end 1) "∈")
|
||||
nil))))))
|
||||
|
||||
|
||||
(defun spacemacs/cider-eval-sexp-end-of-line ()
|
||||
|
@ -54,7 +67,7 @@
|
|||
(indent-region pt-max (point))
|
||||
(cider-repl-return)
|
||||
(with-selected-window (get-buffer-window (cider-current-connection))
|
||||
(goto-char (point-max))))))
|
||||
(goto-char (point-max))))))
|
||||
|
||||
(defun spacemacs/cider-send-last-sexp-to-repl ()
|
||||
"Send last sexp to REPL and evaluate it without changing
|
||||
|
|
14
layers/+lang/clojure/layers.el
Normal file
14
layers/+lang/clojure/layers.el
Normal file
|
@ -0,0 +1,14 @@
|
|||
;;; layers.el --- Clojure Layer layers File for Spacemacs
|
||||
;;
|
||||
;; Copyright (c) 2012-2020 Sylvain Benner & Contributors
|
||||
;;
|
||||
;; Author: Maximilian Wolff <smile13241324@gmail.com>
|
||||
;; URL: https://github.com/syl20bnr/spacemacs
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;;; License: GPLv3
|
||||
|
||||
(when (and (boundp 'clojure-backend)
|
||||
(eq clojure-backend 'lsp))
|
||||
(configuration-layer/declare-layer-dependencies '(lsp)))
|
|
@ -9,36 +9,36 @@
|
|||
;;
|
||||
;;; License: GPLv3
|
||||
|
||||
(setq clojure-packages
|
||||
'(
|
||||
cider
|
||||
cider-eval-sexp-fu
|
||||
(clj-refactor :toggle clojure-enable-clj-refactor)
|
||||
(helm-cider :toggle (configuration-layer/layer-used-p 'helm))
|
||||
clojure-mode
|
||||
(clojure-snippets :toggle (configuration-layer/layer-used-p 'auto-completion))
|
||||
company
|
||||
eldoc
|
||||
evil-cleverparens
|
||||
flycheck
|
||||
(flycheck-clojure :toggle (memq 'squiggly (if (listp clojure-enable-linters)
|
||||
clojure-enable-linters
|
||||
(list clojure-enable-linters))))
|
||||
(flycheck-clj-kondo :toggle (memq 'clj-kondo (if (listp clojure-enable-linters)
|
||||
clojure-enable-linters
|
||||
(list clojure-enable-linters))))
|
||||
(flycheck-joker :toggle (memq 'joker (if (listp clojure-enable-linters)
|
||||
clojure-enable-linters
|
||||
(list clojure-enable-linters))))
|
||||
ggtags
|
||||
counsel-gtags
|
||||
helm-gtags
|
||||
org
|
||||
parinfer
|
||||
popwin
|
||||
(sayid :toggle clojure-enable-sayid)
|
||||
smartparens
|
||||
subword))
|
||||
(defconst clojure-packages
|
||||
'(
|
||||
cider
|
||||
cider-eval-sexp-fu
|
||||
(clj-refactor :toggle clojure-enable-clj-refactor)
|
||||
(helm-cider :toggle (configuration-layer/layer-used-p 'helm))
|
||||
clojure-mode
|
||||
(clojure-snippets :toggle (configuration-layer/layer-used-p 'auto-completion))
|
||||
company
|
||||
eldoc
|
||||
evil-cleverparens
|
||||
flycheck
|
||||
(flycheck-clojure :toggle (memq 'squiggly (if (listp clojure-enable-linters)
|
||||
clojure-enable-linters
|
||||
(list clojure-enable-linters))))
|
||||
(flycheck-clj-kondo :toggle (memq 'clj-kondo (if (listp clojure-enable-linters)
|
||||
clojure-enable-linters
|
||||
(list clojure-enable-linters))))
|
||||
(flycheck-joker :toggle (memq 'joker (if (listp clojure-enable-linters)
|
||||
clojure-enable-linters
|
||||
(list clojure-enable-linters))))
|
||||
ggtags
|
||||
counsel-gtags
|
||||
helm-gtags
|
||||
org
|
||||
parinfer
|
||||
popwin
|
||||
(sayid :toggle clojure-enable-sayid)
|
||||
smartparens
|
||||
subword))
|
||||
|
||||
|
||||
(defun clojure/init-cider ()
|
||||
|
@ -64,14 +64,11 @@
|
|||
;; TODO: having this work for cider-macroexpansion-mode would be nice,
|
||||
;; but the problem is that it uses clojure-mode as its major-mode
|
||||
(let ((cider--key-binding-prefixes
|
||||
'(("m=" . "format")
|
||||
("m=e" . "edn")
|
||||
'(("m=e" . "edn")
|
||||
("md" . "debug")
|
||||
("mdv" . "inspect values")
|
||||
("me" . "evaluation")
|
||||
("mep" . "pretty print")
|
||||
("mg" . "goto")
|
||||
("mh" . "documentation")
|
||||
("mm" . "manage repls")
|
||||
("mml" . "link session")
|
||||
("mmS" . "sibling sessions")
|
||||
|
@ -81,31 +78,39 @@
|
|||
("msc" . "connect external repl")
|
||||
("msj" . "jack-in")
|
||||
("msq" . "quit/restart repl")
|
||||
("mt" . "test")
|
||||
("mt" . "test")))
|
||||
(cider--key-binding-non-lsp-prefixes
|
||||
'(("m=" . "format")
|
||||
("mg" . "goto") ;; no lsp
|
||||
("mh" . "documentation")
|
||||
("mT" . "toggle"))))
|
||||
|
||||
(spacemacs|forall-clojure-modes m
|
||||
(mapc (lambda (x) (spacemacs/declare-prefix-for-mode
|
||||
m (car x) (cdr x)))
|
||||
cider--key-binding-prefixes)
|
||||
|
||||
(unless (eq (spacemacs//clojure-backend) 'lsp)
|
||||
(mapc (lambda (x) (spacemacs/declare-prefix-for-mode
|
||||
m (car x) (cdr x)))
|
||||
cider--key-binding-non-lsp-prefixes)
|
||||
(spacemacs/set-leader-keys-for-major-mode m
|
||||
"hh" 'cider-doc
|
||||
"=r" 'cider-format-region
|
||||
"ge" 'cider-jump-to-compilation-error
|
||||
"gr" 'cider-find-resource
|
||||
"gs" 'cider-browse-spec
|
||||
"gS" 'cider-browse-spec-all))
|
||||
(spacemacs/set-leader-keys-for-major-mode m
|
||||
|
||||
;; shortcuts
|
||||
"'" 'sesman-start
|
||||
|
||||
;; help / documentation
|
||||
"ha" 'cider-apropos
|
||||
"hc" 'cider-cheatsheet
|
||||
"hd" 'cider-clojuredocs
|
||||
"hh" 'cider-doc
|
||||
"hj" 'cider-javadoc
|
||||
"hn" 'cider-browse-ns
|
||||
"hN" 'cider-browse-ns-all
|
||||
"hs" 'cider-browse-spec
|
||||
"hS" 'cider-browse-spec-all
|
||||
|
||||
|
||||
;; evaluate in source code buffer
|
||||
"e;" 'cider-eval-defun-to-comment
|
||||
"e$" 'spacemacs/cider-eval-sexp-end-of-line
|
||||
|
@ -128,25 +133,17 @@
|
|||
"ev" 'cider-eval-sexp-at-point
|
||||
"eV" 'cider-eval-sexp-up-to-point
|
||||
"ew" 'cider-eval-last-sexp-and-replace
|
||||
|
||||
;; format code style
|
||||
"==" 'cider-format-buffer
|
||||
"=eb" 'cider-format-edn-buffer
|
||||
"=ee" 'cider-format-edn-last-sexp
|
||||
"=er" 'cider-format-edn-region
|
||||
"=f" 'cider-format-defun
|
||||
"=r" 'cider-format-region
|
||||
|
||||
;; goto
|
||||
"gb" 'cider-pop-back
|
||||
"gc" 'cider-classpath
|
||||
"gg" 'spacemacs/clj-find-var
|
||||
"ge" 'cider-jump-to-compilation-error
|
||||
"gn" 'cider-find-ns
|
||||
"gr" 'cider-find-resource
|
||||
"gs" 'cider-browse-spec
|
||||
"gS" 'cider-browse-spec-all
|
||||
|
||||
;; manage cider connections / sesman
|
||||
"mb" 'sesman-browser
|
||||
"mi" 'sesman-info
|
||||
|
@ -160,7 +157,6 @@
|
|||
"mSj" 'cider-connect-sibling-clj
|
||||
"mSs" 'cider-connect-sibling-cljs
|
||||
"ms" 'sesman-start
|
||||
|
||||
;; send code - spacemacs convention
|
||||
"sa" (if (eq m 'cider-repl-mode)
|
||||
'cider-switch-to-last-clojure-buffer
|
||||
|
@ -190,13 +186,11 @@
|
|||
"sr" 'spacemacs/cider-send-region-to-repl
|
||||
"sR" 'spacemacs/cider-send-region-to-repl-focus
|
||||
"su" 'cider-repl-require-repl-utils
|
||||
|
||||
;; toggle options
|
||||
"Te" 'cider-enlighten-mode
|
||||
"Tf" 'spacemacs/cider-toggle-repl-font-locking
|
||||
"Tp" 'spacemacs/cider-toggle-repl-pretty-printing
|
||||
"Tt" 'cider-auto-test-mode
|
||||
|
||||
;; cider-tests
|
||||
"ta" 'spacemacs/cider-test-run-all-tests
|
||||
"tb" 'cider-test-show-report
|
||||
|
@ -205,7 +199,6 @@
|
|||
"tp" 'spacemacs/cider-test-run-project-tests
|
||||
"tr" 'spacemacs/cider-test-rerun-failed-tests
|
||||
"tt" 'spacemacs/cider-test-run-focused-test
|
||||
|
||||
;; cider-debug and inspect
|
||||
"db" 'cider-debug-defun-at-point
|
||||
"de" 'spacemacs/cider-display-error-buffer
|
||||
|
@ -214,7 +207,6 @@
|
|||
"dvi" 'cider-inspect
|
||||
"dvl" 'cider-inspect-last-result
|
||||
"dvv" 'cider-inspect-expr
|
||||
|
||||
;; profile
|
||||
"p+" 'cider-profile-samples
|
||||
"pc" 'cider-profile-clear
|
||||
|
@ -224,7 +216,6 @@
|
|||
"pt" 'cider-profile-toggle
|
||||
"pv" 'cider-profile-var-profiled-p)))
|
||||
|
||||
|
||||
;; cider-repl-mode only
|
||||
(spacemacs/set-leader-keys-for-major-mode 'cider-repl-mode
|
||||
"," 'cider-repl-handle-shortcut)
|
||||
|
@ -351,10 +342,10 @@
|
|||
(add-to-list 'auto-mode-alist '("\\.boot\\'" . clojure-mode))
|
||||
;; This regexp matches shebang expressions like `#!/usr/bin/env boot'
|
||||
(add-to-list 'magic-mode-alist '("#!.*boot\\s-*$" . clojure-mode))
|
||||
(add-hook 'clojure-mode-hook #'spacemacs//clojure-setup-backend)
|
||||
;; Define all the prefixes here, although most of them apply only to bindings in clj-refactor
|
||||
(let ((clj-refactor--key-binding-prefixes
|
||||
'(("mr" . "refactor")
|
||||
("mra" . "add")
|
||||
'(("mra" . "add")
|
||||
("mrc" . "cycle/clean/convert")
|
||||
("mrd" . "destructure")
|
||||
("mre" . "extract/expand")
|
||||
|
@ -366,11 +357,17 @@
|
|||
("mrr" . "remove/rename/replace")
|
||||
("mrs" . "show/sort/stop")
|
||||
("mrt" . "thread")
|
||||
("mru" . "unwind/update"))))
|
||||
("mru" . "unwind/update")))
|
||||
(clj-refactor--key-binding-non-lsp-prefixes
|
||||
'(("mr" . "refactor"))))
|
||||
(spacemacs|forall-clojure-modes m
|
||||
(mapc (lambda (x) (spacemacs/declare-prefix-for-mode
|
||||
m (car x) (cdr x)))
|
||||
clj-refactor--key-binding-prefixes)
|
||||
(unless (eq (spacemacs//clojure-backend) 'lsp)
|
||||
(mapc (lambda (x) (spacemacs/declare-prefix-for-mode
|
||||
m (car x) (cdr x)))
|
||||
clj-refactor--key-binding-non-lsp-prefixes))
|
||||
(spacemacs/set-leader-keys-for-major-mode m
|
||||
"=l" 'clojure-align
|
||||
"ran" 'clojure-insert-ns-form
|
||||
|
@ -430,9 +427,7 @@
|
|||
(defun clojure/post-init-company ()
|
||||
(spacemacs|add-company-backends
|
||||
:backends company-capf
|
||||
:modes
|
||||
cider-mode
|
||||
cider-repl-mode))
|
||||
:modes clojure-mode clojurec-mode clojurescript-mode clojurex-mode cide-clojure-interaction-mode cider-mode cider-repl-mode))
|
||||
|
||||
(defun clojure/post-init-ggtags ()
|
||||
(add-hook 'clojure-mode-local-vars-hook #'spacemacs/ggtags-mode-enable))
|
||||
|
|
Loading…
Reference in a new issue