require all namespaces with a prefix - clojure

Hello fellow Clojurians,
I would like to make my Clojure project extensible by auto-loading its plugin namespaces from the classpath. I would like to solve it by require-ing every namespace that has a given prefix.
(require-all-ns 'module.custom)
;; this should require module.custom.video, module.custom.audio, module.custom.xxx, ...
Obviously all-ns does not work here as it only lists already loaded namespaces.
I can easily find all namespaces by walking the file system. But I want it to work when additional namespaces are inside a jar file on in an other directory on the classpath. I also need it to work when my program is packaged.
My question is: how to require every namespaces from the file system?
Thank you

Related

reading a file from a puppet erb template -- what is the working directory?

I have a bunch of config files with comments and various annotations that improve maintainability but the target application does not cope with this human oriented stuff.
I want to have an erb template that reads the file and transforms it into the format needed by the application. The actual processing is straight forward the bit that I have not figured out is how to construct the file name so the template reads it from the module/file directory.
Put another way what is the working directory when a template is being processed by puppet?
I don't know your exact need, but let me give you some hints:
If you're exploring how the puppet community uses templates you may want to google for the modules that use templates and get inspired from there (just paste the following in Google):
inurl:templates https://github.com/voxpupuli
Regarding your question:
what is the working directory when a template is being processed by puppet ?
The template is pulled from the module /etc/puppetlabs/code/environments/<your-env>/modules/<your-module>/templates/<your-path>/<your-template>.erb when a construction like the one bellow and the .conf file is generated. It may be using a temporary location for the generation (internally), but you don't have access and you shouldn't care:
file { "/etc/<your-path-to-your-conf>/<some-filename>":
path => "/etc/tomcat/testing/$name.conf",
content => template("template('#{module_name}/<your-path>/<your-template>.erb'),"),
}
Note: Most the examples (e.g. here or here) you find, hardcode the template path to your module, but you can also use #{module_name} as variable

Is there any way to force Clojure to map a parent namespace path to a certain directory?

I like that boot lets me put all my source files in the current directory. However, I would still like to develop code that refers to a parent namespace, to make it easier to import into other projects. For example, I'd like to make all my namespaces start with the same prefix, but still have their source files reside in the current directory, like this:
(ns polysyndeton.conjunctions ...) ; in ./conjunctions.clj
(ns polysyndeton.disjunctions ...) ; in ./disjunctions.clj
(ns polysyndeton.util ...) ; in ./util.clj
How can I tell boot or Clojure that any namespace starting with polysyndeton. should be found in the current directory?
I don't think it possible (without workarounds that are not recommended). Clojure uses the directory structure corresponding to the namespace segments to find source files on the classpath. So you must adhere to this structure.
Also see: What are common conventions for using namespaces in Clojure?
You can achieve this easily with a symlink. Note that this will map ANY strings like polysyndeton.polysyndeton.polysyndeton.{...}.util to the file util.clj:
ln -s . polysyndeton

Structuring a Library in SML

I'm currently building a testing library in Standard ML (using Poly/ML as the interpreter). I have the following directory structure:
project/a.sml
project/src/b.sml
project/src/c.sml
...
Where a.sml is just a bunch of calls to use
use "src/b.sml"
use "src/c.sml"
...
b.sml, c.sml etc. are all structure definitions like this
structure ComponentX
struct
...
end
which form nice, logically separated components of the library. I sometimes also create one module in one file, and then introduce a substructure within the same module in another file.
I can then use the testing library fine within the root directory of the project, by calling use "a.sml".
However, I can't seem to be able to use the code outside of its own directory, which is a bit of an issue. For example, say I'm in the parent directory of project. If I then call use "project/a.sml", the subsequent calls to use "src/x.sml" try to find a src directory in the parent (which doesn't exist).
Is there some way to do a relative use, or is there a better way to structure this altogether?
The use function itself in Poly/ML doesn't change the path when it is used recursively. You will need to change the path within the sub-directory explicitly using OS.FileSys.chDir. use is just a function so you could redefine it if you wanted. The OS.Path and OS.FileSys structures could be useful.
An alternative is to reorganise your code to make use of PolyML.make. You would have to rename your files to match the name of the structure that each file contains e.g. ComponentX.sml would contain structure ComponentX. For more on this see polyml.org/documentation/Reference/PolyMLMake.html or a this answer about Poly/ML with nested directory structures.

Get Clojure namespaces in current .jar file

I'm looking for a way to get a list of all the current namespaces in the current project, i.e. excluding namespaces in imported jars, libraries etc.
Currently I have found bultitude which seems pretty close to what I need and can do:
(bultitude.core/namespaces-on-classpath)
However this returns all the namespaces on the classpath, including "clojure.core" etc. rather than just the ones in the current project.
Is there an easy and reliable way to solve this?
what about the tools.namespace lib? there are the api:
find-namespaces-in-dir
find-namespaces-in-jarfile
find-namespaces-on-classpath
Well, it depends.
The idea behind bultitude is to provide a list of namespaces on the classpath. Any .clj files on that classpath will be accounted for.
You can, however, look up only namespaces beginning with a certain prefix. Usually projects also begin with a certain prefix in their namespaces. Would that work? Example from the readme:
user=> (b/namespaces-on-classpath :prefix "bultitude")
(bultitude.core-test bultitude.core)
If that isn't good enough, you can try to give it a classpath that only your files are on, but that may not work so well.
user=> (b/namespaces-on-classpath :prefix "bultitude" :classpath "src:test")
(bultitude.core bultitude.core-test)

reload middleware that handles explicitly loaded source files

Ring comes with the middleware 'reload' (https://github.com/ring-clojure/ring/blob/master/ring-devel/src/ring/middleware/reload.clj). It's based on ns-tracker (https://github.com/weavejester/ns-tracker). ns-tracker looks through source directories for likely source files that begin with an ns form. It builds a dependency graph from the information contained in those ns forms. This of course works perfectly, but only for dependencies explicitly included in the ns form.
There's an idiom in Clojure where a namespace is broken into several files. There is a single source file that defines a namespace (with an ns form). This file can contain any number of top-level forms, but notably will include loads, normally at the top level but not necessarily I suppose. The files loaded begin with in-ns forms. This is not as obscure a technique as you might think... clojure.core uses it.
The contents of these loaded files do not in themselves constitute modules, nor can they necessarily be coerced into being modules (circular dependencies etc).
ns-tracker does not scan source files looking for load expressions nor does it look for in-ns forms. And the reasons are clear enough. But it really messes up my workflow since changes to the loaded files, obviously, will not reload the namespace.
Does anyone know if there's a library that deals with explicitly loaded source files? If there isn't something I'll hack something together (probably by writing some ugly macro around load) and make it available publicly.
Okay, answering my question... I have extended ns-tracker and submitted a pull request. It's less hacky that I expected, actually reasonably reasonable.
My fork is at: https://github.com/hutch/ns-tracker
There are a number of changes to ns-tracker included. Specifically to my question, it supports the usage of load/in-ns in the way used by clojure/core.
You can use this fork in your projects by using the leiningen 'checkouts' mechanism.