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

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.

Related

How to update ERB template with inserted file in one Puppet run?

I am attempting to build a file in Puppet 5 using an ERB template. This ERB file uses class variables in the normal fashion, but is also constructed by inserting another Puppet-managed local file. However, I find that whenever I update the inserted file, it takes two Puppet runs to update the ERB-generated file. I want the updating to happen in one Puppet run.
It is easiest to see this with an example:
# test/manifests/init.pp
class test {
# This file will be inserted inside the next file:
file { '/tmp/partial.txt':
source => 'puppet:///modules/test/partial.txt',
before => File['/tmp/layers.txt'],
}
$inserted_file = file('/tmp/partial.txt')
# This file uses a template and has the above file inserted into it.
file { '/tmp/layers.txt':
content => template('test/layers.txt.erb')
}
}
Here is the template file:
# test/templates/layers.txt.erb
This is a file
<%= #inserted_file %>
If I make a change to the file test/files/partial.txt it takes two Puppet runs for the change to propagate to /tmp/layers.txt. For operational reasons it is important that the update happen in only one Puppet run.
I have tried using various dependencies (before, require, etc.) and even Puppet stages, but everything I tried still requires two Puppet runs.
While it is possible to achieve the same result using an exec resource with sed (or something similar), I would rather use a "pure" Puppet approach. Is this possible?
I am attempting to build a file in Puppet 5 using an ERB template. This ERB file uses class variables in the normal fashion, but is also constructed by inserting another Puppet-managed local file.
A Puppet run proceeds in three main phases:
Fact collection
Catalog building
Catalog application
Puppet manifests are completely evaluated during the catalog building phase, including evaluating all templates and function calls. Moreover, with a master / agent setup, catalog building happens on the master, so that's "the local system" during that phase. All target system modifications happen in the catalog application phase.
Thus your
$inserted_file = file('/tmp/partial.txt')
runs during catalog building, before File[/tmp/partial.txt] is applied. Since you give an absolute path to the file() function, it attempts to use the version already present on the catalog-building system, which is not necessarily even the machine for which the manifest is being built.
It's unclear to me why you want to install and manage the partial result in addition to the full templated file, but if indeed you do, then it seems to me that the best way to do so would be to feed both from the same source instead of trying to feed one from the other. To do this, you can make use of the file function's ability to load data from a file in the (any) module's files/ directory, similar to how File.source can do.
For example,
# test/manifests/init.pp
class test {
# Reads the contents of a module file:
$inserted_file = file('test/tmp/partial.txt')
file { '/tmp/partial.txt':
content => $inserted_file,
# resource relationship not necessary
}
file { '/tmp/layers.txt':
# interpolates $inserted_file:
content => template('test/layers.txt.erb')
}
}
Note also that the comments in your example manifest are misleading. Neither the file resource you present nor the contents of the file it manages are interpolated into your template, unless incidentally. What is interpolated is the value of the $inserted_file variable of the class that evaluates the template.

How to eval in a repl all forms in a file in Idea Cursive plugin for Clojure?

There is an "eval form hotkey", so if I manually eval each top-level form in a file I get what I want eventually. But I can't find a way to eval all forms at once. Sometimes form a depends on b which depends on c and manual evaluation is not convenient. Is that possible?
Set your shortcut for Load file in REPL in keymap(Preferences)

How to reload enlive template?

I have a web application that uses enlive.
If I change an html file used by a template I don't see the changes unless I restart figwheel.
I am using ring.middleware.reload/wrap-reload like this:
(-> routes
(ring.middleware.reload/wrap-reload {:dirs ["src" "resources"]})
...
...but without any effect.
Note that if I change any .clj or .cljs file I don't have to restart the server.
Following the link given by Piotrek I found this project which fixed my issue: https://github.com/kolov/enlive-reload
The fix was to wrap the routes with (wrap-enlive-reload) and now everything works just fine.

Output separate js files, but share some code with leiningen?

I'm a bit confused on how best to set up project.clj for my use case.
We're trying to embed new technology into the old, so we're creating separate pages using cljs and embedding them into our old application (thus, not a "single page app"). So, ideally, one page's javascript would be separated from another. Page X's javascript wouldn't contain Page Y's javascript except whatever functions are common between them.
I'm not really sure how best to set this up in project.clj. Imagine we have some common utilities in the "util" namespace, some code for Page X in the "page-x" namespace, and code for Page Y in the "page-y" namespace. What is the best way of setting this up without duplicating code? Is it possible?
I imagine the directory structure might look something like this:
src/cljs/util/...
src/cljs/page-x/...
src/cljs/page-y/...
Perhaps if I set up :source-paths as ["src/cljs/util", "src/cljs/page-x"] for the Page X build, and use page-y for the Page Y build? Just include the common code in the array as needed? Perhaps something like:
:page-x {
:source-paths ["src/cljs/util", "src/cljs/page-x"]
:compiler {
:output-to "dist/js/page-x.min.js"
:optimizations :advanced}}
:page-y {
:source-paths ["src/cljs/util", "src/cljs/page-y"]
:compiler {
:output-to "dist/js/page-y.min.js"
:optimizations :advanced}}
I'll keep messing around, but I thought I'd toss out the question as I do so.
Edit: Namespacing issues with the above idea. I have a src/cljs/util/util.cljs and src/cljs/page-x/main.cljs, for example. I believe the convention is the namespace of the file is the directory it's in, but if src/cljs/util is the directory specified in :source-paths, it's the root, so there is no namespace for util.cljs that I can tell. This leads me to some lovely ERROR - required "util.util" namespace never provided messages when leiningen runs.
As far as I can tell the compiler right now only works for outputing a single file, so no code splitting / common shared code bundles right now.
Tracking jira issue: http://dev.clojure.org/jira/browse/CLJS-848

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.