code as data: update a clojure file programmatically - clojure

Say you are using leiningen and you want to add a dependency to your project.clj file.
Instead of opening your editor and add this manually it must be possible to do so programmatically via the clojure language. Like so:
(update-in :dependencies conj ["enlive" "1.1.3"])
lein's update-in is not helping, since it does not make the change for good.
How would you guys do this?

Since project.clj is a Clojure file, you could put this at the top of your project.clj file :
(def my-deps [["enlive" "1.1.3"]])
..and later on :
:dependencies my-deps
Which means that you could even slurp an .edn file that you could edit however you want. I actually have this on the top of my build.boot (equivalent of project.clj but for boot) :
(defn slurp-deps []
(read-string (slurp "resources/deps.edn")))
And I use it like so :
:dependencies (slurp-deps)
The rest would just be updating your map and writing it back to the same .edn file.
If you want to reload your dependencies after that have a look at this SO question.
Note : as an alternative, I know that this is the way to do things in a REPL with boot, and that it will fetch/load the dependencies :
boot.user=> (set-env!
#_=> :resource-paths #{"src"}
#_=> :dependencies '[["enlive" "1.1.3"]])

Related

how to read properties file in clojure so that there no body can see my data-base password

In java we read the properties file by
Myclass.class.getProtectionDomain.getCodesource.getLocation.getPath()
But how this read in clojure
Demo on different class:
(def clazz clojure.lang.PersistentVector)
(.. clazz getProtectionDomain getCodeSource getLocation getPath)
You can also use ClojureWerkz's propertied library :
http://blog.clojurewerkz.org/blog/2013/10/07/introducing-propertied/
Propertied is a tiny Clojure library that makes working with Java property lists from Clojure a bit nicer.
It is very small in scope: convert java.util.Properties to and from an immutable map, load and store them to and from .properties files.

Clojure: Enlive has selector doesn't return anything

I'm trying to get images inside links from enlive document. The following works:
(html/select nodes [:a :img])
But this way I only get the image nodes, I want the links too!
So the next step was
(html/select nodes [:a (html/has [:img])])
But for some reason this returns just an empty list. I tried to browse the documentation and read the source code and it seems this should return links with img tags as child but maybe I missed something (or this is a bug)
Okay, figured it out. This needs second set of brackets. Why? I tried to read the documentation but I'm not sure (something about and rules). Anyway, here is the answer.
(html/select nodes [[:a (html/has [:img])]])

How to implement per user .emacs style config in clojure application?

I have a Clojure application which process some data in our company. So I want to obtain possibility of its customization throw .myapp.clj file or something like this.
It must be a simple script in clojure in which user can define own data processing principle. Also he must has possibility for tunning http back end and others application parts.
So, what is the best way to implement this fiche?
A couple ways come to mind with varying levels of sophistication. The simplest is to just have each user define a ~/.myall.clj in their home directory and then the start of the program would include a line:
(def per-user-config (load-file "~/.myall.clj"))
load-file reads a file and returns the last form read in the file. This allows you to compose config files nicely. For instance you can make a company wide template that has symbols for things like user-name and then load it from a per-user config file that defines user-name and then calls load-file on the template
config-template.clj:
{:app-name "foo"
:user-url (str "http://server.company:8080/users/" user-name)
:foo "bar"}
joes-config.clj:
(def user-name "joe")
(load-file "resources/global-config.clj")
this allows you to distribute most of the config through git while still allowing users to overwrite any arbitrary part of the config.

Cannot load and compile external clojure file

I'm trying to load and/or compile a .clj file from within another .clj file.
I'm doing this because the file I'm trying to load just contains a bunch of maps, and I intend eventually to replace these with an xml file. I could just :use the file and it'll work, but I'm trying to go through the exercise of loading an external bunch of data.
Through some random hacking around the repl (via emacs etc) I was able to (load "default_libs") as well as (compile...) it somehow (using different combinations of namespace qualifiers, ', and ") and get access to the maps, but after restarting the repl it didn't work any more, and anyway I had to use the full namespace name to get to the data.
This is lib_manager.clj:
(ns mycad.lib-manager
(:use [clojure repl]
[mycad utils]))
(compile 'mycad.default-libs)
(println mycad.default-libs/default-symbols)
This is the file I'm trying to load, default_libs.clj. The data here will eventually be some xml file, but I'm still pretty new at this, so for now I've just written a bunch of clojure maps directly.
(ns mycad.default-libs)
(def default-symbols {.... })
So the question is how can I load a bunch of data from a .clj file without really loading it into the namespace with (ns...) but instead treating it as a source of data using either load or compile?
Thanks for any help
Change the compile in your example into a load as you described it earlier in your question. Then the example will work.
compile is used for AOT compilation of a namespace. So it is not what you need here.
In case there is just a single map defined you can use load-file.
(def default-symbols (load-file "/file/path.clj"))
In case the "file" is actually somewhere on the classpath or by some other non-local stream, there is load-string.
(def default-symbols (load-string (slurp (io/reader stream))))
Lisps are very dynamic languages. Clojure, being Lisp, allows you to do the following:
user=> (eval (read-string "(def a 10)"))
#'user/a
user=> a
10
So you can load your file e.g. with a function read-all from here, and then (eval all forms:
(use 'clojure.java.io) ; for (reader ..) function
(import 'java.io.PushbackReader)
....
(doseq [f (read-all (PushbackReader. (reader "your/file.clj")))] (eval f))
Then if your file.clj contains (definitions only, they will be in your current namespace then you can use them as simple variables. If, though, your file.clj contained some namespace-changing forms ((ns..), (in-ns ..)), then things may be complicated, because current namespace will change. If such declarations are mandatory and cannot be deleted in the file itself, you can try and filter them, (evaling a form only if it is a definition.
Update: hm, I found out that (eval + (read-all is equivalent in some sense to (load-file:
(load-file "your/file.clj")
But in the case of load-file the namespace does not change even if there were namespace-changing commands - these namespaces are just loaded into memory, and you can refer to symbols in them as usual. It seems that this is what you need.

If I load a file with (ns my-namespace) in it, why doesn't it switch my current namepace?

I have a file like this
(ns boston.core)
If I (load "boston/core") from the REPL, however, my *ns* doesn't change to boston but remains user. Why is this?
This is because load just loads the specified file (into the boston.core namespace, as specified at the top of the file). It doesn't do anything to the current namespace in the REPL.
If you also want to switch namespace in the REPL to use whatever has just been loaded you need to do something like:
(load "boston/core")
(ns boston.core)
Note that "boston/core" has a slash because it refers to a file resource, whereas namespaces themselves use a dot as separators.