diff --git a/CHANGELOG.md b/CHANGELOG.md index bd27aecab..0471a2415 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ * [#2373](https://github.com/clojure-emacs/cider/issues/2373): Make it possible to configure the welcome message displayed in scratch buffers via `cider-scratch-initial-message`. * Add the ability to jump to the profiler buffer using `cider-selector`. * [#1980](https://github.com/clojure-emacs/cider/issues/1980): Echo back missing namespace name on interactive eval (requires nREPL 0.4.3+). +* [#2397](https://github.com/clojure-emacs/cider/pull/2397): Add shadow-select CLJS REPL type. ### Bugs fixed diff --git a/cider.el b/cider.el index 6e188513f..00064c9ab 100644 --- a/cider.el +++ b/cider.el @@ -682,12 +682,38 @@ Generally you should not disable this unless you run into some faulty check." (unless (cider-library-present-p "thheller/shadow-cljs") (user-error "The shadow-cljs ClojureScript REPL is not available"))) +(defun cider-normalize-cljs-init-options (options) + "Normalize the OPTIONS string used for initializing a CLJS REPL." + (if (or (string-prefix-p "{" options) + (string-prefix-p "(" options) + (string-prefix-p "[" options) + (string-prefix-p ":" options)) + options + (concat ":" options))) + +(defcustom cider-shadow-default-options nil + "Defines default `shadow-cljs' options." + :type 'string + :safe (lambda (s) (or (null s) (stringp s))) + :package-version '(cider . "0.18.0")) + +(defun cider-shadow-select-cljs-init-form () + "Generate the init form for a shadow-cljs select-only REPL. +We have to prompt the user to select a build, that's why this is a command, +not just a string." + (let ((form "(do (require '[shadow.cljs.devtools.api :as shadow]) (shadow/nrepl-select :%s))") + (options (or cider-shadow-default-options + (read-from-minibuffer "Select shadow-cljs build (e.g. dev): ")))) + (format form (cider-normalize-cljs-init-options options)))) + (defun cider-shadow-cljs-init-form () "Generate the init form for a shadow-cljs REPL. We have to prompt the user to select a build, that's why this is a command, not just a string." - (let ((form "(do (require '[shadow.cljs.devtools.api :as shadow]) (shadow/watch :%s) (shadow/nrepl-select :%s))") - (build (string-remove-prefix ":" (read-from-minibuffer "Select shadow-cljs build (e.g. dev): ")))) + (let* ((form "(do (require '[shadow.cljs.devtools.api :as shadow]) (shadow/watch :%s) (shadow/nrepl-select :%s))") + (options (or cider-shadow-default-options + (read-from-minibuffer "Select shadow-cljs build (e.g. dev): "))) + (build (cider-normalize-cljs-init-options options))) (format form build build))) (defcustom cider-figwheel-main-default-options nil @@ -701,16 +727,11 @@ Figwheel for details." (defun cider-figwheel-main-init-form () "Produce the figwheel-main ClojureScript init form." - (let* ((form "(do (require 'figwheel.main) (figwheel.main/start %s))") - (options (string-trim - (or cider-figwheel-main-default-options - (read-from-minibuffer "Select figwheel-main build (e.g. :dev): ")))) - (normalized-options (if (or (string-prefix-p "{" options) - (string-prefix-p "(" options) - (string-prefix-p ":" options)) - options - (concat ":" options)))) - (format form normalized-options))) + (let ((form "(do (require 'figwheel.main) (figwheel.main/start %s))") + (options (string-trim + (or cider-figwheel-main-default-options + (read-from-minibuffer "Select figwheel-main build (e.g. :dev): "))))) + (format form (cider-normalize-cljs-init-options options)))) (defun cider-custom-cljs-repl-init-form () "Prompt for a form that would start a ClojureScript REPL. @@ -735,6 +756,7 @@ The supplied string will be wrapped in a do form if needed." (boot "(do (require 'adzerk.boot-cljs-repl) (adzerk.boot-cljs-repl/start-repl))" cider-check-boot-requirements) (shadow cider-shadow-cljs-init-form cider-check-shadow-cljs-requirements) + (shadow-select cider-shadow-select-cljs-init-form cider-check-shadow-cljs-requirements) (custom cider-custom-cljs-repl-init-form nil)) "A list of supported ClojureScript REPLs. diff --git a/doc/clojurescript.md b/doc/clojurescript.md index be7110d5d..d4b665eed 100644 --- a/doc/clojurescript.md +++ b/doc/clojurescript.md @@ -254,6 +254,10 @@ npx shadow-cljs server And connect to it with `cider-connect`. +Lastly, if you already have a running server watching a build, for instance you +have already run `npx shadow-cljs watch :dev`, you can use the `shadow-select` +CLJS REPL and specify `:dev` when prompted. + [leiningen]: http://leiningen.org/ [boot]: http://boot-clj.com/ [piggieback]: https://github.com/nrepl/piggieback diff --git a/test/cider-tests.el b/test/cider-tests.el index e812207cc..070557a46 100644 --- a/test/cider-tests.el +++ b/test/cider-tests.el @@ -207,6 +207,19 @@ :and-return-value '()) (expect (cider-project-type) :to-equal cider-default-repl-command)))) +(describe "cider-normalize-cljs-init-options" + (describe "from options" + (it "leaves keywords alone" + (expect (cider-normalize-cljs-init-options ":dev") :to-equal ":dev")) + (it "leaves maps alone" + (expect (cider-normalize-cljs-init-options "{:a 1 :b 2}") :to-equal "{:a 1 :b 2}")) + (it "leaves s-exprs alone" + (expect (cider-normalize-cljs-init-options "(hashmap :a 1 :b 2)") :to-equal "(hashmap :a 1 :b 2)")) + (it "leaves vectors alone" + (expect (cider-normalize-cljs-init-options "[1 2 3]") :to-equal "[1 2 3]")) + (it "prepends colon to plain names" + (expect (cider-normalize-cljs-init-options "dev") :to-equal ":dev")))) + (describe "cider-figwheel-main-init-form" ;; whitespace checks sprinkled amongst other tests (describe "from options"