lynaghk / cljx Goto Github PK
View Code? Open in Web Editor NEWWrite a portable codebase targeting Clojure/ClojureScript
License: Other
Write a portable codebase targeting Clojure/ClojureScript
License: Other
Similar to what Austin does.
Middleware, middleware, everywhere. o.O
Hi Chas,
Thanks for the release of 0.5.0! Just tried it out, and I'm seeing a StackOverflowError on lein cljx once
(running Leiningen 2.4.2):
lein cljx once
Exception in thread "main" java.lang.StackOverflowError
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.boundedLength(RT.java:1654)
at clojure.lang.AFn.applyToHelper(AFn.java:148)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:626)
at clojure.core$partial$fn__4228.doInvoke(core.clj:2468)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$map$fn__4245.invoke(core.clj:2559)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:484)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core$apply.invoke(core.clj:624)
at clojure.walk$walk.invoke(walk.clj:44)
at clojure.walk$postwalk.invoke(walk.clj:58)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:626)
at clojure.core$partial$fn__4228.doInvoke(core.clj:2468)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$map$fn__4245.invoke(core.clj:2559)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.boundedLength(RT.java:1654)
at clojure.lang.RestFn.applyTo(RestFn.java:130)
at clojure.core$apply.invoke(core.clj:624)
at clojure.walk$walk.invoke(walk.clj:44)
at clojure.walk$postwalk.invoke(walk.clj:58)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:626)
at clojure.core$partial$fn__4228.doInvoke(core.clj:2468)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$map$fn__4245.invoke(core.clj:2559)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.PersistentList$1.doInvoke(PersistentList.java:37)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:624)
at clojure.walk$walk.invoke(walk.clj:44)
at clojure.walk$postwalk.invoke(walk.clj:58)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:626)
at clojure.core$partial$fn__4228.doInvoke(core.clj:2468)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$map$fn__4245.invoke(core.clj:2557)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:484)
at clojure.lang.LazilyPersistentVector.create(LazilyPersistentVector.java:31)
at clojure.core$vec.invoke(core.clj:354)
at clojure.walk$walk.invoke(walk.clj:45)
at clojure.walk$postwalk.invoke(walk.clj:58)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:626)
at clojure.core$partial$fn__4228.doInvoke(core.clj:2468)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$map$fn__4245.invoke(core.clj:2559)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:484)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core.protocols$seq_reduce.invoke(protocols.clj:30)
at clojure.core.protocols$fn__6078.invoke(protocols.clj:54)
at clojure.core.protocols$fn__6031$G__6026__6044.invoke(protocols.clj:13)
at clojure.core$reduce.invoke(core.clj:6289)
at clojure.core$into.invoke(core.clj:6341)
at clojure.walk$walk.invoke(walk.clj:49)
at clojure.walk$postwalk.invoke(walk.clj:58)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:626)
at clojure.core$partial$fn__4228.doInvoke(core.clj:2468)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$map$fn__4245.invoke(core.clj:2557)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:484)
at clojure.lang.LazilyPersistentVector.create(LazilyPersistentVector.java:31)
at clojure.core$vec.invoke(core.clj:354)
at clojure.walk$walk.invoke(walk.clj:45)
at clojure.walk$postwalk.invoke(walk.clj:58)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:626)
at clojure.core$partial$fn__4228.doInvoke(core.clj:2468)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$map$fn__4245.invoke(core.clj:2559)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:598)
at clojure.core$next.invoke(core.clj:64)
at clojure.core.protocols$fn__6086.invoke(protocols.clj:146)
at clojure.core.protocols$fn__6057$G__6052__6066.invoke(protocols.clj:19)
at clojure.core.protocols$seq_reduce.invoke(protocols.clj:31)
at clojure.core.protocols$fn__6078.invoke(protocols.clj:54)
at clojure.core.protocols$fn__6031$G__6026__6044.invoke(protocols.clj:13)
at clojure.core$reduce.invoke(core.clj:6289)
at clojure.core$into.invoke(core.clj:6341)
at clojure.walk$walk.invoke(walk.clj:49)
at clojure.walk$postwalk.invoke(walk.clj:58)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:626)
at clojure.core$partial$fn__4228.doInvoke(core.clj:2468)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$map$fn__4245.invoke(core.clj:2557)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:484)
at clojure.lang.LazilyPersistentVector.create(LazilyPersistentVector.java:31)
at clojure.core$vec.invoke(core.clj:354)
at clojure.walk$walk.invoke(walk.clj:45)
at clojure.walk$postwalk.invoke(walk.clj:58)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:626)
at clojure.core$partial$fn__4228.doInvoke(core.clj:2468)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$map$fn__4245.invoke(core.clj:2559)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:598)
at clojure.core$next.invoke(core.clj:64)
at clojure.core.protocols$fn__6086.invoke(protocols.clj:146)
at clojure.core.protocols$fn__6057$G__6052__6066.invoke(protocols.clj:19)
at clojure.core.protocols$seq_reduce.invoke(protocols.clj:31)
at clojure.core.protocols$fn__6078.invoke(protocols.clj:54)
at clojure.core.protocols$fn__6031$G__6026__6044.invoke(protocols.clj:13)
at clojure.core$reduce.invoke(core.clj:6289)
at clojure.core$into.invoke(core.clj:6341)
at clojure.walk$walk.invoke(walk.clj:49)
at clojure.walk$postwalk.invoke(walk.clj:58)
at clojure.walk$postwalk_replace.invoke(walk.clj:123)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:626)
at clojure.core$partial$fn__4228.doInvoke(core.clj:2468)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojurescript.test.plugin$middleware.invoke(plugin.clj:61)
at clojure.lang.Var.invoke(Var.java:379)
<...>
This is against Sente's dev branch, available here. Cljx version 0.4.0 was working fine, as was a fork using @lbradstreet's patch here - so I'm guessing this is maybe the result of one of the other changes, like sjacket?
Should have some free time later tonight; will try see if I can find a specific cause then. Just bringing this to your attention in the meantime and checking if you have any ideas off the top of your head?
Thanks again, cheers! :-)
In terms of generated output files, cljx works perfectly.
However, in terms of the repl, I am getting some errors when putting cljx readers into the (ns ) declaration.
Reproduce by
git clone [email protected]:samedhi/cljx-ns-trouble.git
cd cljx-ns-trouble
lein repl-headless
open emacs
start up nrepl
and connect to your repl-headless session
Then visit the file at cljx/trouble.cljx
Within emacs try
Ctrl-c Meta-n
=> RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:219)
Ctrl-c-k
works fine but then if you Ctrl-x-e
on expression at line 4 you get => Namespace not found
You can circumvent the errors by evaluating the expressions (including the ns declaration) one at a time, or by removing the cljx code from the ns declaration.
Hi Chas! Just thinking out loud here...
The two major workflow patterns seem to be:
/src/clj
, src/cljs
, src/cljx
dirs./src
dir with mixed .clj
, .cljs
, .cljx
files as necessary.In both of these cases there's a tricky choice that needs to be made when a namespace is predominantly but not entirely single-platform. The choice is:
.cljx
file with appropriate annotations everywhere.It occurs to me that an alternative may be worth thinking about:
.clj
, .cljs
, .cljx
.Within .cljx
files, we have the usual #+clj
and #+cljs
annotations.
Within .clj
files, everything is assumed to be #+clj
unless otherwise annotated.
Within .cljs
files, everything is assumed to be #+cljs
unless otherwise annotated.
This'd allow a convenient third choice to the problem above: use a file extension (.clj
/.cljs
) appropriate for the majority of the ns code and add a minimal number of annotations for the few alternate-platform bits.
(With this capability I'd suggest that the second workflow pattern would make a sensible default recommendation btw, but that's tangential).
There is a snag:
There would be an ambiguity in .clj
/.cljs
files whether #+cljs
/#+clj
means "this code only for that platform", or "also" for that platform. Some ideas off the top of my head:
#+cljx
annotation to mean "both platforms" [1].#+clj-also
#+cljs-also
or equivalent annotations (my preference).#+clj
and #+cljs
to both coexist on the same form somehow (seems distasteful + possibly tricky?).[1] At first I thought the #+cljx
annotation may be limiting (what if we have additional platforms later?) - but in fact this is the default behaviour anyway with .cljx
files currently so may be reasonable.
Curious to get your feedback on this. Anyway, enjoy the rest of your weekend - cheers! :-)
We should update piggieback dependency to 0.1.5 to support CLJS 0.0-2665. Now with CLJS 0.0-2665 it can happen that lein cljx once
works but we'll get an error missing implementation of the new 2 arg -setup
method from IJavaScriptEnv (https://github.com/clojure/clojurescript/wiki/Custom-REPLs#expectations) when running a repl with piggieback middleware.
I'd like to make some server environment variables available to CLJS, through something like environ
. Does cljx enable this sort of functionality?
Here is a test repository where I enabled :hooks
for both cljsbuild
and cljx
:
git clone https://github.com/magomimmo/modern-cljs.git
cd modern-cljs
git checkout double
$ lein do clean, compile, test
Deleting files generated by lein-cljsbuild.
Rewriting test/cljx to target/test/clj (clj) with features #{clj} and 0 transformations.
Rewriting test/cljx to target/test/cljs (cljs) with features #{cljs} and 1 transformations.
Compiling ClojureScript.
Compiling "resources/public/js/modern_pre.js" from ["src/brepl" "src/cljs"]...
...
...
Successfully compiled "target/test/js/testable.js" in 7.192822 seconds.
Rewriting test/cljx to target/test/clj (clj) with features #{clj} and 0 transformations.
Rewriting test/cljx to target/test/cljs (cljs) with features #{cljs} and 1 transformations.
Compiling ClojureScript.
Compiling "target/test/js/testable_dbg.js" from ["src/brepl" "src/cljs" "target/test/cljs"]...
...
...
Successfully compiled "target/test/js/testable.js" in 6.853873 seconds.
lein test modern-cljs.shopping.validators-test
Ran 1 tests containing 13 assertions.
0 failures, 0 errors.
Running all ClojureScript tests.
Testing modern-cljs.shopping.validators-test
Ran 1 tests containing 13 assertions.
....
{:test 1, :pass 13, :fail 0, :error 0, :type :summary}
$
I don-t know if this behavior pertains cljx
, cljsbuild
or even `lein.
Not sure if this is the intended behaviour, but it seems that attempting to exclude nested forms results in :cljx.core/exclude
being left over in the generated code. From line 33 of cljx.core (remove #(= % :cljx.core/exclude))
, it seems that this is by design because a remove is performed instead of a walk. Would it be possible to support this?
Example of input code that exhibits this problem:
(ns dali.core
^:clj
(:use [dali.macros :only (defshape)])
^:cljs
(:use-macros [dali.macros :only (defshape)]))
Not sure if this is some oversight on my part, or a bug, so I'll report it here. I'm running Clojure 1.7.0-alpha2, cljx 0.6.0, using CIDER nrepl 0.8.2.
Leiningen 2.4.2 on Java 1.8.0_11 Java HotSpot(TM) 64-Bit Server VM
We've been using cljx for a while with no issues, but just noticed an error with the following code snippet inside a cljx file:
#+clj
(defn foo []
\x)
Compiling that namespace yields "No reader function for tag +clj". If I remove the #+clj
, or if I replace the \x
with "x"
, all works well.
On Windows, :source-paths has to be defined as "src\cljx" otherwise it's ignored and the generated files end up in the same directory as the original files. This is because of line 49 of cljx.core which uses a regular expression to do path manipulation: (string/replace cljx-path output-path).
Hi Chas,
Upgrading from Cljx 0.4.0 to 0.6.0 produces the following new error on lein check
:
Exception in thread "main" java.lang.Exception: namespace 'cemerick.piggieback' not found, compiling:(cljx/repl_middleware.clj:1:1)
at clojure.core$throw_if.doInvoke(core.clj:5572)
at clojure.lang.RestFn.invoke(RestFn.java:442)
at clojure.core$load_lib.doInvoke(core.clj:5658)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:628)
at clojure.core$load_libs.doInvoke(core.clj:5691)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:628)
at clojure.core$require.doInvoke(core.clj:5774)
at clojure.lang.RestFn.invoke(RestFn.java:512)
at cljx.repl_middleware$eval48740$loading__5295__auto____48741.invoke(repl_middleware.clj:1)
lein deps :tree
shows that the correct deps are being pulled in:
[com.keminglabs/cljx "0.6.0"]
[com.cemerick/piggieback "0.1.5"]
[net.cgrand/sjacket "0.1.1" :exclusions [[org.clojure/clojure]]]
[net.cgrand/parsley "0.9.2"]
[net.cgrand/regex "1.1.0"]
[org.clojure/core.match "0.2.0"]
[watchtower "0.1.1"]
I suspect that this is the breaking change you're referring to here, but I'm a little unclear from the description there what the problem / correct migration actually are.
My project.clj config:
[com.keminglabs/cljx "0.6.0"]
- since I'm using my own nrepl middleware stack which includes cljx.repl-middleware/wrap-cljx
and needs to exist in production.[com.keminglabs/cljx "0.6.0" :middleware false]
.:prep-tasks [["cljx" "once"] "javac" "compile"]
entry.:cljx
entry::cljx
{:builds
[{:source-paths ["src" "test"] :rules :clj :output-path "target/classes"}
{:source-paths ["src" "test"] :rules :cljs :output-path "target/classes"}]}''
0.4.0 works fine with this config, 0.6.0 throws the piggieback exception. Would appreciate your input if you have any ideas?
Thanks a lot!
Cheers :-)
The REPL middleware works well, but it doesn't help when you load a file or evaluate an expression that requires some other namespace that:
The REPL middleware needs to intercept load
calls so that e.g. (require 'foo)
will look for a foo.cljx
resource on the classpath, cljx
it to Clojure/ClojureScript based on the prevailing rules, and then invoke the regular file-loading mechanism for the type of REPL session in progress. Of course, if a .cljx
file isn't available, the normal loading mechanism should apply.
Done pervasively/properly, this should make cljx precompilation entirely unnecessary except when cutting a jar/war/other distributable.
When lein cljx once
or lein cljx auto
is executed, any code in the user
namespace is automatically loaded. In the development profile, this namespace may be populated. For instance if a project is designed along the lines of Stuart Sierra's reloaded workflow, there may be a file "dev/user.clj" that is included in the development profile.
If this is the case, running lein cljx
can result in a circular dependency, if the user namespace depends on files that are generated by cljx.
I'm currently working around this with the following:
:aliases {"cljx" ["with-profile" "cljx" "cljx"]}
:profiles {:cljx {}}
I'm using cljx 0.5.0 and it works great when I run lein cljx once
. However, when I run lein cljx auto
it will generate the code twice and I'm not sure wether this is caused by a misconfiguration in the project.clj
or a bug of cljx.
The following folders are created:
target/generated-src/{ns}...
-> correct clj/cljs filestarget/generated-src/file//{path-to-project}/test/cljx/{ns}/...
-> contains generated clj/cljs test-filestarget/generated-test/{ns}...
-> correct clj/cljs test-filestarget/generated-src/file//{path-to-project}/src/cljx/{ns}/...
-> contains generated clj/cljs filesWith lein cljx once
only the folders of 1 and 3 are generated.
My project.clj contains the following:
(defproject ...
:source-paths ["src/clj" "src/cljs" "target/generated-src"]
:test-paths ["test/clj" "test/cljs" "target/generated-test"]
...
:auto-clean false
:cljx {:builds [{:source-paths ["src/cljx"]
:output-path "target/generated-src"
:rules :clj}
{:source-paths ["src/cljx"]
:output-path "target/generated-src"
:rules :cljs}
{:source-paths ["test/cljx"]
:output-path "target/generated-test"
:rules :clj}
{:source-paths ["test/cljx"]
:output-path "target/generated-test"
:rules :cljs}]}
...
:dependencies [
[org.clojure/clojure "1.6.0"]
[org.clojure/clojurescript "0.0-2511" :scope "provided"]
...
]
:profiles {
:dev {
:plugins [[com.keminglabs/cljx "0.5.0" :exclusions [org.clojure/clojure org.clojure/clojurescript]]]
:prep-tasks [["cljx" "once"]]
...
}}
}})
Starting 2.4.2
leiningen calls the clean
task right before the deploy
task. This implies for most cljx configuration jars uploaded won't contain any generated file. Starting 2.5.0
the same happens before install
so even local jars won't be properly generated.
:auto-clean false
can be used for this but it looks like the preferred solution is to rely on :prep-tasks "cljx once"
.
Documentation should probably be updated as this behavior is pretty unexpected.
See leiningen#1642 and leiningen#1586 for more details.
Although documentation indicates the nREPL middleware can be used with version 0.2.2 it is actually not in the jar pushed on clojars.
Maybe a new version should be pushed with this change?
I've trying to port a debug macro -- https://github.com/harsha-mudi/dbg
cljx didn't apply cljs rules to a .clj file initially
Lets say I have a cljx source with a ns
declaration like this:
(ns #+clj ^{:doc "spam" :author "me"}
my.ns)
The resulting .cljs
would be:
(ns
)
but I would wish this in some way:
(ns
my.ns)
How do I prevent the ^{...}
from being included in the cljs
generated source, but not my.ns
also?
Hi Keving,
very good work! But I miss a $ lein cljx clean
subtask to delete any generated clj/cljs file. Is it something you're working on?
Thanks so much
Wouldn't be better to have the same way to hook cljx and cljsbuild to tasks?
Now we have to write:
:hooks [leiningen.cljsbuild cljx.hooks]
IMHO it would be better to write
:hooks [leiningen.cljsbuild leiningen.cljx]
cljx is a great way to write portable code and I was wondering if there is a way to speed up compiling. I noticed that the polling rate is set to 1000ms. Worst case, it takes a whole second just to notice that a file was changed.
What do you think of making the polling rate configurable or dropping it to something much lower, like 50ms?
I got a stacktrace while trying to cljx the demo file from readme.MD. I wish I could provide more info but I don't know what else should I report. My project.clj is also pretty standard. The :cljx part looks like:
:cljx {:builds [{:source-paths ["src/cljx"]
:output-path "target/cljx-generated/clj"
:rules :clj}
{:source-paths ["src/cljx"]
:output-path "target/cljx-generated/cljs"
:rules :cljs}]}
Here is what I get:
▸ lein cljx once
Rewriting src/cljx to target/cljx-generated/clj (clj) with features #{clj} and 0 transformations.
Exception in thread "main" java.lang.IndexOutOfBoundsException
at clojure.lang.RT.subvec(RT.java:1483)
at clojure.core$subvec.invoke(core.clj:3440)
at cljx.rules$apply_features.invoke(rules.clj:18)
at cljx.core$walk.invoke(core.clj:29)
at cljx.core$walk$fn__3486.invoke(core.clj:35)
at clojure.core$iterate$fn__4266.invoke(core.clj:2651)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:598)
at clojure.core$next.invoke(core.clj:64)
at clojure.core$some.invoke(core.clj:2443)
at cljx.core$walk.invoke(core.clj:32)
at cljx.core$walk$fn__3486.invoke(core.clj:35)
at clojure.core$iterate$fn__4266.invoke(core.clj:2651)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:598)
at clojure.core$next.invoke(core.clj:64)
at clojure.core$some.invoke(core.clj:2443)
at cljx.core$walk.invoke(core.clj:32)
at cljx.core$transform.invoke(core.clj:44)
at cljx.core$generate.invoke(core.clj:65)
at cljx.core$cljx_compile.invoke(core.clj:86)
at clojure.lang.Var.invoke(Var.java:415)
at user$eval3531.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:6619)
at clojure.lang.Compiler.eval(Compiler.java:6608)
at clojure.lang.Compiler.eval(Compiler.java:6609)
at clojure.lang.Compiler.eval(Compiler.java:6582)
at clojure.core$eval.invoke(core.clj:2852)
at clojure.main$eval_opt.invoke(main.clj:308)
at clojure.main$initialize.invoke(main.clj:327)
at clojure.main$null_opt.invoke(main.clj:362)
at clojure.main$main.doInvoke(main.clj:440)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:419)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
Subprocess failed
Should probably match cljsbuild, hooking jar
, compile
, and test
.
Using :source-paths like ["../shared/src/cljx"] doesn't work.
Exception in thread "main" java.io.FileNotFoundException:
/home/juho/Source/foobar/target/generated/clj/file:/home/juho/Source/foobar/app1/../shared/src/cljx/foobar/common/transit.clj (No such file or directory), compiling:(/tmp/form-init2327862490854915151.clj:1:72)
This would be fixed by #67
Hello,
I'm trying to get cljx files be parsed correctly by Light Table. First I try to be able to use load-file from the REPL.
From cljx README, I only need to install cljx as a plugin, but it doesn't work.
So I tried to use cljx.repl-middleware/wrap-cljx nrepl middleware.
To perform my experiment, I tried to load cljx file from Schema configured REPL which is of the following:
:profiles {:dev {:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/clojurescript "0.0-2030"]
[com.keminglabs/cljx "0.3.1"]]
:plugins [[com.keminglabs/cljx "0.3.1"]
[lein-cljsbuild "0.3.2"]
[com.cemerick/austin "0.1.3"]
[com.cemerick/clojurescript.test "0.2.2"]]
:hooks [leiningen.cljsbuild]
:repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl
cljx.repl-middleware/wrap-cljx]}}}
When I launch lein repl, cljx generates the cljs/clj files and cljsbuild generate javascript. When done, if I tried to load a cljx file *(load-file "test/cljx/schema/test_test.cljx") I got the following error:
nREPL server started on port 57898 on host 127.0.0.1
REPL-y 0.3.0
Clojure 1.5.1
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
user=> (load-file "test/cljx/schema/test_test.cljx")
CompilerException java.lang.RuntimeException: No reader function for tag +clj, compiling:(/Users/bertrand/Desktop/schema/test/cljx/schema/test_test.cljx:2:28)
Can you explain me how to make it work ?
Sincerely
Bertrand
Hi Kevin/all,
I think there's an incompatibility between CLJX and browser REPLs caused by CLJX's middleware adding its own dependency (including its version of Piggieback - currently 0.1.0, latest is 0.1.3) to the project in preference to any other version of Piggieback that users specify in their project.clj.
It's been raised on the mailing list at https://groups.google.com/forum/?fromgroups=#!topic/clojurescript/-ZfDekURO6I - although I've had other problems with this in the past - sorry for not reporting it sooner.
I currently work around it with this gist: https://gist.github.com/james-henderson/4c890844903f6054334b - essentially, by replicating what the middleware does in my own project.clj.
I can think of a couple of solutions off the top of my head, (although I suspect with your familiarity with the codebase, you'll probably have more ideas!):
leinjacker.deps/add-if-missing
rather than just conj - this would mean that users could add their own CLJX dependency with exclusions, and the middleware wouldn't override itThanks for writing and maintaining CLJX btw, it's really helped my Clojure/ClojureScript workflow - a much appreciated library!
James
It looks like :prep-tasks [["cljx" "once"]]
works nicely, so we can eliminate the hooks and change docs. This will fix #22, too.
user.clj
is loaded before any of the hooks get a chance to be called.
I made some attempts to add other hooks but without success. As user.clj
is loaded by Clojure code and not by leiningen it makes things more complex.
Out-of-the-box, cljx auto does not provide a means of calling cljsbuild (once?) upon run.
Some workflow or configuration for getting the effect of both "lein cljx auto" and "lein cljsbuild auto" should be documented as supported.
I currently have this in my project.clj:
:prep-tasks [["clean"]
["cljx" "once"]
["cljs-prod"]
["garden" "once"]
["javac"]
["compile" ":all"]]
With both 0.4.0 and 0.5.0, cljx seems trigger this sequence of events to be performed again and again. In 0.4.0, cljx is run before the others, in 0.5.0 it seems that cljx isn't run at all (possibly related to #60 )
I recently fixed this in lein-garden, maybe it's something similar here: https://github.com/Skinney/lein-garden/commit/6dc65a2193fca84838b34334a37c6d2b23b7e799
Am not entirely sure if that is related to recent REPL changes in CLJS, but I can't open a Clojure REPL in my CLJX project anymore :( Removing all other deps and trying various recent CLJS releases, the issue only seems to start w/ CLJS 0.0-2665, 2657 still is working fine...
lein repl
.... (a ton of various reflection warnings because I enabled them...)
Reflection warning, cemerick/piggieback.clj:54:3 - call to static method putProperty on org.mozilla.javascript.ScriptableObject can't be resolved (argument types: unknown, java.lang.String, java.lang.Object).
Error loading cljx.repl-middleware: java.lang.IllegalArgumentException: No single method: _setup of interface: cljs.repl.IJavaScriptEnv found for function: -setup of protocol: IJavaScriptEnv, compiling:(cemerick/piggieback.clj:149:5)
Exception in thread "main" java.lang.RuntimeException: Unable to resolve var: cljx.repl-middleware/wrap-cljx in this context, compiling:(/private/var/folders/x8/_j311xvx49151dw3t3gmcbmm0000gn/T/form-init601009934546686385.clj:1:1829)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6651)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6646)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6646)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.access$100(Compiler.java:38)
at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6050)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6644)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5217)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3846)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6642)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.eval(Compiler.java:6700)
at clojure.lang.Compiler.eval(Compiler.java:6693)
at clojure.lang.Compiler.eval(Compiler.java:6693)
at clojure.lang.Compiler.load(Compiler.java:7130)
at clojure.lang.Compiler.loadFile(Compiler.java:7086)
at clojure.main$load_script.invoke(main.clj:274)
at clojure.main$init_opt.invoke(main.clj:279)
at clojure.main$initialize.invoke(main.clj:307)
at clojure.main$null_opt.invoke(main.clj:342)
at clojure.main$main.doInvoke(main.clj:420)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: Unable to resolve var: cljx.repl-middleware/wrap-cljx in this context
at clojure.lang.Util.runtimeException(Util.java:221)
at clojure.lang.Compiler$TheVarExpr$Parser.parse(Compiler.java:659)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6644)
... 34 more
This isn't so much a problem, but just a open ended question. Adding the cljx hook to my project adds about 4-5 seconds to my "lein test" task.
Don't get me wrong, I appreciate what cljx is doing for me. I was just wondering if there was some way (documented or otherwise) to get cljx to either:
Attempting to eliminate the 0.7.0
core.logic dependency (thus tracking the rev that kibit requests, currently 0.8.0-rc2
) results in a stackoverflow:
Rewriting src/cljx to target/classes (clj) with 2 rules.
Exception in thread "main" java.lang.StackOverflowError
at clojure.core.logic.Substitutions.walk(logic.clj:546)
at clojure.core.logic$walk_STAR_.invoke(logic.clj:415)
at clojure.core.logic$walk_STAR_$fn__1399.invoke(logic.clj:420)
at clojure.core.logic$eval1582$fn__1583.invoke(logic.clj:1068)
at clojure.core.logic$eval312$fn__313$G__303__320.invoke(logic.clj:85)
at clojure.core.logic$walk_STAR_.invoke(logic.clj:416)
......
Using kibit with the older core.logic works now, but that's presumably not going to be true forever…
I run my builds with the following in my uberjar profile:
:prep-tasks ^:replace [["clean"]
["cljx" "once"]
["cljsbuild" "clean"]
["cljsbuild" "once" "prod"]
["javac"]
["compile" ":all"]]
With cljx 0.4.0 and Leiningen 2.5.0, this works great. When I upgrade to cljx 0.5.0, the cljsbuild task starts running before cljx, causing a compilation failure and crashing the process. Moving cljx after cljsbuild doesn't help.
If I remove all tasks except for cljx, it works.
Any ideas on what might have changed here?
The sjacket branch now has symbol replacement (e.g. clojure.lang.IFn
=> cljs.core.IFn
).
After looking into expanding this significantly (with the objective of providing at least a full mapping of Clojure interfaces => ClojureScript protocols), I'm think that it's not such a good idea. While there's a sizable correspondence between the names involved, it's far from uniform: ClojureScript has many, many more protocols than Clojure has interfaces, and the methods defined by them are arranged in a couple of cases slightly differently. We could provide automatic replacement for the ones that are directly analogous, but then users would be left having to know/remember which protocol name changes are taken care of and which aren't.
Beyond that, it seems like the real pain around protocols isn't their names, but their methods. The camelCase vs. -dash-prefix conventions are consistent in many places, but post-ClojureScript Clojure protocols have been following that movement and also using -dash-prefix method names; do we always presume that people are writing Clojure and convert when emitting ClojureScript? What happens with "userland" protocols that use the camelCase convention?
I'm strongly leaning towards abandoning this particular feature (though cljx master only replaces two symbols as it is, IFn
and Atom
;-P). Thoughts?
The README states:
cljx itself will be added as a project dependency (this will only affect REPL processes, and won't leak out into your project's pom.xml, influencing downstream users of your library, if you're writing one)
However, cljx does leak out. For example, the Medley 0.5.0 has a dependency on cljx 0.4.0.
Having this bug in project.clj
:
:cljx {:builds [{ ; boring
:rules clj}]}
caused the rather unhelpful error:
$ lein cljx once
java.lang.NullPointerException
at clojure.lang.Symbol.intern(Symbol.java:60)
at clojure.core$symbol.invoke(core.clj:539)
at cljx.core$cljx_compile.doInvoke(core.clj:85)
at clojure.lang.RestFn.invoke(RestFn.java:410)
at leiningen.cljx$once.invoke(cljx.clj:11)
at leiningen.cljx$cljx.invoke(cljx.clj:33) ...
I do appreciate the freedom the fallback to resolving symbols in cljx-compile
allows - but it causes a steep price for an average user (in a failure case like this).
A little more context (e.g. "NPE while trying to load namespace x") in the error message seems like a good idea.
Maybe even fuzzy checking to catch "clj" and "cljs" as strings / symbols and emit a "Did you actually mean what you wrote in the config?" message.
I have the following project.clj
(defproject samedhi.quizry "0.0.1-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/clojurescript "0.0-1878"]
[domina "1.0.1"]
[ch.qos.logback/logback-classic "1.0.7"
:exclusions [org.slf4j/slf4j-api]]
[io.pedestal/pedestal.app "0.2.1"]
[io.pedestal/pedestal.app-tools "0.2.1"]
[com.cemerick/piggieback "0.1.0"]
[org.clojure/test.generative "0.5.1"
:exclusions [org.clojure/tools.namespace]]
[org.clojure/core.async "0.1.242.0-44b1e3-alpha"]]
:repl-options
{:port 5000
:init-ns user
:init (do
(try
(use 'io.pedestal.app-tools.dev)
(catch Throwable t
(println "ERROR: There was a problem loading io.pedestal.app-tools.dev")
(clojure.stacktrace/print-stack-trace t)
(println)))
(start))
:welcome (println "Welcome to pedestal-app! Run (tools-help) for help.")}
:aliases {"test!" ["do" "clean," "test"]
"repl-headless"["trampoline""repl" ":headless"]}
:repositories {"sonatype-oss-public" "https://oss.sonatype.org/content/groups/public/"}
:min-lein-version "2.0.0"
:source-paths ["app/src" "app/templates" "app/generated/cljs"]
:test-paths ["app/src" "test" "app/generated/clj"]
:resource-paths ["config"]
:target-path "out/"
:clean-targets [:target-path "app/generated"]
:main ^{:skip-aot true} io.pedestal.app-tools.dev
:plugins [[com.keminglabs/cljx "0.3.1"]]
:cljx {:builds [{:source-paths ["app/cljx"]
:output-path "app/generated/clj/samedhi/quizry"
:rules :clj}
{:source-paths ["app/cljx"]
:output-path "app/generated/cljs/samedhi/quizry"
:rules :cljs}
{:source-paths ["app/macro-cljx"]
:output-path "app/generated/clj/samedhi/quizry"
:rules
{:filetype "clj"
:features #{"clj"}
:transforms []}}
{:source-paths ["app/macro-cljx"]
:output-path "app/generated/cljs/samedhi/quizry"
:rules
{:filetype "clj"
:features #{"cljs"}
:transforms []}}]}
:hooks [cljx.hooks])
And have 2 odd things to report.
Number 1:
As you can see, I separated my simple clojure and macro containing clojure into two separate areas. I compile them into "app/generated/cljs" and "app/generated/clj". When I am messing around in clojure nrepl, or when I for instance run my "lein test!" alias (both pure clojure code) then everything is fine.
However, if I try to start up the (cljs-repl) and then go to a browser to compile the app for development, I get a funny error. It is clear that the cljs files are being used, however, it appears the that the macros files for the clojure world are being used instead of the macro files for the clojurescript world. Stated differently, when I :require-macro's from within a .cljs file, the macros used are the macros that were meant for the clojure world, not for the clojurescript world. Or, to just put it directly, the .cljs files, which are under "app/generated/cljs" are using the equivalently named and namespaced files under "app/generated/clj" for their macros.
The confusing matter is that I don't seem to have included "app/generated/clj" in my :source-paths, so I don't see how it is the case that the clojurescript compiler can even see "app/generated/clj".
As you might guess, I can easily fix the issue by removing the "app/generated/clj" directory before I attempt to use the clojurescript compiler. Then it finds the macros (which are .clj files) in "app/generated/cljs" and everything works fine.
Number 2:
When I run "lein clean; lein repl-headless" I don't seem to be able to find the expected files when compiling for cljs. However, if I run "lein clean; lein cljx once; lein repl-headless" everything works fine.
This would seem to have something to do with the classpath being checked and found missing before cljx had a chance to generate "app/generated/*" ? Just a guess.
Finally, I want to note that I am using pedestal, it is possible that these issues have nothing to do with cljx at all, I will ask there as well.
Hey @lynaghk (and whoever else). Following up on the spike of using sjacket (see the corresponding branch), a thought I'd like feedback on:
Since the Clojure reader isn't being used anymore, the e.g. ^:clj
tags don't actually denote metadata. It seems that cljx should stop using them, and perhaps adopt feature expression-style (née Common Lisp-style) tags e.g. #+clj
. sjacket currently parses these (properly) as reader literals, so matching and eliding/transforming their value portion is no more difficult than the ^:clj
-style tags.
Along with an option to define the "features" that are to be turned on on a per-build basis, this would make cljx a fairly general-purpose s-expression preprocessor.
Thoughts?
When source-paths
value is present several times in the complete file path, all occurences are replaced by the value of output-path
.
e.g.
with {:source-paths ["test"] :output-path "generated-test"}
path is generated-test/XX/generated-test/
instead of generated-test/XX/test/
Note this doesn't happen with branch sjacket
.
I'm trying to set up cljx to build a multi-platform project with clj, cljs, jvm and android-device tags. For (admittedly quite an extreme) example
(defn debug-log [s]
(#+android-device Log/d #+jvm println #+cljs .log #+cljs js/console s))
and it looks like it should work for my purposes, however it seems that the plugin inserts a dependency in the runtime code on com.keminglabs/cljx which depends on piggieback which depends on clojurescript and rhino and clojure core, all of which cause conflicts with the android dependencies. For example the dexing process can only add one copy of each class, and I'm getting an "already added org/mozilla/classfile/ByteCode" which implies I have two copies of that dependency somewhere. It is also pulling in clojure core 1.5.1, when lein droid requires a special build of clojure.core.
Is there a way to reduce the dependency tree without taking away the ability to evaluate cljx at runtime via the repl, and how do I remove these dependencies completely for the release product?
Hi @lynaghk
I've settled master such that it's ready for an 0.5.0
release. All that remains is for you to:
lein do clean, deploy clojars
0.5.0
I pushed off the more ambitious stuff that was slated for 0.5.0
to 0.6.0
so that the pending :prep-tasks
fix and cljx auto
enhancement can get out there.
Thanks!
The middleware is not wrapped with leiningen 2.5.1.
Idk whether its cljx or leiningens "fault". Just wanted to report.
I think I've followed the instructions in the readme correctly, but when I run lein cljx once, I get the following error:
Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: match in this context, compiling:(cljx/rules.clj:18)
Do you have any ideas?
Most of my projects using cljx end up with a configuration similar to:
:source-paths ["src" "target/generated-src"]
:test-paths ["test" "target/generated-test"]
:cljsbuild {:builds [{:source-paths ["src" "target/generated-src"]}]}
:cljx {:builds [{:source-paths ["src"]
:output-path "target/generated-src"
:rules :clj}
{:source-paths ["src"]
:output-path "target/generated-src"
:rules :cljs}
{:source-paths ["test"]
:output-path "target/generated-test"
:rules :clj}
{:source-paths ["test"]
:output-path "target/generated-test"
:rules :cljs}]}
Note that the cljx
configuration has some implications on source-paths
, test-paths
and cljsbuild
.
Most of it could be deduced and injected at run time (by a leiningen plugin). The configuration could be simplified down to:
:cljx {:builds [{:source-paths ["src" "test"]
:output-path "target/generated-%"
:rules [:clj :cljs]}]}
This is similar to this proposition for clojurescript.test
.
The whole configuration could be omitted with some default:
source-paths
is the concatenation of source-paths
and test-paths
output-path
has some defaultrules
defaults to [:clj :cljs]
Now this is probably too much (and assumes cljx
files are in the same directory structures than clj
files, which I usually do).
When running lein repl
followed by Austin, will have to lein cljsbuild clean
before lein cljx once
to be able to have new code changes available in the cljs repl.
Is this an expected behavior?
I've recently switched to @cemerick's 0.5.0-SNAPSHOT. version and using :prep-tasks [["cljx once"] "javac" "compile"]
. When running the above lein command chain it does correctly generate cljx transforms, but the test command is then invoked for the 'user' ns only, even if I specify the :all
test selector... running lein clean
and lein TEST
separately works fine though.
This report concerns sjacket
branch.
When running lein install
with hooks defined I get the following exception:
Exception in thread "main" java.io.FileNotFoundException: Could not locate cljx/core__init.class or cljx/core.clj on classpath:
at clojure.lang.RT.load(RT.java:443)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5018.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
at clojure.core$load_lib.doInvoke(core.clj:5374)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$load_libs.doInvoke(core.clj:5413)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$require.doInvoke(core.clj:5496)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at user$eval3.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:6619)
at clojure.lang.Compiler.eval(Compiler.java:6608)
at clojure.lang.Compiler.eval(Compiler.java:6582)
at clojure.core$eval.invoke(core.clj:2852)
at clojure.main$eval_opt.invoke(main.clj:308)
at clojure.main$initialize.invoke(main.clj:327)
at clojure.main$null_opt.invoke(main.clj:362)
at clojure.main$main.doInvoke(main.clj:440)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:419)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
I can reproduce with data.generators after adding :hooks [cljx.hooks]
.
After removing the hooks definition it works perfectly. Also it works fine with the hook and master branch.
It looks like what happens is the plugin isn't aware of any exclusions it might so when it adds itself as a dep, no exclusions are copied over. When no exclusions are applied (org.clojure/clojure) to the plugin, you see two duplicate traces like so:
(WARNING!!! version ranges found for:)
([com.keminglabs/cljx "0.4.0"] -> [org.clojars.trptcolin/sjacket "0.1.0.6"] -> [org.clojure/clojure "[1.3.0,)"]
Consider using [com.keminglabs/cljx "0.4.0" :exclusions [org.clojure/clojure]].)
([com.keminglabs/cljx "0.4.0"] -> [org.clojars.trptcolin/sjacket "0.1.0.6"] -> [net.cgrand/regex "1.1.0"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [com.keminglabs/cljx "0.4.0" :exclusions [org.clojure/clojure]].)
([com.keminglabs/cljx "0.4.0"] -> [org.clojars.trptcolin/sjacket "0.1.0.6"] -> [net.cgrand/parsley "0.9.1"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [com.keminglabs/cljx "0.4.0" :exclusions [org.clojure/clojure]].)
([lein-gorilla "0.3.1"] -> [gorilla-repl "0.3.1"] -> [grimradical/clj-semver "0.2.0"] -> [org.clojure/clojure "[1.3.0,)"]
Consider using [lein-gorilla "0.3.1" :exclusions [org.clojure/clojure]].)
([com.keminglabs/cljx "0.4.0"] -> [org.clojars.trptcolin/sjacket "0.1.0.6"] -> [net.cgrand/parsley "0.9.1"] -> [net.cgrand/regex "1.1.0"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [com.keminglabs/cljx "0.4.0" :exclusions [org.clojure/clojure]].)
nil
(WARNING!!! version ranges found for:)
([com.keminglabs/cljx "0.4.0"] -> [org.clojars.trptcolin/sjacket "0.1.0.6"] -> [org.clojure/clojure "[1.3.0,)"]
Consider using [com.keminglabs/cljx "0.4.0" :exclusions [org.clojure/clojure]].)
([com.keminglabs/cljx "0.4.0"] -> [org.clojars.trptcolin/sjacket "0.1.0.6"] -> [net.cgrand/regex "1.1.0"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [com.keminglabs/cljx "0.4.0" :exclusions [org.clojure/clojure]].)
([com.keminglabs/cljx "0.4.0"] -> [org.clojars.trptcolin/sjacket "0.1.0.6"] -> [net.cgrand/parsley "0.9.1"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [com.keminglabs/cljx "0.4.0" :exclusions [org.clojure/clojure]].)
([com.keminglabs/cljx "0.4.0"] -> [org.clojars.trptcolin/sjacket "0.1.0.6"] -> [net.cgrand/parsley "0.9.1"] -> [net.cgrand/regex "1.1.0"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [com.keminglabs/cljx "0.4.0" :exclusions [org.clojure/clojure]].)
nil
The workaround is to manually add the dep in profiles dev provide exclusion for it and add the piggieback repl option as well. not so bad, but it would be helpful if cljx plugin could take care of this since it affects all projects downstream - in fact it should probably exclude by default.
Edit: arg actually that doesn't solve it since you lose the cljx lein task.
When defining a function overriding another one part of clojure.core
(e.g. get
) an exception is thrown at call time. REPL is then unusable.
You can reproduce with the following snippet
(ns test
(:refer-clojure :exclude [get]))
(defn ^:clj get [] ())
and then at REPL
(use 'test)
(get)
triggers the following exception:
ERROR: Unhandled REPL handler exception processing message {:code (get), :id ebbd0492-33c1-4842-909c-7d312b3bd754, :op eval, :session 4b9d1082-14b1-4e2b-9529-a1a52bbd13c0}
java.lang.IllegalStateException: get already refers to: #'test/get in namespace: user
at clojure.lang.Namespace.warnOrFailOnReplace(Namespace.java:88)
at clojure.lang.Namespace.reference(Namespace.java:110)
at clojure.lang.Namespace.refer(Namespace.java:168)
at clojure.core$refer.doInvoke(core.clj:3850)
at clojure.lang.RestFn.invoke(RestFn.java:439)
at kibit.check$careful_refer$fn__6011.invoke(check.clj:52)
at kibit.check$careful_refer.invoke(check.clj:51)
at kibit.check$read_file.invoke(check.clj:72)
at kibit.check$fn__6029.invoke(check.clj:161)
at kibit.check$check_reader.doInvoke(check.clj:219)
at clojure.lang.RestFn.invoke(RestFn.java:559)
at cljx.core$munge_forms.invoke(core.clj:64)
at cljx.repl_middleware$munge_code.invoke(repl_middleware.clj:30)
at cljx.repl_middleware$wrap_cljx$fn__6165.invoke(repl_middleware.clj:48)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__402.invoke(middleware.clj:17)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__402.invoke(middleware.clj:17)
at clojure.tools.nrepl.middleware.session$session$fn__695.invoke(session.clj:192)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__402.invoke(middleware.clj:17)
at clojure.tools.nrepl.server$handle_STAR_.invoke(server.clj:18)
at clojure.tools.nrepl.server$handle$fn__757.invoke(server.clj:27)
at clojure.core$binding_conveyor_fn$fn__4107.invoke(core.clj:1836)
at clojure.lang.AFn.call(AFn.java:18)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.