This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-02-16
Channels
- # admin-announcements (14)
- # announcements (1)
- # aws (1)
- # beginners (105)
- # boot (609)
- # braid-chat (4)
- # braveandtrue (3)
- # cider (24)
- # cljs-dev (13)
- # cljsrn (2)
- # clojure (142)
- # clojure-berlin (7)
- # clojure-ireland (7)
- # clojure-japan (10)
- # clojure-nl (4)
- # clojure-poland (76)
- # clojure-russia (198)
- # clojure-sg (4)
- # clojure-taiwan (1)
- # clojurebridge (1)
- # clojured (4)
- # clojurescript (73)
- # conf-proposals (11)
- # cursive (10)
- # datomic (32)
- # devcards (1)
- # dirac (22)
- # editors (5)
- # emacs (3)
- # events (4)
- # funcool (19)
- # hoplon (18)
- # job (1)
- # jobs (3)
- # jobs-rus (16)
- # keechma (25)
- # ldnclj (33)
- # lein-figwheel (10)
- # leiningen (4)
- # luminus (1)
- # off-topic (19)
- # om (255)
- # onyx (51)
- # overtone (1)
- # parinfer (206)
- # perun (5)
- # proton (2)
- # re-frame (3)
- # reagent (2)
- # remote-jobs (13)
- # ring-swagger (7)
- # slack-help (4)
- # yada (7)
sorry for super nooby question but I can't seem to grok how this works. (deftask what "Specify a thing" [t thing THING str "An object" p pluralize bool "Whether to pluralize"] (fn middleware [next-handler] (fn handler [_] (next-handler {:thing thing :pluralize pluralize})))) (deftask fire "Announce a thing is on fire" [] (fn middleware [next-handler] (fn handler [thing-map] (let [updated-thing-map (next-handler thing-map) verb (if (:pluralize thing-map) "are" "is")] (println "My" (:thing thing-map) verb "on fire!"))))) :source http://www.flyingmachinestudios.com/programming/boot-clj/
I'm not sure what is being passed to what and since I can't simply print a line and have the actual function definition printed I'm finding it difficult to comprehend.
This is the command [ boot what -t "pants" -p -- fire ]
@jethroksy: yes I have had success
yes of course you need export VAR=
otherwise it won't work, I usually also merge with a default config
@richiardiandrea: thanks!
yeah that's true
anyone getting any error using: (sift :to-resource #{#"version\.properties"})
?
Error:
clojure.lang.ArityException: Wrong number of args (1) passed to: task-helpers/sift-match/fn--1265
yes that's right, but I will try
clojure.lang.ArityException: Wrong number of args (1) passed to: task-helpers/sift-match/fn--1265
...
boot.task-helpers/sift-mv/fn/reducer task_helpers.clj: 85
...
clojure.core/fn core.clj: 6536
clojure.core.protocols/fn/G protocols.clj: 174
clojure.core/reduce-kv core.clj: 6562
clojure.core/partial/fn core.clj: 2500
...
clojure.core/apply core.clj: 632
clojure.core/update-in core.clj: 5923
Looks like an error inside the reducer(defn- sift-match
[invert? regexes]
(->> (map #(partial re-find %) regexes)
(apply some-fn)
(comp (if invert? not identity))))
yes it is a Clojure standard function
very tricky 😄
I saw it first time here
will investigate tomorrow TIWE - today I worked enough 😄
that one is tricky though
generates a re-find
function for all the regexes then passes it to some-fn
the first who returns true short circuits
Are there any tutorials on how to build a blog site using Perun?
@joshua.d.horwitz: not that i'm aware of but there a few blogs on github, https://github.com/martinklepsch/martinklepsch.org is one
But by the way does the above error works for you guys? is it just my problem?
Just reposting this question. sorry for super nooby question but I can't seem to grok how this works. (deftask what "Specify a thing" [t thing THING str "An object" p pluralize bool "Whether to pluralize"] (fn middleware [next-handler] (fn handler [_] (next-handler {:thing thing :pluralize pluralize})))) (deftask fire "Announce a thing is on fire" [] (fn middleware [next-handler] (fn handler [thing-map] (let [updated-thing-map (next-handler thing-map) verb (if (:pluralize thing-map) "are" "is")] (println "My" (:thing thing-map) verb "on fire!"))))) :source http://www.flyingmachinestudios.com/programming/boot-clj/ [11:08] I'm not sure what is being passed to what and since I can't simply print a line and have the actual function definition printed I'm finding it difficult to comprehend. [11:08] This is the command [ boot what -t "pants" -p -- fire ]
@alandipert: Is that enough info for you (or anyone) to help Wade?
Thanks @meow
@alandipert: Nevermind. Problem solved.
Feeling like I dove in way over my head with Boot. Will have to drop back to Leiningen for my projects until I am more familiar with Clojure.
@grounded_sage: the example is a little contrived - it's demonstrating the way boot works without doing anything related to building or running anything. what are you hoping to accomplish?
Was just looking at using Boot as it's just Clojure as a way of learning both Boot and continuing to learn Clojure. I am basically looking at building a simple static website using. Stasis, Hiccup, Garden, Mesh. Using live reloading of the browser when I make changes. Yes it's something really basic but I figured it would be the best way to get up and running with something that was still rather simple.
got it
the big idea with boot is, the filesystem can be a value
once it's a value, you can pass and return it to/from functions
and then you're working with values and functions, and all of clojure can be brought to bear
so at a high level a boot "task" is a function that takes and returns a fileset
however it's convenient for tasks to be able to remember the values they saw so that they can cache/memoize... so boot tasks are actually functions that return functions
which is the nested fn
stuff going on in the example
but it's also convenient to be able to parameterize this stack of 2 functions... so we do that with a function also. this what deftask
is
in the example you pasted daniel is stringing together tasks with a map instead of a FileSet, which is the value passed between tasks in the real world
i hope that was helpful, but i gotta run now
for static websites, i would recommend checking out #C0JM5DUFL
@onetom: I have a config that I'm very pleased with (with dev/user.clj) if you're interested I could show you
Thanks for the detailed response @alandipert most of that didn't make much sense to me haha. I'll come back to Boot another time when I am more skilled in Clojure
I'm trying to figure something out, fairly complex. And I think I'm 90% of the way there. I just need some advice on how to proceed.
I'm trying to track down why cider-nrepl isn't able to resolve the file location of symbols when the nrepl is run within a pod.
It looks like cider-nrepl is using fake.class.path to resolve the classpath, however fake.class.path doesn't include the classpath from within the pod. Any advice on where it should be pulling the classpath from?
I'm wondering if cider-nrepl middleware should infact be using clojure.lang.RT to get the classpath, and not get it from the system property directly? @micha @juhoteperi it looks like you guys are in charge of these tickets
@jethroksy: of course i would be interested in it. thx!
Morning booters. I continue to have a very hard time understanding the Fileset API. This moring an insanely great idea for improving boot came to me. Here are some problems, as I see things. First, the Fileset API exposes way too much implementation detail. Take core/tmp-dir!, for example - it always creates an anonymous temp dir, so there is no reason it must be exposed to the developer. I just want my input stuff to turn into my output stuff, and I don't care what the mechanism is; provided I supply enough information, boot should be able to do the right thing however it pleases. Second, the API is not very clojurish. Take core/input-files for example. The beauty of the Fileset concept is that it treats the OS filesystem as just another database, and exposes functionality using defrecord TmpFileSet. That makes a TmpFileSet a clojure map - it should be possible to write (:input-files fs) rather than (core/input-files fs). Altering a FS should be done using ordinary Clojure idioms. With the API as it stands, the dev has to learn way too much about boot internals - make a tmp-dir!, make files, copy stuff, then do something like core/add-resource, etc. With a really Clojurized API it would be possible to use the standard map stuff. For example to copy foo/bar.clj to WEB-INF/classes/foo/bar.clj, something like:
(assoc fs :input-files (merge (:input-files fs) {"WEB-INF/classes/foo/bar.clj" "foo/bar.clj"}))
Unfortunately this would require major rearchitecting - you'd have to switch from defrecord to deftype, and implement all the necessary interfaces. Fortunately, it turns out I've already done this for a very similar situation: the Google Appengine Datastore. I used defrecord to make gae datastore Entity objects behave exactly like Clojure maps.
you can totally implement an api on top of the fileset btw, i would be interested to see it
@micha: not sure yet how to deal with all case, but I'm sure with a little analysis a good solution would be found.
Regarding implementation on top of the fileset: that's exactly what I want to avoid. Instead of an API layered on top of Fileset, better to define the Fileset API using protocols. That way the FS api is just the Clojure API - no special fns needed.
i just came across http://projects.spring.io/spring-boot/ and wondered if it has anything to do w boot... i saw it mentioned in this rather aggressive remote job post: https://remoteok.io/remote-jobs/15499-remote-clojure-developer-restaurantzone is it any good!? how come ppl are using it together w clojure?
I think the knowledge you've gained analysing stuff would carry over. Protocols: I mean Clojure's interfaces, e.g. ILookup, IPersistentMap, etc. The goal would be to make Fileset look and act like any other map, with implementation details hidden.
Right, but the idea is to use a custom implementation so that standard operations like assoc can do specialized boot work. Using defrecord you only get a standard implementation. You can see an (unfinished) example at https://github.com/migae/datastore .
it's difficult to talk about a fictional thing when there are many subtle concerns that are being balanced
so i recommend that you build a thing on top of the existing api, so we can compare in a productive way
a simple example: to support (:input-files fs), you have to implement containsKey, which is in the clojure.lang.Associative interface. Then you can return whatever you want, your deftype need not actually contain the :input-files key. The whole thing is virtualized. I'm not sure if you can override such interfaces with defrecord; I think you have to use deftype.
Not sure how soon I'll be able to write any demo code, just wanted to put the idea forward for consideration.
Sorry, I think its valAt, which is in ILookup. The advantage is that there is then no need to learn an API. You just use Clojure.
i'm kind of in the mindset where i think using protocols and record types in the first place was overengineering, i think it made things more complicated than they need to be
Fileset does not have an :input-files key. You implement valAt to return the same thing core/input-files returns. That's just a simple example.
with the magical key thing you will need to implement every permutation of selector in there
or you will have some hybrid thing where sometimes you use functions and sometimes special magical keys
Matter of taste, I guess. I personally would very much prefer to be able to do everything I need to do with Filesets using nothing more that assoc, merge, cons, etc. - just the Clojure api, with the addition of some kind of commit! operation.
so you'd need to know more internals to know which things are implemented magically and which things are just functions
basically every time i've used protocols in boot i've sort of regretted it, i think it could have been simpler if i hadn't jumped to overgeneralize
like even if it's no worse, it would need to be better to justify adding another layer of infrastructure on top of simple data and functions
especially since it is totally feasible to implement all of this on top of the existing api
In any case I don't mean to be argumentative, but I don't think what I have in mind could be implemented as a layer on top of Fileset, although I'd have to look into it a bit more to be sure.
For me, it all comes down to ease of use for devs - as I mentioned, I'm finding it quite difficult indeed to understand the API.
I guess if I can find some time the thing to do would be to fork an experimental version of boot just for exploring ideas.
Sure but in that case you'd basically end up reimplementing the whole thing. I don't mean fork as in a competing implementation, I just mean one the I don't worry about keeping in sync with master.
there shouldn't be any need to rip any existing functionality out, becuse every part is needed
ok for expermenting you're right, i could have my deftype just forward operations to a wrapped Fileset.
yes and you maintain compatibility with all the existing tasks that you don't want to have to rewrite
you can even make your own with-pre-wrap macro that does the wrapping and unwrapping for you
i think you will find that the simplicity of the existing thing will make this approach way easier than if it was already all wrapped up in protoocls
that way i could implement just bits of functionality, like the example i gave above for copying: (assoc fs :input-files (merge (:input-files fs) {"WEB-INF/classes/foo/bar.clj" "foo/bar.clj"}))
Glad you mentioned that, I wanted to ask about it. I don't understand the doc and tried without success to use it. Is using core/cp preferable to using io/copy?
going from examples, mainly - https://github.com/cpmcdaniel/boot-copy/blob/master/src/cpmcdaniel/boot_copy.clj
what i find confusing is that the destfile is supposed to already be in the fileset.
if you want to copy to a new file you'd do that by copying the file in the temp dir and then adding that
if it's already supposed to be in the fileset how did it get there? copying is how you put something new in a directory; why is it differnt in a Fileset?
like git is confusing, but it's extermely difficult to produce a better alternative when all concerns are considered
the fileset is different than the filesystem in the same way that the git tree is different from the working set
but in order for git to provide the transactional commits etc it needs to do things differently than you'd do them with pure mutable filesystem objects
(core/with-pre-wrap [fs] (let [tgt (core/tmp-dir!) in-files (->> fs core/output-files (core/not-by-ext [".clj"]) (map (juxt core/tmp-path core/tmp-file)))] (doseq [[rel-path in-file] in-files] (let [out-file (doto (io/file tgt (str rel-path "/foo")) io/make-parents)] (println " in-file: " in-file) (println "tmp out-file: " out-file) (core/cp fs in-file out-file))) (core/add-asset fs tgt) (core/commit! fs))))
I get No implementation of method: :dir of protocol: #'boot.tmpdir/ITmpFile found for class: java.io.File
the mix of http://clojure.java.io and boot api stuff in examples and in the source is a little perplexing - i never know when to use what
doesn't that make it - oops, just reread the doc, tmp-file creates a java.io.File - that's surprising, given the name of the fn
it merely provides a io.File object corresponding to a file in some immutable, content-addressed storage area
right, sorry, tmp-file returns the java.io.File associated with an existing Tmpfile
you can't save that File object or do anything with it that spans multiple transactions
ok, do you have a simple example illustrating correct usage of core/cp? i remain thoroughly confused.
the next time you get the fileset and you do tmp-file on it, you will find a different io.File object
so if you have two tmpfiles in the fileset and you want them to contain the same bytes, you can use that function
if you use io/copy to read from ont tmp-file and write to another you will corrupt the fileset
the basic rule is that the io.File objects you obtain from the fileset api are read-only
@micha I catch you. I'd love to pick your brain on fake.class.path a little later. I know you're busy now, and two conversations is too many 😛
do you have a simple example of how to copy stuff from source to target using just filesets?
@mobileink: it's not possible
that's like asking "how to copy stuff from a git repo to arbitrary directories using just git commands"
filesets are for a single specific purpose: providing a transactional, immutable interface on top of and alongside the actual filesystem, so you can control what is on the classpath
named files on the filesystem are beyond the scope of the fileset api, as it only deals with anonymous files
let me rephrase the question: what is the cannonical way to write a task whose job is to copy stuff, in such a way that the task can be inserted in a pipeline of tasks? There must be an example somewhere. Can you recommend a third party lib that does things the boot way?
yes, i've used sift, but what if i want to chain two copy tasks, e.g. one for css and one for jpeg. The first sift will remove the files needed for the second task, no?
@jethroksy: looks like a bug
i'm looking for how to write copy tasks that can be chained, i don't see now sift can be used for that.
anyway i've used up too much of your time. if you or anybody else can come up with sample code i would be grateful.
@mobileink: can you make a gist of the paste you pasted?
what i'm trying to do is break down the copying (for gae) to separate tasks, one for each file type. probably not necessary but i like small composable things
the copying i can manage, it's making everything pipeline-able that's giving me trouble
@mobileink: commented on the gist
@micha: on a completely unrelated note, I spent way too much time this morning finding out that I had written (core/by-ext ".clj") instead of (core/by-ext [".clj"]). So I added preconditions to the by-foo stuff in core.clj, e.g. {:pre [(vector? exts)]} for by-ext. Do you want a PR?
probly sequential?
for that, so maps would explode
oh true
(and (seq x) (every? string x))
no thanks
Right, but for external tools, you guys were advocating the use of fake.class.path for external tools. Isn't a System property JVM-wide? Because there is other REPLs in that script, and they need access to their files also.
I'm wondering if advocating fake.class.path might be the wrong approach here (in general for external tools), and instead using clojure's provided classpath is the better approach.
I agree, but in issue https://github.com/boot-clj/boot/issues/249 you guys advocate fake.class.path, which is why I'm bringing this up 😛
boot is the only build tool that has pods, as far as i know, so nothing is designed with that in mind
I mean, I think the best hack (and stuart sierra caught onto this it seems, always ahead of us!), is to get the class loader from clojure, and derive the classpath from that.
That should theoretically always be correct, because even if people use a different "pod" library, clojure's classloader should be set correctly.
There might be resistance to that, due to this comment, https://github.com/clojure-emacs/refactor-nrepl/issues/97#issuecomment-121033676
basically the concept of banging on text files in editor plugins is not so compatible with boot
In fireplace/cider/misc, you can go to the source file of a library, but that is broken, because the library isn't on the fake classpath.
http://pastebin.com/u6ggjNtw this is the result of clojure.RT.baseLoader. Yeah, that makes sense. I'm more than happy to contribute back to cider/fireplace/other tools.
I think it's important to decide on a solution that works for as many cases as possible for 3rd party tools to integrate with.
I do agree that some of the refactoring make more sense elsewhere. But some minor ones make sense in the editor, so it's complicated really. And should you lose refactoring just because you're working on an ant/lein project now?
I don't think that you think we should, just, it's a hard problem really. And I think when it comes to editors, convenience is king, in practice
But anyway, the problem with the cider init code, is that it's lost in child pods, see: https://github.com/juxt/edge/blob/master/build.boot#L64 I have to resolve the default middleware in the parent pod, and pass it down to the child.
But yeah, my clojure.lang.RT has the original source paths. Which is what fake.class.path provides. I don't think children pods were picking up the source files unless I set the directories to include the source paths (which makes sense as children pods aren't part of a fileset really). But then that change would break parent pods, agh, difficult.
@jethroksy: @micha it was a regression in my code, but it is weird because BOOT_VERSION=2.5.5
should not have my new changes...
@micha so if you check the source I linked, I specify the directories. The source paths weren't included to the child pod, and I haven't seen an option to retrospectively run boot against a new list of source paths.
How can I add a file the project root as resource? Is it idiomatic to use (add-resource fs (java.io.File. ".") :include what-goes-here?)
?
ok the following works: (add-resource (java.io.File. ".") :include #{#"^version\.properties$"})
@micha Nope. But there would be if there were reprocessing in pods. I'd like to create a fully working system where you can isolate things within a task if you please.
the problem is that in order for boot tasks to be able to do what they do, they need to not need to know or care about the provenance of the files they're manipulating
so now you have many named places that all tasks need to recognize and handle specially
and some things simply become impossible, like tasks that modify .cljs.edn files for instance
I don't think I totally understand. I agree with what you're saying, but I don't understand how what I'm trying to achieve conflicts with that.
Essentially, I'm saying that it should be possible to isolate the dependencies of any task to it's bare minimum (as in, excluding the parent, instead of extending). This is obviously useful for clojurescript and clojure separation within a single jvm, but I'd love to make it generic.
I do agree that having the source paths in the pods classloader is a little crude of a solution. It would be really awesome to load boot in boot, and have a new fileset running within a pod. I need to contribute a fix to the repl task for with env, because it has the delay in reading the environment, and therefore can't be podded directly yet.
But I may have discovered an issue with podding and the repl task in general, because the default middleware isn't passed in from the parent.
There will need to be a way to pass information into that pod (default dependencies and middleware), for the cider middleware to run
the repl client communicates with nrepl over a socket, so it doesn't need to be in pod A
Right, but check edge, I create a pod for the nrepl server to run in. In pod C. I have to subvert the repl task though
Yeah, have a quick look if you can. The server task creates a pod, and then starts a repl in it.
Yeah, that would be awesome. I understand what you mean now. Yeah, socket repl should make that possible.
i am imagining the repl server generating expressions that it sends to clojure.main/repl in the pod where you want to compute
which means the nrepl code needs to be on the classpath in the pod where you want to compute
Problem there is being compatible with cider, losing cider would be a huge barrier to use in my opinion
Ah, I find the ability to jump to symbol really handy, plus the namespace cleaning is mandatory on one project
sorry to put a question there, but is there a way to set BOOT_VERSION from build.boot
?
@richiardiandrea: unfortunately, no, unless you are using boot-in-boot, in which case yes
I am using it 😄
Doesn't work for libraries, plus in a 750 line file you're not familiar with, I hate figuring out what the alias is.
@richiardiandrea I may be missing something, but is there something wrong with boot properties?
nothing wrong now the way to force the version for tests in my patch is to use a boot.properties
, but I was thinking of reading the version from the main version.properties
in the boot
's project root
Ah, I see. Higher level. Just wanted to double check you hadn't overlooked the obvious solution.
@micha, we got distracted by the ultimate isolation of the nrepl, I need to come up with a variable that matches these properties: - points to the fake classpath - always correct within a pod The latter is the blocked one currently. How is it best to solve this do you think? I'll patch cider nrepl to use it.
you can look at the set-fake-class-path!
function (i think that's what it's called) in boot.core
that seems like an ok place to put it, since it is fundamentally a description of the environment
But it's it okay for the parent pod to set that in it's environment? Instead of as a property? That way getting it from the environment would be reliable (once get env is patched to use pod/env in boot)
Boot having the classpath set at the jvm level makes less sense when you consider the theory behind pods.
What if I set boot.App/config("BOOT_VERSION", "2.6.0-SNAPSHOT")
at runtime? will the next boot in boot see it?
I wanted to be clever, but I think for now I will leave a static boot.properties
and tests will be called in the Makefile
I guess?
actually
I can generate a boot.properties
in the Makefile
before launching the tests
I don't even need that, I will just set the BOOT_VERSION env var
If I add a .cljs.edn file to a library project and put build-jar in the build-boot file before build-jar, then a .js file is created and added to the jar file. I want to use this .js file with a web worker in an application. Separate compilation is not an issue here, as the web worker does is not running shared. Now I figure the .js file needs to be moved into a resources directory in the jar file so that it will be loaded? I'm a bit lost at this point.
@laforge49: you can do something like this
(require '[ :as io[)
(deftask foo
[...]
(let [tmp (tmp-dir!)]
(with-pre-wrap [fs]
(io/copy (io/input-stream (io/resource "foo/bar.js")) (io/file tmp "foo" "bar.js"))
(-> fs (add-resource tmp) commit!))))
Hello again guys, how can I see if a file in a fileset is a "resource"?
@richiardiandrea: you can do this:
so source
files are usually shown in input-files
right?
ah yes i remember the table 😄
yes but my tasks are peculiar 😄 I am trying to test to-resource
or to-assets
so you can use the set operations to select the files with the roles you are interested in
trying, let's see 😄
When I use boot-reload
and serve two HTML files with some ClojureScript, is there a way to run separate :js-onjsload
functions for each of them?
The reason I'm asking is that I have a devcards.html
and an index.html
(serving my app). When I update devcards, boot-reload
keeps on calling the :on-jsload
in my app, which then errors out because it tries to mount my Om Next app from app.js
into devcards.html
...
The only quick solution I can think of is to have separate boot tasks for running the two.
A real solution would be to deprecate on-jsload
and fix the reload logic to always reload dependent namespaces (if foo.a
changes and foo.main
depends on that, foo.main
is always reloaded, and it would contain the app "reset" code)
:ids #{"app"}
simply disables all reloading for devcards.cljs.edn
. That's certainly not what I want. 😉
@juhoteperi: How hard would doing what you suggested be?
Quick fix: in the app, check if the last path segment of JS window.location.pathname
starts with devcards
and don't run any reload logic if that's the case.
@jannis: It would be somewhat complex as proper dependent namespace reloading requires complete dependency graph from somewhere. I think the best solution will be to reuse Figwheel client code which reads the dependency graph from Closure files and fixes several other problems.
It is on my todo list but I'm busy with other stuff currently so it will be some time before I get around to it.
Is there any way to "require"/load an EDN file with data from resources/
in CLJS code built with boot-cljs
?
i either install it in my local maven repo, or i deploy to clojars, or i upload it to s3
@micha: The macro worked out of the box with data/seed.edn
as the path. Perfect, thank you again