changeset 451:3f44c38bf870

Page templates, more flexible writer interfaces, small fixes.
author Jari-Matti M?kel? <jmjm@iki.fi>
date Wed, 24 Oct 2007 17:25:52 +0300
parents 4adfca0c71df
children f658ec4a15dd
files trunk/src/docgen/document/htmlwriter.d trunk/src/docgen/document/latexwriter.d trunk/src/docgen/document/plaintextwriter.d trunk/src/docgen/document/writer.d trunk/src/docgen/document/writers.d trunk/src/docgen/document/xmlwriter.d trunk/src/docgen/graphutils/dotwriter.d trunk/src/docgen/graphutils/modulenamewriter.d trunk/src/docgen/graphutils/modulepathwriter.d trunk/src/docgen/graphutils/writer.d trunk/src/docgen/graphutils/writers.d trunk/src/docgen/misc/misc.d trunk/src/docgen/misc/parser.d trunk/src/docgen/misc/textutils.d trunk/src/docgen/sourcelisting/htmlwriter.d trunk/src/docgen/sourcelisting/latexwriter.d trunk/src/docgen/sourcelisting/plaintextwriter.d trunk/src/docgen/sourcelisting/writer.d trunk/src/docgen/sourcelisting/writers.d trunk/src/docgen/sourcelisting/xmlwriter.d trunk/src/docgen/templates/default/html/firstpage.tpl trunk/src/docgen/templates/default/html/graphics.tpl trunk/src/docgen/templates/default/html/listing.tpl trunk/src/docgen/templates/default/latex/firstpage.tpl trunk/src/docgen/templates/default/latex/graphics.tpl trunk/src/docgen/templates/default/latex/listing.tpl trunk/src/docgen/templates/default/plaintext/graphics.tpl trunk/src/docgen/templates/default/plaintext/listing.tpl trunk/src/docgen/templates/htmlwriter.d trunk/src/docgen/templates/latexwriter.d trunk/src/docgen/templates/plaintextwriter.d trunk/src/docgen/templates/writer.d trunk/src/docgen/templates/writers.d trunk/src/docgen/templates/xmlwriter.d trunk/src/docgen/tests/doctemplate.d trunk/src/docgen/tests/graphs.d trunk/src/docgen/tests/listing.d trunk/src/docgen/teststuff/clean.sh trunk/src/docgen/teststuff/lstlang0.sty trunk/src/docgen/teststuff/modules.tex
diffstat 39 files changed, 616 insertions(+), 494 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/document/htmlwriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,33 @@
+/**
+ * Author: Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.document.htmlwriter;
+
+import docgen.document.writer;
+import tango.io.FileConduit : FileConduit;
+import tango.io.Print: Print;
+import tango.text.convert.Layout : Layout;
+
+// TODO: this is mostly broken now
+
+/**
+ * Writes a HTML document skeleton.
+ */
+class HTMLWriter : AbstractDocumentWriter!(2, "html") {
+  this(DocumentWriterFactory factory, OutputStream[] outputs) {
+    super(factory, outputs);
+  }
+
+  void generateDocument() {
+    auto output = new Print!(char)(new Layout!(char), outputs[0]);
+    
+    output.format(
+      templates["firstpage"],
+      factory.options.templates.title,
+      factory.options.templates.copyright,
+      factory.options.templates.versionString,
+      docgen_version
+    );
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/document/latexwriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,33 @@
+/**
+ * Author: Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.document.latexwriter;
+
+import docgen.document.writer;
+import tango.io.FileConduit : FileConduit;
+import tango.io.Print: Print;
+import tango.text.convert.Layout : Layout;
+
+/**
+ * Writes a LaTeX document skeleton.
+ */
+class LaTeXWriter : AbstractDocumentWriter!(1, "latex") {
+  this(DocumentWriterFactory factory, OutputStream[] outputs) {
+    super(factory, outputs);
+  }
+
+  void generateDocument() {
+    auto print = new Print!(char)(new Layout!(char), outputs[0]);
+    
+    print.format(
+      templates["firstpage"],
+      factory.options.templates.paperSize,
+      factory.options.templates.title,
+      factory.options.templates.versionString,
+      docgen_version,
+      timeNow(),
+      factory.options.listings.literateStyle ? "" : "%"
+    );
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/document/plaintextwriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,38 @@
+/**
+ * Author: Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.document.plaintextwriter;
+
+import docgen.document.writer;
+import docgen.misc.textutils;
+import tango.io.FileConduit : FileConduit;
+import tango.io.Print: Print;
+import tango.text.convert.Layout : Layout;
+
+//TODO: this is mostly broken now
+
+/**
+ * Writes a plain text document skeleton.
+ */
+class PlainTextWriter : AbstractDocumentWriter!(1, "plaintext") {
+  this(DocumentWriterFactory factory, OutputStream[] outputs) {
+    super(factory, outputs);
+  }
+
+  void generateDocument() {
+    auto output = new Print!(char)(new Layout!(char), outputs[0]);
+    
+    output(
+      plainTextHeading(factory.options.templates.title ~ " Reference Manual") ~
+      factory.options.templates.versionString ~ \n ~
+      "Generated by " ~ docgen_version ~ \n ~
+      timeNow() ~ \n \n \n ~
+      plainTextHorizLine() ~ \n \n ~
+      plainTextHeading("Table of Contents") ~ \n ~
+      plainTextHeading("Module documentation") ~ \n ~
+      plainTextHeading("File listings") ~ \n ~
+      plainTextHeading("Dependency diagram") ~ \n
+    );
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/document/writer.d	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,91 @@
+/**
+ * Author: Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.document.writer;
+
+public import docgen.misc.misc;
+import tango.io.model.IConduit : OutputStream;
+import tango.util.time.Date;
+import tango.util.time.Clock;
+import tango.text.convert.Sprint;
+import tango.io.stream.FileStream;
+import tango.io.Stdout;
+import tango.io.Print: Print;
+import tango.text.convert.Layout : Layout;
+
+char[] timeNow() {
+  auto date = Clock.toDate;
+  auto sprint = new Sprint!(char);
+  return sprint.format("{0} {1} {2} {3}",
+    date.asDay(),
+    date.asMonth(),
+    date.day,
+    date.year);
+}
+
+char[] loadTemplate(char[] style, char[] format, char[] templateName) {
+  char[] fn = "docgen/templates/"~style~"/"~format~"/"~templateName~".tpl";
+  
+  scope(failure) {
+    Stderr("Warning: error opening template "~fn~".");
+    return null;
+  }
+
+  auto file = new FileInput(fn);
+  auto content = new char[file.length];
+  auto bytesRead = file.read(content);
+  
+  assert(bytesRead == file.length, "Error reading template");
+  
+  file.close();
+  
+  return content;
+}
+
+const templateNames = [ "firstpage"[], "graphics"[], "listing"[] ];
+//const templateNames = [ "firstpage", "toc", "module", "depGraph", "graphics" ];
+
+interface DocumentWriter {
+  void generateDocument();
+  
+  /**
+   * Writes a tag for the given image to the output stream
+   */ 
+  void addGraphics(char[] imageFile);
+  
+  /**
+   * Writes a tag for the given source listing to the output stream;
+   */
+  void addListing(char[] moduleName, char[] contents, bool inline = true);
+}
+
+interface DocumentWriterFactory : WriterFactory {
+  DocumentWriter createDocumentWriter(OutputStream[] outputs);
+}
+
+template AbstractDocumentWriter(int n, char[] format) {
+  abstract class AbstractDocumentWriter : AbstractWriter!(DocumentWriterFactory, n), DocumentWriter {
+    protected char[][char[]] templates;
+         
+    this(DocumentWriterFactory factory, OutputStream[] outputs) {
+      super(factory, outputs);
+    
+      foreach(tpl; templateNames) {
+        templates[tpl] = loadTemplate(factory.options.templates.templateStyle, format, tpl);
+      }
+    }
+  
+    void addGraphics(char[] imageFile) {
+      auto print = new Print!(char)(new Layout!(char), outputs[0]);
+    
+      print.format(templates["graphics"], imageFile);
+    }
+    
+    void addListing(char[] moduleName, char[] contents, bool inline) {
+      auto print = new Print!(char)(new Layout!(char), outputs[0]);
+    
+      print.format(templates["listing"], moduleName, contents);
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/document/writers.d	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,32 @@
+/**
+ * Author: Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.document.writers;
+
+public import docgen.document.writer;
+import docgen.document.htmlwriter;
+import docgen.document.xmlwriter;
+import docgen.document.plaintextwriter;
+import docgen.document.latexwriter;
+
+class DefaultDocumentWriterFactory : AbstractWriterFactory, DocumentWriterFactory {
+  this(DocGenerator generator) {
+    super(generator);
+  }
+
+  DocumentWriter createDocumentWriter(OutputStream[] outputs) {
+    switch (options.docFormat) {
+      case DocFormat.LaTeX:
+        return new LaTeXWriter(this, outputs);
+      case DocFormat.XML:
+        return new XMLWriter(this, outputs);
+      case DocFormat.HTML:
+        return new HTMLWriter(this, outputs);
+      case DocFormat.PlainText:
+        return new PlainTextWriter(this, outputs);
+      default:
+        throw new Exception("Document writer type does not exist!");
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/document/xmlwriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,23 @@
+/**
+ * Author: Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.document.xmlwriter;
+
+import docgen.document.writer;
+import tango.io.FileConduit : FileConduit;
+import tango.io.Print: Print;
+import tango.text.convert.Layout : Layout;
+
+//TODO: this is mostly broken now
+
+/**
+ * TODO
+ */
+class XMLWriter : AbstractDocumentWriter!(2, "xml") {
+  this(DocumentWriterFactory factory, OutputStream[] outputs) {
+    super(factory, outputs);
+  }
+
+  void generateDocument() { /* TODO */ }
+}
\ No newline at end of file
--- a/trunk/src/docgen/graphutils/dotwriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/graphutils/dotwriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -12,17 +12,14 @@
 
 /**
  * Creates a graph rule file for the dot utility.
- *
- * TODO: support changing colors / graph style?
  */
-class DotWriter : AbstractWriter!(GraphWriterFactory, 2), GraphWriter {
-  this(GraphWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
+class DotWriter : AbstractGraphWriter {
+  this(GraphWriterFactory factory, DocumentWriter writer) {
+    super(factory, writer);
   }
 
-  void generateGraph(Vertex[] vertices, Edge[] edges) {
-    auto output2 = new Print!(char)(new Layout!(char), outputs[0]);
-    auto output = new Print!(char)(new Layout!(char), outputs[1]);
+  void generateGraph(Vertex[] vertices, Edge[] edges, OutputStream imageFile) {
+    auto image = new Print!(char)(new Layout!(char), imageFile);
 
     Vertex[][char[]] verticesByPckgName;
     if (factory.options.graph.GroupByFullPackageName)
@@ -33,64 +30,52 @@
         factory.options.graph.HighlightCyclicEdges)
       findCycles(vertices, edges);
 
-    if (cast(FileConduit)outputs[1]) {
+    if (cast(FileConduit)imageFile.conduit) {
       // name of the .dot file
-      char[] fn = (cast(FileConduit)outputs[1]).toUtf8();
+      char[] fn = (cast(FileConduit)imageFile.conduit).toUtf8();
       fn = FilePath(fn).file;
 
-      // .dot -> .svg/.png/.gif/...
-      fn = fn[0..$-3] ~ imageFormatExts[factory.options.graph.imageFormat];
-
-      switch(factory.options.docFormat) {
-        case DocFormat.LaTeX:
-          output2.format("\\includegraphics{{{0}}", fn);
-          break;
-        case DocFormat.XML:
-          // TODO
-          break;
-        case DocFormat.HTML:
-          output2.format(`<img src="{0}" />`, fn);
-          break;
-        case DocFormat.PlainText:
-          throw new Exception("Dot output is not supported in plain text mode.");
-      }
+      fn = fn[0..$-4];
+      
+      writer.addGraphics(fn);
     }
-
-    output("Digraph ModuleDependencies {\n");
+    
+    image("Digraph ModuleDependencies {\n");
 
     if (factory.options.graph.HighlightCyclicVertices)
       foreach (module_; vertices)
-        output.format(
+        image.format(
           `  n{0} [label="{1}"{2}];`\n,
           module_.id,
           module_.name,
-          (module_.isCyclic ? ",style=filled,fillcolor=tomato" : "")
+          (module_.isCyclic ? ",style=filled,fillcolor=" ~ factory.options.graph.nodeColor : "")
         );
     else
         foreach (i, module_; vertices)
-            output.format(`  n{0} [label="{1}"];`, i, module_.name);
+            image.format(`  n{0} [label="{1}"];`, i, module_.name);
 
     foreach (edge; edges)
-      output.format(
+      image.format(
         `  n{0} -> n{1}{2};`\n,
         edge.outgoing.id,
         edge.incoming.id,
-        (edge.isCyclic ? "[color=red]" : "")
+        (edge.isCyclic ? "[color=" ~ factory.options.graph.cyclicNodeColor ~ "]" : "")
       );
 
     if (factory.options.graph.GroupByFullPackageName)
       foreach (packageName, vertices; verticesByPckgName) {
-        output.format(
-          `  subgraph "cluster_{0}" {{`\n`    label="{0}";color=blue;`\n`    `,
+        image.format(
+          `  subgraph "cluster_{0}" {{`\n`    label="{0}";color=`
+          ~ factory.options.graph.clusterColor ~ `;`\n`    `,
           packageName,
           packageName
         );
 
         foreach (module_; vertices)
-          output.format(`n{0};`, module_.id);
-        output("\n  }\n");
+          image.format(`n{0};`, module_.id);
+        image("\n  }\n");
       }
 
-    output("}");
+    image("}");
   }
 }
\ No newline at end of file
--- a/trunk/src/docgen/graphutils/modulenamewriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/graphutils/modulenamewriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -9,22 +9,18 @@
 import tango.io.Print: Print;
 import tango.text.convert.Layout : Layout;
 
-/**
- * TODO: add support for html/xml/latex?
- */
-class ModuleNameWriter : AbstractWriter!(GraphWriterFactory, 1), GraphWriter {
-  this(GraphWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
+class ModuleNameWriter : AbstractGraphWriter {
+  this(GraphWriterFactory factory, DocumentWriter writer) {
+    super(factory, writer);
   }
 
-  void generateGraph(Vertex[] vertices, Edge[] edges) {
-    auto output = new Print!(char)(new Layout!(char), outputs[0]);
+  void generateGraph(Vertex[] vertices, Edge[] edges, OutputStream imageFile) {
 
     void doList(Vertex[] v, uint level, char[] indent = "") {
       if (!level) return;
 
       foreach (vertex; v) {
-        output(indent)(vertex.name).newline;
+        // TODO: output(indent)(vertex.name).newline;
         if (vertex.outgoing.length)
           doList(vertex.outgoing, level-1, indent ~ "  ");
       }
--- a/trunk/src/docgen/graphutils/modulepathwriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/graphutils/modulepathwriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -9,22 +9,18 @@
 import tango.io.Print: Print;
 import tango.text.convert.Layout : Layout;
 
-/**
- * TODO: add support for html/xml/latex?
- */
-class ModulePathWriter : AbstractWriter!(GraphWriterFactory, 1), GraphWriter {
-  this(GraphWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
+class ModulePathWriter : AbstractGraphWriter {
+  this(GraphWriterFactory factory, DocumentWriter writer) {
+    super(factory, writer);
   }
 
-  void generateGraph(Vertex[] vertices, Edge[] edges) {
-    auto output = new Print!(char)(new Layout!(char), outputs[0]);
+  void generateGraph(Vertex[] vertices, Edge[] edges, OutputStream imageFile) {
 
     void doPaths(Vertex[] v, uint level, char[] indent = "") {
       if (!level) return;
 
       foreach (vertex; v) {
-        output(indent)(vertex.location).newline;
+        // TODO: output(indent)(vertex.location).newline;
         if (vertex.outgoing.length)
           doPaths(vertex.outgoing, level-1, indent ~ "  ");
       }
--- a/trunk/src/docgen/graphutils/writer.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/graphutils/writer.d	Wed Oct 24 17:25:52 2007 +0300
@@ -6,14 +6,13 @@
 
 public import docgen.misc.misc;
 public import docgen.graphutils.primitives;
+public import docgen.document.writer;
 debug import tango.io.Stdout;
 
 interface GraphWriter {
-  void generateGraph(Vertex[], Edge[]);
+  void generateGraph(Vertex[] vertices, Edge[] edges, OutputStream imageFile);
 }
 
-alias void delegate(Vertex[], Edge[]) GraphWriterDg;
-
 /**
  * Marks all cycles in the graph.
  *
@@ -126,5 +125,14 @@
     +/
 
 interface GraphWriterFactory : WriterFactory {
-  GraphWriterDg createGraphWriter(OutputStream[] outputs);
+  GraphWriter createGraphWriter(DocumentWriter writer);
+}
+
+abstract class AbstractGraphWriter : AbstractWriter!(GraphWriterFactory), GraphWriter {
+  DocumentWriter writer;
+  
+  this(GraphWriterFactory factory, DocumentWriter writer) {
+    super(factory);
+    this.writer = writer;
+  }
 }
\ No newline at end of file
--- a/trunk/src/docgen/graphutils/writers.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/graphutils/writers.d	Wed Oct 24 17:25:52 2007 +0300
@@ -14,14 +14,14 @@
     super(generator);
   }
 
-  GraphWriterDg createGraphWriter(OutputStream[] outputs) {
+  GraphWriter createGraphWriter(DocumentWriter writer) {
     switch (options.graph.graphFormat) {
       case GraphFormat.Dot:
-        return &((new DotWriter(this, outputs)).generateGraph);
+        return new DotWriter(this, writer);
       case GraphFormat.ModuleNames:
-        return &((new ModuleNameWriter(this, outputs)).generateGraph);
+        return new ModuleNameWriter(this, writer);
       case GraphFormat.ModulePaths:
-        return &((new ModulePathWriter(this, outputs)).generateGraph);
+        return new ModulePathWriter(this, writer);
       default:
         throw new Exception("Graph writer type does not exist!");
     }
--- a/trunk/src/docgen/misc/misc.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/misc/misc.d	Wed Oct 24 17:25:52 2007 +0300
@@ -7,6 +7,7 @@
 
 char[] docgen_version = "Dil document generator 0.1";
 
+/** Supported document output formats. */
 enum DocFormat {
   LaTeX,
   XML,
@@ -14,19 +15,29 @@
   PlainText
 }
 
+/**
+ * Supported comment formats.
+ * 
+ * http://www.stack.nl/~dimitri/doxygen/docblocks.html
+ * http://www.digitalmars.com/d/ddoc.html
+ */
 enum CommentFormat {
   Ddoc,
   Doxygen
 }
 
+/** Supported image formats. */
 enum ImageFormat {
   PNG,
   SVG,
-  GIF
+  GIF,
+  PS
 }
 
-const imageFormatExts = [ "png", "svg", "gif" ];
+/** Image format extensions. */
+const imageFormatExts = [ "png", "svg", "gif", "ps" ];
 
+/** Supported graph writers. */
 enum GraphFormat {
   Dot,
   ModuleNames,
@@ -37,6 +48,9 @@
   GraphFormat graphFormat;
   ImageFormat imageFormat;
   uint depth;
+  char[] nodeColor = "tomato";
+  char[] cyclicNodeColor = "red";
+  char[] clusterColor = "";
   bool IncludeUnlocatableModules;
   bool HighlightCyclicEdges;
   bool HighlightCyclicVertices;
@@ -45,26 +59,47 @@
 }
 
 struct ListingOptions {
+  /// use literate programming symbols [LaTeX]
   bool literateStyle = true;
+  /// enable source code listings
   bool enableListings;
 }
 
 struct TemplateOptions {
+  /// project title
   char[] title = "Test project";
+  /// project version
   char[] versionString = "1.0";
+  /// copyright notice
   char[] copyright;
+  /// paper size [LaTeX]
   char[] paperSize = "a4paper";
+  /// use short file names [HTML]
+  bool shortFileNames;
+  /// page template style to use, customizable via docgen/templates
+  char[] templateStyle = "default";
+}
+
+struct ParserOptions {
+  /// location for the generated output
+  char[] outputDir;
+  /// paths to search for imports 
+  char[][] importPaths;
+  /// regexps for excluding modules
+  char[][] strRegexps;
 }
 
 struct DocGeneratorOptions {
-  
   GraphOptions graph;
   ListingOptions listings;
   TemplateOptions templates;
+  ParserOptions parser;
   DocFormat docFormat;
   CommentFormat commentFormat;
 }
 
+// ---
+
 interface DocGenerator {
   DocGeneratorOptions *options();
   void generate();
@@ -86,16 +121,22 @@
   }
 }
 
-template AbstractWriter(T, int n = -1) {
+template AbstractWriter(T, int n = 0) {
   abstract class AbstractWriter {
     protected T factory;
-    protected OutputStream[] outputs;
   
-    this(T factory, OutputStream[] outputs) {
-      this.factory = factory;
-      this.outputs = outputs;
-      static if (n > -1)
+    static if (n > 0) {
+      protected OutputStream[] outputs;
+      
+      this(T factory, OutputStream[] outputs) {
+        this.factory = factory;
+        this.outputs = outputs;
         assert(outputs.length == n, "Incorrect number of outputs");
+      }
+    } else {
+      this(T factory) {
+        this.factory = factory;
+      }
     }
   }
 }
\ No newline at end of file
--- a/trunk/src/docgen/misc/parser.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/misc/parser.d	Wed Oct 24 17:25:52 2007 +0300
@@ -143,6 +143,7 @@
 
         auto moduleFQNs = mod.getImports();
 
+        // TODO: add public/private attribute to the dg parameters 
         foreach (moduleFQN_; moduleFQNs) {
           auto loaded_mod = loadModule(moduleFQN_, depth == -1 ? depth : depth-1);
 
@@ -162,98 +163,4 @@
     // Ordered list of loaded modules.
     modules = loadedModules.values;
   }
-
-
-  /+ Old version - deprecated
-
-  /**
-   * Imports the transitive closure of imports starting from "filePath".
-   *
-   * The search can be filtered by providing a list of regexps that match the
-   * FQNs of modules to be ignored.
-   *
-   * TODO: integrate better with the docgen stuff - there's no need to
-   * scan&parse several times
-   */
-  public static void loadModules2(string filePath, string[] importPaths,
-                                 string[] strRegexps,
-                                 bool IncludeUnlocatableModules,
-                                 out Vertex[] vertices, out Edge[] edges,
-                                 out Module[] modules) {
-    // Init regular expressions.
-    RegExp[] regexps;
-    foreach (strRegexp; strRegexps)
-      regexps ~= new RegExp(strRegexp);
-
-    // Add directory of file and global directories to import paths.
-    auto fileDir = (new FilePath(filePath)).folder();
-    if (fileDir.length)
-      importPaths ~= fileDir;
-    importPaths ~= GlobalSettings.importPaths;
-
-    Vertex[string] loadedModules;
-    Edge[] _edges;
-    Module[] _modules;
-
-    int modCounter = 0;
-
-    void addModule(Vertex mod) {
-      assert(!(mod.location in loadedModules));
-
-      mod.id = modCounter++;
-      loadedModules[mod.location] = mod;
-    }
-
-    Vertex loadModule(string moduleFQNPath) {
-      // Return already loaded module.
-      auto mod_ = moduleFQNPath in loadedModules;
-      if (mod_ !is null) return *mod_;
-
-      // Ignore module names matching regular expressions.
-      foreach (rx; regexps)
-      if (rx.test(replace(moduleFQNPath, dirSep, '.')))
-        return null;
-
-      auto modulePath = findModulePath(moduleFQNPath, importPaths);
-      if (moduleFQNPath == filePath) modulePath = filePath;
-      auto FQN = replace(moduleFQNPath, dirSep, '.');
-
-      Vertex mod;
-
-      if (modulePath is null) {
-        if (IncludeUnlocatableModules) {
-          mod = new Vertex(FQN, moduleFQNPath);
-          addModule(mod);
-        }
-      } else {
-        mod = new Vertex(FQN, moduleFQNPath);
-        addModule(mod);
-
-        auto m = new Module(modulePath);
-        _modules ~= m;
-        m.parse();
-
-        auto moduleFQNs = m.getImports();
-
-        foreach (moduleFQN_; moduleFQNs) {
-          auto loaded_mod = loadModule(moduleFQN_);
-
-          if (loaded_mod !is null)
-            loaded_mod.addChild(mod);
-        }
-      }
-
-      return mod;
-    } // loadModule
-
-    loadModule(filePath);
-
-    // Finished loading modules.
-
-    // Ordered list of loaded modules.
-    vertices = loadedModules.values;
-    edges = _edges;
-    modules = _modules;
-  }
-  +/
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/misc/textutils.d	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,50 @@
+/**
+ * Author: Aziz Köksal & Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.misc.textutils;
+
+import tango.io.model.IConduit;
+import tango.io.stream.GreedyStream;
+
+// copied from Generate.d
+char[] xml_escape(char[] text)
+{
+  char[] result;
+  result.length = text.length;
+  foreach(c; text)
+    switch(c)
+    {
+      case '<': result ~= "&lt;";  break;
+      case '>': result ~= "&gt;";  break;
+      case '&': result ~= "&amp;"; break;
+      default:  result ~= c;
+    }
+  return result;
+}
+
+class XMLEscapeOutput : GreedyOutput {
+  this (OutputStream stream) {
+    super(stream);
+  }
+
+  uint write (void[] src) {
+    return super.write( xml_escape(cast(char[])src) );
+  }
+}
+
+char[] plainTextHeading(char[] s) {
+  char[] line;
+  line.length = 80;
+  line[] = "=";
+
+  return s ~ \n ~ line[0..s.length].dup ~ \n ~ \n;
+}
+
+char[] plainTextHorizLine(int l = 80) {
+  char[] line;
+  line.length = 80;
+  line[] = "-";
+  
+  return line[0..l].dup ~ \n;
+}
\ No newline at end of file
--- a/trunk/src/docgen/sourcelisting/htmlwriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/sourcelisting/htmlwriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -5,21 +5,39 @@
 module docgen.sourcelisting.htmlwriter;
 
 public import docgen.sourcelisting.writer;
+import docgen.misc.textutils;
 import dil.Parser;
 import tango.io.protocol.Writer : Writer;
 import tango.io.FileConduit : FileConduit;
+import tango.io.stream.FileStream;
 import tango.io.Print: Print;
 import tango.text.convert.Layout : Layout;
+import tango.text.stream.LineIterator;
 
 
 /**
  * TODO
  */
-class HTMLWriter : AbstractWriter!(ListingWriterFactory, 2), ListingWriter {
-  this(ListingWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
+class HTMLWriter : AbstractWriter!(ListingWriterFactory), ListingWriter {
+  DocumentWriter writer;
+  
+  this(ListingWriterFactory factory, DocumentWriter writer) {
+    super(factory);
+    this.writer = writer;
   }
-
+  
   void generateListing(Parser parser) { /* TODO */ }
-  void generateListing(InputStream input, char[] moduleName) { /* TODO */ }
+  
+  void generateListing(InputStream input, OutputStream output, char[] moduleName) {
+    auto inputStream = cast(FileInput)input;
+    auto content = new char[inputStream.length];
+    auto bytesRead = inputStream.read (content);
+    
+    assert(bytesRead == inputStream.length, "Error reading source file");
+    
+    writer.addListing(
+      moduleName,
+      xml_escape(content)
+    );
+  }
 }
\ No newline at end of file
--- a/trunk/src/docgen/sourcelisting/latexwriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/sourcelisting/latexwriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -8,33 +8,29 @@
 import dil.Parser;
 import tango.io.protocol.Writer : Writer;
 import tango.io.FileConduit : FileConduit;
-import tango.io.Print;
+import tango.io.Print: Print;
 import tango.io.FilePath;
 import tango.text.convert.Layout : Layout;
 
 /**
  * Adds a code listing section for the given file. 
  */
-class LaTeXWriter : AbstractWriter!(ListingWriterFactory, 2), ListingWriter {
-  this(ListingWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
+class LaTeXWriter : AbstractWriter!(ListingWriterFactory), ListingWriter {
+  DocumentWriter writer;
+  
+  this(ListingWriterFactory factory, DocumentWriter writer) {
+    super(factory);
+    this.writer = writer;
   }
 
-  void generateListing(Parser parser) {
-    auto output2 = new Print!(char)(new Layout!(char), outputs[0]);
-    auto output = new Print!(char)(new Layout!(char), outputs[1]);
-    /* TODO */
-  }
+  void generateListing(Parser parser) { /* TODO */ }
   
-  void generateListing(InputStream input, char[] moduleName) {
-    auto output2 = new Print!(char)(new Layout!(char), outputs[0]);
-
-    if (cast(FileConduit)outputs[1]) {
-      char[] fn = (cast(FileConduit)outputs[1]).toUtf8();
-      fn = FilePath(fn).file;
-      output2.format("\\section{{Module {0}}\n", moduleName);
-      output2.format("\\lstinputlisting[language=d]{{{0}}\n", fn);
-    }
-    outputs[1].copy(input);
+  void generateListing(InputStream input, OutputStream output, char[] moduleName) {
+    output.copy(input);
+    
+    writer.addListing(
+      moduleName,
+      FilePath((cast(FileConduit)output.conduit).toUtf8()).file
+    );
   }
 }
--- a/trunk/src/docgen/sourcelisting/plaintextwriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/sourcelisting/plaintextwriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -5,20 +5,33 @@
 module docgen.sourcelisting.plaintextwriter;
 
 public import docgen.sourcelisting.writer;
+import docgen.misc.textutils;
 import dil.Parser;
 import tango.io.protocol.Writer : Writer;
 import tango.io.FileConduit : FileConduit;
 import tango.io.Print: Print;
 import tango.text.convert.Layout : Layout;
+import tango.io.FilePath;
 
 /**
  * TODO
  */
-class PlainTextWriter : AbstractWriter!(ListingWriterFactory, 2), ListingWriter {
-  this(ListingWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
+class PlainTextWriter : AbstractWriter!(ListingWriterFactory), ListingWriter {
+  DocumentWriter writer;
+  
+  this(ListingWriterFactory factory, DocumentWriter writer) {
+    super(factory);
+    this.writer = writer;
   }
 
   void generateListing(Parser parser) { /* TODO */ }
-  void generateListing(InputStream input, char[] moduleName) { /* TODO */ }
+  
+  void generateListing(InputStream input, OutputStream output, char[] moduleName) {
+    output.copy(input);
+    
+    writer.addListing(
+      moduleName,
+      FilePath((cast(FileConduit)output.conduit).toUtf8()).file
+    );
+  }
 }
\ No newline at end of file
--- a/trunk/src/docgen/sourcelisting/writer.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/sourcelisting/writer.d	Wed Oct 24 17:25:52 2007 +0300
@@ -5,14 +5,15 @@
 module docgen.sourcelisting.writer;
 
 public import docgen.misc.misc;
+public import docgen.document.writer;
 import dil.Parser;
 import tango.io.model.IConduit : OutputStream, InputStream;
 
 interface ListingWriter {
   void generateListing(Parser parser);
-  void generateListing(InputStream input, char[] moduleName);
+  void generateListing(InputStream input, OutputStream output, char[] moduleName);
 }
 
 interface ListingWriterFactory : WriterFactory {
-  ListingWriter createListingWriter(OutputStream[] outputs);
+  ListingWriter createListingWriter(DocumentWriter writer);
 }
\ No newline at end of file
--- a/trunk/src/docgen/sourcelisting/writers.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/sourcelisting/writers.d	Wed Oct 24 17:25:52 2007 +0300
@@ -15,16 +15,16 @@
     super(generator);
   }
 
-  ListingWriter createListingWriter(OutputStream[] outputs) {
+  ListingWriter createListingWriter(DocumentWriter writer) {
     switch (options.docFormat) {
       case DocFormat.LaTeX:
-        return new LaTeXWriter(this, outputs);
+        return new LaTeXWriter(this, writer);
       case DocFormat.XML:
-        return new XMLWriter(this, outputs);
+        return new XMLWriter(this, writer);
       case DocFormat.HTML:
-        return new HTMLWriter(this, outputs);
+        return new HTMLWriter(this, writer);
       case DocFormat.PlainText:
-        return new PlainTextWriter(this, outputs);
+        return new PlainTextWriter(this, writer);
       default:
         throw new Exception("Listing writer type does not exist!");
     }
--- a/trunk/src/docgen/sourcelisting/xmlwriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/sourcelisting/xmlwriter.d	Wed Oct 24 17:25:52 2007 +0300
@@ -14,11 +14,14 @@
 /**
  * TODO
  */
-class XMLWriter : AbstractWriter!(ListingWriterFactory, 2), ListingWriter {
-  this(ListingWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
+class XMLWriter : AbstractWriter!(ListingWriterFactory), ListingWriter {
+  DocumentWriter writer;
+  
+  this(ListingWriterFactory factory, DocumentWriter writer) {
+    super(factory);
+    this.writer = writer;
   }
 
   void generateListing(Parser parser) { /* TODO */ }
-  void generateListing(InputStream input, char[] moduleName) { /* TODO */ }
+  void generateListing(InputStream input, OutputStream output, char[] moduleName) { /* TODO */ }
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/templates/default/html/firstpage.tpl	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+  <title>{0} Reference Manual</title>
+  <meta name="author" content="{1}" />
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <link rel="stylesheet" href="style.css" media="all" title="default" />
+  <link rel="stylesheet" href="print.css" media="print" />
+</head>
+<body>
+<h1>{0} Reference Manual</h1>
+<h2>{2}</h2>
+<h2>Generated by {3}</h2>
+<h3>{4}</h3>
+<hr />
+<h2>Table of Contents</h2>
+<hr />
+<h2>Module documentation</h2>
+<hr />
+<h2>File listings</h2>
+<hr />
+<h2>Dependency diagram</h2>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/templates/default/html/graphics.tpl	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,1 @@
+<img src="{}" />
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/templates/default/html/listing.tpl	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,2 @@
+<h2>Module {}</h2>
+<pre style="dcode">{}</pre>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/templates/default/latex/firstpage.tpl	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,67 @@
+\documentclass[{0}]{{book}
+\usepackage{{a4wide}
+\usepackage{{makeidx}
+\usepackage{{fancyhdr}
+\usepackage{{graphicx}
+\usepackage{{multicol}
+\usepackage{{float}
+\usepackage{{textcomp}
+\usepackage{{alltt}
+\usepackage[utf8]{{inputenc}
+\usepackage{{listings}
+\lstnewenvironment{{dcode}
+{{ \lstset{{language=d} }
+{{}
+\lstset{{
+  {5} literate=
+  {5}          {{<=}{{{{$\leq$}}1
+  {5}          {{>=}{{{{$\geq$}}1
+  {5}          {{!=}{{{{$\neq$}}1
+  {5}          {{...}{{{{$\dots$}}1
+  {5}          {{~}{{{{$\sim$}}1,
+  stringstyle=\ttfamily,
+  inputencoding=utf8,
+  extendedchars=false,
+  columns=fixed,
+  basicstyle=\small
+}
+\makeindex
+\setcounter{{tocdepth}{{1}
+\newcommand{{\clearemptydoublepage}{{\newpage{{\pagestyle{{empty}\cleardoublepage}}
+\def\thechapter{{\Roman{{chapter}}
+\def\thesection{{\arabic{{chapter}.\arabic{{section}}
+% \renewcommand{{\footrulewidth}{{0.4pt}
+
+\begin{{document}
+
+\begin{{titlepage}
+\vspace*{{7cm}
+\begin{{center}
+{{\Large {1} Reference Manual\\[1ex]\large {2} }\\
+\vspace*{{1cm}
+{{\large Generated by {3} }\\
+\vspace*{{0.5cm}
+{{\small {4} }\\
+\end{{center}
+\end{{titlepage}
+
+\clearemptydoublepage
+
+\tableofcontents
+\thispagestyle{{empty}
+
+\clearemptydoublepage
+
+\setcounter{{page}{{1}
+\chapter{{Module documentation}
+\input{{modules}
+
+\chapter{{File listings}
+\input{{files}
+
+\chapter{{Dependency diagram}
+\input{{dependencies}
+
+\printindex
+
+\end{{document}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/templates/default/latex/graphics.tpl	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,1 @@
+\includegraphics{{{0}}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/templates/default/latex/listing.tpl	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,3 @@
+\section{{Module {0}}
+\lstinputlisting[language=d]{{{1}}
+\clearpage
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/templates/default/plaintext/graphics.tpl	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,1 @@
+See {}.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/templates/default/plaintext/listing.tpl	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,3 @@
+Module {0}
+See {1}.
+
--- a/trunk/src/docgen/templates/htmlwriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/**
- * Author: Jari-Matti Mäkelä
- * License: GPL3
- */
-module docgen.templates.htmlwriter;
-
-import docgen.templates.writer;
-import tango.io.FileConduit : FileConduit;
-import tango.io.Print: Print;
-import tango.text.convert.Layout : Layout;
-
-// TODO: this is mostly broken now
-
-/**
- * Writes a HTML document skeleton.
- */
-class HTMLWriter : AbstractWriter!(TemplateWriterFactory, 2), TemplateWriter {
-  this(TemplateWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
-  }
-
-  void generateTemplate() {
-    auto output = new Print!(char)(new Layout!(char), outputs[0]);
-    
-    output(`
-    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-    <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-      <title>` ~ factory.options.templates.title ~ ` Reference Manual</title>
-      <meta name="AUTHOR" content="` ~ factory.options.templates.copyright ~ `" />
-      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-      <link rel="stylesheet" href="style.css" media="all" title="default" />
-      <link rel="stylesheet" href="print.css" media="print" />
-    </head>
-    <body>
-    <h1>` ~ factory.options.templates.title ~ ` Reference Manual</h1>
-    <h2>` ~ factory.options.templates.versionString ~ `</h2>
-    <h2>Generated by ` ~ docgen_version ~ `</h2>
-    <h3>` ~ timeNow() ~ `</h3>
-    <hr />
-    <h2>Table of Contents</h2>
-    <hr />
-    <h2>Module documentation</h2>
-    <hr />
-    <h2>File listings</h2>
-    <hr />
-    <h2>Dependency diagram</h2>
-    </body>
-    </html>`);
-  }
-}
\ No newline at end of file
--- a/trunk/src/docgen/templates/latexwriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/**
- * Author: Jari-Matti Mäkelä
- * License: GPL3
- */
-module docgen.templates.latexwriter;
-
-import docgen.templates.writer;
-import tango.io.FileConduit : FileConduit;
-import tango.io.Print: Print;
-import tango.text.convert.Layout : Layout;
-
-/**
- * Writes a LaTeX document skeleton.
- */
-class LaTeXWriter : AbstractWriter!(TemplateWriterFactory, 1), TemplateWriter {
-  this(TemplateWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
-  }
-
-  void generateTemplate() {
-    auto output = new Print!(char)(new Layout!(char), outputs[0]);
-    
-    output(`
-    \documentclass[` ~ factory.options.templates.paperSize ~ `]{book}
-    \usepackage{a4wide}
-    \usepackage{makeidx}
-    \usepackage{fancyhdr}
-    \usepackage{graphicx}
-    \usepackage{multicol}
-    \usepackage{float}
-    \usepackage{textcomp}
-    \usepackage{alltt}
-    \usepackage[utf8]{inputenc}
-    \usepackage{listings}
-    \lstnewenvironment{dcode}
-    { \lstset{language=d} }
-    {}
-    \lstset{` ~
-      (factory.options.listings.literateStyle ? ` 
-      literate=
-               {<=}{{$\leq$}}1
-               {>=}{{$\geq$}}1
-               {!=}{{$\neq$}}1
-               {...}{{$\dots$}}1
-               {~}{{$\sim$}}1,` : ``) ~ `
-      stringstyle=\ttfamily,
-      inputencoding=utf8,
-      extendedchars=false,
-      columns=fixed,
-      basicstyle=\small
-    }
-    \makeindex
-    \setcounter{tocdepth}{1}
-    \newcommand{\clearemptydoublepage}{\newpage{\pagestyle{empty}\cleardoublepage}}
-    \def\thechapter{\Roman{chapter}}
-    \def\thesection{\arabic{chapter}.\arabic{section}}
-    % \renewcommand{\footrulewidth}{0.4pt}
-
-    \begin{document}
-
-    \begin{titlepage}
-    \vspace*{7cm}
-    \begin{center}
-    {\Large ` ~ factory.options.templates.title ~ ` Reference Manual\\[1ex]\large ` ~
-        factory.options.templates.versionString ~ ` }\\
-    \vspace*{1cm}
-    {\large Generated by ` ~ docgen_version ~ `}\\
-    \vspace*{0.5cm}
-    {\small ` ~ timeNow() ~ `}\\
-    \end{center}
-    \end{titlepage}
-
-    \clearemptydoublepage
-
-    \tableofcontents
-    \thispagestyle{empty}
-
-    \clearemptydoublepage
-
-    \setcounter{page}{1}
-    \chapter{Module documentation}
-    \input{modules}
-
-    \chapter{File listings}
-    \input{files}
-
-    \chapter{Dependency diagram}
-    \input{dependencies}
-
-    \printindex
-
-    \end{document}
-    `);
-  }
-}
\ No newline at end of file
--- a/trunk/src/docgen/templates/plaintextwriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/**
- * Author: Jari-Matti Mäkelä
- * License: GPL3
- */
-module docgen.templates.plaintextwriter;
-
-import docgen.templates.writer;
-import tango.io.FileConduit : FileConduit;
-import tango.io.Print: Print;
-import tango.text.convert.Layout : Layout;
-
-//TODO: this is mostly broken now
-
-/**
- * Writes a plain text document skeleton.
- */
-class PlainTextWriter : AbstractWriter!(TemplateWriterFactory, 1), TemplateWriter {
-  this(TemplateWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
-  }
-
-  void generateTemplate() {
-    auto output = new Print!(char)(new Layout!(char), outputs[0]);
-    
-    char[] line, line2;
-    line.length = line2.length = 80;
-    line[] = "=";
-    line2[] = "-";
-    
-    char[] h(char[] s) {
-      return s ~ \n ~ line[0..s.length] ~ \n;
-    }
-    
-    output(
-      h(factory.options.templates.title ~ " Reference Manual") ~ \n ~
-      factory.options.templates.versionString ~ \n ~
-      "Generated by " ~ docgen_version ~ \n ~
-      timeNow() ~ \n \n \n ~
-      line2 ~ \n \n \n ~
-      h("Table of Contents") ~ \n \n ~
-      h("Module documentation") ~ \n \n ~
-      h("File listings") ~ \n \n ~
-      h("Dependency diagram") ~ \n \n
-    );
-  }
-}
\ No newline at end of file
--- a/trunk/src/docgen/templates/writer.d	Wed Oct 17 20:55:55 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/**
- * Author: Jari-Matti Mäkelä
- * License: GPL3
- */
-module docgen.templates.writer;
-
-public import docgen.misc.misc;
-import tango.io.model.IConduit : OutputStream;
-import tango.util.time.Date;
-import tango.util.time.Clock;
-import tango.text.convert.Sprint;
-
-interface TemplateWriter {
-  void generateTemplate();
-}
-
-char[] timeNow() {
-  auto date = Clock.toDate;
-  auto sprint = new Sprint!(char);
-  return sprint.format("{0} {1} {2} {3}",
-    date.asDay(),
-    date.asMonth(),
-    date.day,
-    date.year).dup;
-}
-
-interface TemplateWriterFactory : WriterFactory {
-  TemplateWriter createTemplateWriter(OutputStream[] outputs);
-}
\ No newline at end of file
--- a/trunk/src/docgen/templates/writers.d	Wed Oct 17 20:55:55 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/**
- * Author: Jari-Matti Mäkelä
- * License: GPL3
- */
-module docgen.templates.writers;
-
-public import docgen.templates.writer;
-import docgen.templates.htmlwriter;
-import docgen.templates.xmlwriter;
-import docgen.templates.plaintextwriter;
-import docgen.templates.latexwriter;
-
-class DefaultTemplateWriterFactory : AbstractWriterFactory, TemplateWriterFactory {
-  this(DocGenerator generator) {
-    super(generator);
-  }
-
-  TemplateWriter createTemplateWriter(OutputStream[] outputs) {
-    switch (options.docFormat) {
-      case DocFormat.LaTeX:
-        return new LaTeXWriter(this, outputs);
-      case DocFormat.XML:
-        return new XMLWriter(this, outputs);
-      case DocFormat.HTML:
-        return new HTMLWriter(this, outputs);
-      case DocFormat.PlainText:
-        return new PlainTextWriter(this, outputs);
-      default:
-        throw new Exception("Template writer type does not exist!");
-    }
-  }
-}
\ No newline at end of file
--- a/trunk/src/docgen/templates/xmlwriter.d	Wed Oct 17 20:55:55 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-/**
- * Author: Jari-Matti Mäkelä
- * License: GPL3
- */
-module docgen.templates.xmlwriter;
-
-import docgen.templates.writer;
-import tango.io.FileConduit : FileConduit;
-import tango.io.Print: Print;
-import tango.text.convert.Layout : Layout;
-
-//TODO: this is mostly broken now
-
-/**
- * TODO
- */
-class XMLWriter : AbstractWriter!(TemplateWriterFactory, 1), TemplateWriter {
-  this(TemplateWriterFactory factory, OutputStream[] outputs) {
-    super(factory, outputs);
-  }
-
-  void generateTemplate() { /* TODO */ }
-}
\ No newline at end of file
--- a/trunk/src/docgen/tests/doctemplate.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/tests/doctemplate.d	Wed Oct 24 17:25:52 2007 +0300
@@ -5,7 +5,7 @@
 module docgen.tests.doctemplate;
 
 import docgen.tests.common;
-import docgen.templates.writers;
+import docgen.document.writers;
 import tango.io.Stdout;
 import tango.io.FileConduit;
 import tango.io.protocol.Writer : Writer;
@@ -17,11 +17,11 @@
   gen.options.docFormat = DocFormat.LaTeX;
   auto fname = "doctemplate.tex";
   
-  auto gwf = new DefaultTemplateWriterFactory(gen);
+  auto gwf = new DefaultDocumentWriterFactory(gen);
   auto file = new FileConduit("docgen/teststuff/" ~ fname, FileConduit.WriteCreate);
-  auto writer = gwf.createTemplateWriter( [ file ] );
+  auto writer = gwf.createDocumentWriter( [ file ] );
   
-  writer.generateTemplate();
+  writer.generateDocument();
   
   file.close();
 }
\ No newline at end of file
--- a/trunk/src/docgen/tests/graphs.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/tests/graphs.d	Wed Oct 24 17:25:52 2007 +0300
@@ -7,6 +7,7 @@
 import docgen.tests.common;
 import docgen.misc.parser;
 import docgen.graphutils.writers;
+import docgen.document.writers;
 import tango.io.Stdout;
 import tango.io.FileConduit;
 import dil.Module;
@@ -14,17 +15,18 @@
 void saveDefaultGraph(Vertex[] vertices, Edge[] edges, char[] fname) {
   auto gen = new TestDocGenerator;
   gen.options.graph.HighlightCyclicVertices = true;
+  gen.options.graph.imageFormat = ImageFormat.SVG;
   gen.options.graph.graphFormat = GraphFormat.Dot;
   //gen.options.graph.graphFormat = GraphFormat.ModuleNames;
   //gen.options.graph.graphFormat = GraphFormat.ModulePaths;
   gen.options.graph.depth = 5;
-  
+  auto ddf = new DefaultDocumentWriterFactory(gen);
   auto gwf = new DefaultGraphWriterFactory(gen);
   auto file = new FileConduit("docgen/teststuff/" ~ fname, FileConduit.WriteCreate);
   auto file2 = new FileConduit("docgen/teststuff/" ~ fname ~ "-2", FileConduit.WriteCreate);
-  auto writer = gwf.createGraphWriter( [ file2, file] );
+  auto writer = gwf.createGraphWriter( ddf.createDocumentWriter( [ file2 ] ) );
   
-  writer(vertices, edges);
+  writer.generateGraph(vertices, edges, file);
   
   file.close();
   file2.close();
@@ -107,10 +109,12 @@
   auto gen = new TestDocGenerator;
   gen.options.graph.HighlightCyclicVertices = true;
   gen.options.graph.graphFormat = GraphFormat.Dot;
+  gen.options.graph.imageFormat = ImageFormat.SVG;
   gen.options.docFormat = DocFormat.LaTeX;
   auto fname = "dependencies.tex";
   auto imgFname = "depgraph.dot";
   
+  auto ddf = new DefaultDocumentWriterFactory(gen);
   auto gwf = new DefaultGraphWriterFactory(gen);
   auto file = new FileConduit("docgen/teststuff/" ~ fname, FileConduit.WriteCreate);
   auto imgFile = new FileConduit("docgen/teststuff/" ~ imgFname, FileConduit.WriteCreate);
@@ -131,10 +135,10 @@
     },
     modules
   );
+
+  auto writer = gwf.createGraphWriter( ddf.createDocumentWriter( [ file ] ) );
   
-  auto writer = gwf.createGraphWriter( [ file, imgFile ] );
-  
-  writer(vertices.values, edges);
+  writer.generateGraph(vertices.values, edges, imgFile);
   
   file.close();
   imgFile.close();
--- a/trunk/src/docgen/tests/listing.d	Wed Oct 17 20:55:55 2007 +0200
+++ b/trunk/src/docgen/tests/listing.d	Wed Oct 24 17:25:52 2007 +0300
@@ -7,6 +7,7 @@
 import docgen.misc.parser;
 import docgen.tests.common;
 import docgen.sourcelisting.writers;
+import docgen.document.writers;
 import dil.Module;
 import tango.io.Stdout;
 import tango.io.FileConduit;
@@ -20,6 +21,7 @@
   gen.options.docFormat = DocFormat.LaTeX;
   auto fname = "files.tex";
   
+  auto ddf = new DefaultDocumentWriterFactory(gen);
   auto gwf = new DefaultListingWriterFactory(gen);
   auto file = new FileConduit("docgen/teststuff/" ~ fname, FileConduit.WriteCreate);
   
@@ -39,9 +41,9 @@
     
     auto srcFile = new FileConduit(mod.filePath);
     auto dstFile = new FileConduit("docgen/teststuff/_" ~ dstFname ~ ".d", FileConduit.WriteCreate);
-    auto writer = gwf.createListingWriter( [ file, dstFile ] );
+    auto writer = gwf.createListingWriter( ddf.createDocumentWriter( [ file ] ) );
     
-    writer.generateListing(srcFile, mod.moduleFQN);
+    writer.generateListing(srcFile, dstFile, mod.moduleFQN);
 
     srcFile.close();
     dstFile.close();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/teststuff/clean.sh	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,7 @@
+rm _*
+rm dep*
+rm doc*
+rm *.tex
+rm graph*
+rm parse*
+touch modules.tex
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/teststuff/lstlang0.sty	Wed Oct 24 17:25:52 2007 +0300
@@ -0,0 +1,21 @@
+%%
+%% D definition (c) 2007 Jari-Matti Mäkelä
+%%
+\lst@definelanguage{D}%
+  {morekeywords={abstract,alias,align,asm,assert,auto,body,bool,break,%
+      byte,case,cast,catch,cdouble,cent,cfloat,char,class,const,continue,%
+      creal,dchar,debug,default,delegate,delete,deprecated,do,double,%
+      else,enum,export,extern,false,final,finally,float,for,foreach,%
+      foreach_reverse,function,goto,idouble,if,ifloat,import,in,inout,%
+      int,interface,invariant,ireal,is,lazy,long,macro,mixin,module,new,%
+      null,out,override,package,pragma,private,protected,public,real,ref,%
+      return,scope,short,static,struct,super,switch,synchronized,template,%
+      this,throw,true,try,typedef,typeid,typeof,ubyte,ucent,uint,ulong,%
+      union,unittest,ushort,version,void,volatile,wchar,while,with},%
+   sensitive,%
+   morecomment=[s]{/*}{*/},%
+   morecomment=[n]{/+}{+/},%
+   morecomment=[l]//,%
+   morestring=[b]",%
+   morestring=[b]`%
+  }[keywords,comments,strings]%
\ No newline at end of file