Spooky is an XML vocabulary for describing project directory structures and the default content that the project should contain. Its intended that implementations of the Spooky language will use this description to create a project structure.
The goals for developing this language were to create a means of declaratively describing project structures so that these structures can be reused between projects. This enables developers to produce tools based on these standard project structures, such as standardised build files. It also allows simple documentation describing the contents of any given project to be generated directly from its description.
Spooky could potentially be used as a way to quickly add Ant build files, etc for pre-existing projects that don't use them, e.g. legacy apps using Makefiles. It can also be used for standardising project structures within an engineering team, etc.
(For the reasons behind the project name see this blog entry)
Spooky is part of an ongoing investigation into building little languages using XML tools and infastructure.
The current implementation of Spooky uses an XSLT stylesheet to generate an Ant build file capable of:
The build file generated from the project description can then be executed to actually construct the project.
While there is no formal schema for the Spooky language, the following DTD fragment describes the essence of the language:
<!ELEMENT project (meta, structure)> <!ELEMENT meta (home, name, creator, description)> <!ELEMENT structure (file|dir)*> <!ELEMENT dir (file|dir)*> <!ELEMENT file #ANY> <-- any elements you like --> <!ELEMENT home #PCDATA> <!ELEMENT name #PCDATA> <!ELEMENT creator #PCDATA> <!ELEMENT description #PCDATA> <!ATTLIST dir name #IMPLIED type #IMPLIED> <!ATTLIST file name #IMPLIED>
A Spooky project file is divided into two sections: a
meta block which
is intended to contain arbitrary metadata relating to the project as a whole. Supported
elements are currently:
home-- the home directory for the new project being described
name-- the name of the project
creator-- the project creator
description-- plain text description of the project
The bulk of the project is described in the
structure section which
contains the description of the projects hierarchical file system using nested
file elements indicate the location in which a file should be created. Each
file element should have a
name attribute containing the name of the file.
Usual operating system limits for naming files apply.
file elements can
containg any content you want: plain text or elements from other namespaces. The contents
file elements will be used as the default content for the file. If
none is provided then the file name will be used. (This is due to
a limitation in Ant which requires some form of text content for its
dir elements may contain other directories or files. They should have
name attribute, indicating its name, a
attribute indicating its "type", or both. If a name is not provided then the directory's
name will be the value of its type attribute.
Spooky views directories as typed containers, meaning that they contain a certain type of
content, e.g. source (
src), unit tests (
tests), or docs
docs). This is not intended to be a complete list and should be extended
where necessary. The type of a container is intended to affect the generation of default
build files for the project. For example a Java project build file may require the
definition of containers for source code, compiled classes, api docs, etc.
At present the implementation supports only a single directory of each type. However this is not unduly limiting as similar containers can be combined under a single root directory.
The following example file can be downloaded here
<project> <meta> <!-- where the project lives, and should be created --> <home>c:\temp\spooky</home> <!-- name of the project --> <name>example</name> <!-- creator (not currently used) --> <creator>Leigh Dodds</creator> <!-- description of the project --> <description>The Example Project</description> </meta> <structure> <!-- describes the project directory structure, assigns types to each directory, and indicates some default files --> <dir type="bin"/> <dir name="docs"> <dir name="api" type="doc"/> </dir> <dir type="lib"/> <dir name="src"> <dir name="resources"/> <dir name="tests" type="test"/> <dir name="java" type="src"/> </dir> <file name="README.txt"> This is the README file. </file> <file name="BUILD.txt"/> <file name="LICENSE.txt"/> <file name="CREDITS.txt"/> </structure> </project>
Sample output from running this input through the spooky-java implementation.
You can download the complete Spooky project, which includes the following files:
index.html-- This documentation
java.xml-- Default "prefab" build file for Java projects
spooky.xsl-- The basic Spooky implementation, imported by the other stylesheets
spooky-html.xsl-- Implementation of Spooky for XML/XSLT projects
spooky-java.xsl-- Implementation of Spooky for Java projects
spooky-sample.xml-- Sample project description
xslt.xml-- Default "prefab" build file for XML/XSLT projects
Select which implementation to use and then transform your project description using
the implementation stylesheet. Each stylesheet has a required parameter,
which should be the full path to where Spooky is installed. This is used to ensure that
copying over the prefab build files works correctly.
A second optional parameter called
output can also be provided. This should simply
be the name of the output file being generated and is used merely to customise the messages
displayed during the transformation.
Noting that Ant contains a number of tasks (creating directories, concatenating files, macro replacement during file copying, etc) that make it suitable as a way of creating cross-platform scripts for working with file systems, Spooky is implemented using XSLT stylesheets that generate Ant build files.
The implementation is divided up into a basic skeleton (spooky.xsl) which deals with creating the directory structure and default content. This implementation has no concept of directory types, and does not create a default build file for the project.
Using the XSLT
import element this basic framework is extended to provide two additional implementations;
one for generating Java projects (spooky-java.xsl) and one for
generating XML/XSLT projects (spooky-html.xsl). The latter is basically
where HTML (or other output) is generated using a single stylesheet applied to source XML documents.
Both of these implementations extend the basic framework by also adding a default Ant build file for the created project. The build files are based on one of two "prefab" build files included with the project. These "prefabs" are simple Ant build files that contain macros for the name and description of the files, and also locations of required directories.
Directories are considered to be simple typed containers whose contents are exposed to particular manipulations, e.g. compilation, copying, etc. Each implementation of spooky defines its own container types, but there are likely to be some basics (src, lib, doc, bin, etc) which are common to all (even if the operations on their contents may differ).
spooky-java requires the following directory types: src, test, bin, lib, doc.
spooky-html requires the following directory types: src, bin. It also supports
two additional metadata elements as children of the
extension-- indicate the extension of the files generates by the XSLT transformation. Default is ".html"
transform-- the path to the XSLT transformation used to build the project. The default is "site.xsl" in the root of the project
There are several ways in which Spooky can be customised.
The build files provided with Spooky while functional, are merely provided for demonstration purposes. A project will typically require additional Ant tasks, so simply customise the prefabs to provide a better default environment.
Again this is pretty straight-forward. Simple create another XSLT transformation, import
the basic spooky framework and override any of the named templates in the framework to
customise the output. Generally the only change will be to the
template which is invoked to generate the default build file for the project.