Skip to content

Instantly share code, notes, and snippets.

@bhb
Last active May 15, 2023 01:28
Show Gist options
  • Save bhb/2686b023d074ac052dbc21f12f324f18 to your computer and use it in GitHub Desktop.
Save bhb/2686b023d074ac052dbc21f12f324f18 to your computer and use it in GitHub Desktop.
Clojure friendly mode, inspired by https://github.com/slipset/friendly

Friendly

A beginner-friendly REPL that combines

Usage

JVM 8:

clojure -Sdeps '{:deps {friendly {:git/url "https://gist.github.com/bhb/2686b023d074ac052dbc21f12f324f18" :sha "d532662414376900c13bed9c920181651e1efeff"}}}' -X friendly/run

JVM 9 or newer:

clojure -Sdeps '{:deps {friendly {:git/url "https://gist.github.com/bhb/2686b023d074ac052dbc21f12f324f18" :sha "d532662414376900c13bed9c920181651e1efeff"}}}' -X friendly/run

Credits

Inspired by https://github.com/slipset/friendly

I learned the technique of loading code via a gist from https://gist.github.com/athos/b68b15b08efedffaf14d8c020b125202

{:paths ["."]
:deps {com.bhauman/rebel-readline {:mvn/version "0.1.4"}
expound/expound {:mvn/version "0.9.0"}
org.clojure/core.specs.alpha {:mvn/version "0.2.62"}
speculative/speculative {:git/url "https://github.com/borkdude/speculative.git"
:sha "4e773794a4065a84bdadd997516e52c76ab51b1f"}}}
(ns friendly
(:require [rebel-readline.clojure.main]
[expound.alpha :as expound]
[clojure.spec.alpha :as s]
[clojure.stacktrace]
[clojure.main]
;; for specs
[speculative.instrument :as speculative]))
(expound/defmsg :speculative.specs/ifn "should be a function (or a value that can be *treated* like a function e.g. a set or keyword)")
(def printer (expound/custom-printer {:print-specs? false
:show-valid-values? true
:theme :figwheel-theme}))
(defn repl-caught [e]
(let [ex (clojure.main/repl-exception e)
tr (.getStackTrace ex)
el (when-not (zero? (count tr)) (aget tr 0))
ex-m (Throwable->map ex)]
(binding [*out* *err*]
(cond
;; If the output is a clojure spec issue...
(::s/problems (:data ex-m))
;; print expound output
(do
(println (str (re-find #"Call to .* did not conform to spec\:" (.getMessage ex))
"\n"
(with-out-str (printer (:data ex-m))))))
(instance? clojure.lang.LispReader$ReaderException e)
(println (:cause (Throwable->map e)))
:else
;; otherwise print exception
(println (str (if (instance? clojure.lang.Compiler$CompilerException ex)
(str
(-> ex class .getSimpleName)
" " (.getMessage ex) " ")
(str " " (if el
(clojure.stacktrace/print-stack-trace ex)
"[trace missing]")))))))))
(speculative/instrument)
(set! s/*explain-out* printer)
(defn run [_opts]
(rebel-readline.clojure.main/repl :caught repl-caught))
@idrozd
Copy link

idrozd commented Jul 9, 2018

Thank you a lot!
I've tried to jump-start this from under my long-abandoned "clojure-playground" folder, and I've got this:

Caused by: java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter

What am I missing?

❯ java --version
java 10.0.1 2018-04-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)

❯ clj
Clojure 1.9.0

❯ clj -Sdeps '{:deps {friendly {:git/url "https://gist.github.com/bhb/2686b023d074ac052dbc21f12f324f18" :sha "a6a6727f68d52d9024079bdd93fab87222993ae5"}}}' -m friendly

Cloning: https://gist.github.com/bhb/2686b023d074ac052dbc21f12f324f18
Checking out: https://gist.github.com/bhb/2686b023d074ac052dbc21f12f324f18 at a6a6727f68d52d9024079bdd93fab87222993ae5
Downloading: com/bhauman/rebel-readline/0.1.4/rebel-readline-0.1.4.pom from https://clojars.org/repo/
Downloading: venantius/pyro/0.1.2/pyro-0.1.2.pom from https://clojars.org/repo/
Downloading: expound/expound/0.7.1/expound-0.7.1.pom from https://clojars.org/repo/
Downloading: org/jline/jline-reader/3.5.1/jline-reader-3.5.1.pom from https://repo1.maven.org/maven2/
Downloading: org/jline/jline-parent/3.5.1/jline-parent-3.5.1.pom from https://repo1.maven.org/maven2/
Downloading: org/jline/jline-terminal/3.5.1/jline-terminal-3.5.1.pom from https://repo1.maven.org/maven2/
Downloading: org/jline/jline-terminal-jansi/3.5.1/jline-terminal-jansi-3.5.1.pom from https://repo1.maven.org/maven2/
Downloading: cljfmt/cljfmt/0.5.7/cljfmt-0.5.7.pom from https://clojars.org/repo/
Downloading: compliment/compliment/0.3.6/compliment-0.3.6.pom from https://clojars.org/repo/
Downloading: venantius/glow/0.1.5/glow-0.1.5.pom from https://clojars.org/repo/
Downloading: org/fusesource/jansi/jansi/1.16/jansi-1.16.pom from https://repo1.maven.org/maven2/
Downloading: org/fusesource/jansi/jansi-project/1.16/jansi-project-1.16.pom from https://repo1.maven.org/maven2/
Downloading: org/fusesource/fusesource-pom/1.11/fusesource-pom-1.11.pom from https://repo1.maven.org/maven2/
Downloading: org/clojure/tools.reader/1.0.0-alpha4/tools.reader-1.0.0-alpha4.pom from https://repo1.maven.org/maven2/
Downloading: rewrite-clj/rewrite-clj/0.5.2/rewrite-clj-0.5.2.pom from https://clojars.org/repo/
Downloading: rewrite-cljs/rewrite-cljs/0.4.3/rewrite-cljs-0.4.3.pom from https://clojars.org/repo/
Downloading: expound/expound/0.7.1/expound-0.7.1.jar from https://clojars.org/repo/
Downloading: venantius/glow/0.1.5/glow-0.1.5.jar from https://clojars.org/repo/
Downloading: org/jline/jline-terminal-jansi/3.5.1/jline-terminal-jansi-3.5.1.jar from https://repo1.maven.org/maven2/
Downloading: com/bhauman/rebel-readline/0.1.4/rebel-readline-0.1.4.jar from https://clojars.org/repo/
Downloading: cljfmt/cljfmt/0.5.7/cljfmt-0.5.7.jar from https://clojars.org/repo/
Downloading: rewrite-clj/rewrite-clj/0.5.2/rewrite-clj-0.5.2.jar from https://clojars.org/repo/
Downloading: org/clojure/clojurescript/1.7.228/clojurescript-1.7.228.jar from https://repo1.maven.org/maven2/
Downloading: venantius/pyro/0.1.2/pyro-0.1.2.jar from https://clojars.org/repo/
Downloading: org/fusesource/jansi/jansi/1.16/jansi-1.16.jar from https://repo1.maven.org/maven2/
Downloading: com/google/javascript/closure-compiler/v20151216/closure-compiler-v20151216.jar from https://repo1.maven.org/maven2/
Downloading: org/clojure/tools.reader/1.0.0-alpha4/tools.reader-1.0.0-alpha4.jar from https://repo1.maven.org/maven2/
Downloading: compliment/compliment/0.3.6/compliment-0.3.6.jar from https://clojars.org/repo/
Downloading: org/jline/jline-terminal/3.5.1/jline-terminal-3.5.1.jar from https://repo1.maven.org/maven2/
Downloading: org/jline/jline-reader/3.5.1/jline-reader-3.5.1.jar from https://repo1.maven.org/maven2/
Downloading: rewrite-cljs/rewrite-cljs/0.4.3/rewrite-cljs-0.4.3.jar from https://clojars.org/repo/
Exception in thread "main" java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter, compiling:(pyro/source.clj:1:1)
	at clojure.lang.Compiler.load(Compiler.java:7526)
	at clojure.lang.RT.loadResourceScript(RT.java:379)
	at clojure.lang.RT.loadResourceScript(RT.java:370)
	at clojure.lang.RT.load(RT.java:460)
	at clojure.lang.RT.load(RT.java:426)
	at clojure.core$load$fn__6548.invoke(core.clj:6046)
	at clojure.core$load.invokeStatic(core.clj:6045)
	at clojure.core$load.doInvoke(core.clj:6029)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invokeStatic(core.clj:5848)
	at clojure.core$load_one.invoke(core.clj:5843)
	at clojure.core$load_lib$fn__6493.invoke(core.clj:5888)
	at clojure.core$load_lib.invokeStatic(core.clj:5887)
	at clojure.core$load_lib.doInvoke(core.clj:5868)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$load_libs.invokeStatic(core.clj:5925)
	at clojure.core$load_libs.doInvoke(core.clj:5909)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$require.invokeStatic(core.clj:5947)
	at clojure.core$require.doInvoke(core.clj:5947)
	at clojure.lang.RestFn.invoke(RestFn.java:512)
	at pyro.printer$eval153$loading__6434__auto____154.invoke(printer.clj:1)
	at pyro.printer$eval153.invokeStatic(printer.clj:1)
	at pyro.printer$eval153.invoke(printer.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:7062)
	at clojure.lang.Compiler.eval(Compiler.java:7051)
	at clojure.lang.Compiler.load(Compiler.java:7514)
	at clojure.lang.RT.loadResourceScript(RT.java:379)
	at clojure.lang.RT.loadResourceScript(RT.java:370)
	at clojure.lang.RT.load(RT.java:460)
	at clojure.lang.RT.load(RT.java:426)
	at clojure.core$load$fn__6548.invoke(core.clj:6046)
	at clojure.core$load.invokeStatic(core.clj:6045)
	at clojure.core$load.doInvoke(core.clj:6029)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invokeStatic(core.clj:5848)
	at clojure.core$load_one.invoke(core.clj:5843)
	at clojure.core$load_lib$fn__6493.invoke(core.clj:5888)
	at clojure.core$load_lib.invokeStatic(core.clj:5887)
	at clojure.core$load_lib.doInvoke(core.clj:5868)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$load_libs.invokeStatic(core.clj:5925)
	at clojure.core$load_libs.doInvoke(core.clj:5909)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$require.invokeStatic(core.clj:5947)
	at clojure.core$require.doInvoke(core.clj:5947)
	at clojure.lang.RestFn.invoke(RestFn.java:551)
	at friendly$eval147$loading__6434__auto____148.invoke(friendly.clj:1)
	at friendly$eval147.invokeStatic(friendly.clj:1)
	at friendly$eval147.invoke(friendly.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:7062)
	at clojure.lang.Compiler.eval(Compiler.java:7051)
	at clojure.lang.Compiler.load(Compiler.java:7514)
	at clojure.lang.RT.loadResourceScript(RT.java:379)
	at clojure.lang.RT.loadResourceScript(RT.java:370)
	at clojure.lang.RT.load(RT.java:460)
	at clojure.lang.RT.load(RT.java:426)
	at clojure.core$load$fn__6548.invoke(core.clj:6046)
	at clojure.core$load.invokeStatic(core.clj:6045)
	at clojure.core$load.doInvoke(core.clj:6029)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invokeStatic(core.clj:5848)
	at clojure.core$load_one.invoke(core.clj:5843)
	at clojure.core$load_lib$fn__6493.invoke(core.clj:5888)
	at clojure.core$load_lib.invokeStatic(core.clj:5887)
	at clojure.core$load_lib.doInvoke(core.clj:5868)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$load_libs.invokeStatic(core.clj:5925)
	at clojure.core$load_libs.doInvoke(core.clj:5909)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$require.invokeStatic(core.clj:5947)
	at clojure.main$main_opt.invokeStatic(main.clj:317)
	at clojure.main$main_opt.invoke(main.clj:313)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:466)
	at clojure.lang.DynamicClassLoader.findClass(DynamicClassLoader.java:69)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:566)
	at clojure.lang.DynamicClassLoader.loadClass(DynamicClassLoader.java:77)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:374)
	at clojure.lang.RT.classForName(RT.java:2204)
	at clojure.lang.RT.classForNameNonLoading(RT.java:2217)
	at pyro.source$eval268$loading__6434__auto____269.invoke(source.clj:1)
	at pyro.source$eval268.invokeStatic(source.clj:1)
	at pyro.source$eval268.invoke(source.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:7062)
	at clojure.lang.Compiler.eval(Compiler.java:7051)
	at clojure.lang.Compiler.load(Compiler.java:7514)
	... 83 more

@souenzzo
Copy link

souenzzo commented Jul 9, 2018

Reported to pyro
venantius/pyro#23
@idrozd it's a issue with JVM9+, you can "fix" using JVM8 or add the --add-modules java.xml.bind on jvm9+

@andnils
Copy link

andnils commented Jul 10, 2018

This should work:
clj -J--add-modules=java.xml.bind -Sdeps '{:deps {friendly {:git/url "https://gist.github.com/bhb/2686b023d074ac052dbc21f12f324f18" :sha "418bf66fd96851cc55398b55d5a8aff65692f565"}}}' -m friendly

@bhb
Copy link
Author

bhb commented Sep 7, 2018

Thanks @andnils for the fix!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment