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 describedname
-- the name of the projectcreator
-- the project creatordescription
-- 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 dir
and file
elements.
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
of the 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 concat
task)
dir
elements may contain other directories or files. They should have
either a name
attribute, indicating its name, a type
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 documentationjava.xml
-- Default "prefab" build file for Java projectsspooky.xsl
-- The basic Spooky implementation, imported by the other stylesheetsspooky-html.xsl
-- Implementation of Spooky for XML/XSLT projectsspooky-java.xsl
-- Implementation of Spooky for Java projectsspooky-sample.xml
-- Sample project descriptionxslt.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, spooky-home
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 meta
element:
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 projectThere 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 makeBuildFile
template which is invoked to generate the default build file for the project.