Mercurial > projects > dil
changeset 455:f92505ad18ab
Simple configuration reader, small modifications.
author | Jari-Matti M?kel? <jmjm@iki.fi> |
---|---|
date | Mon, 29 Oct 2007 21:27:02 +0200 |
parents | dbdc9fa5d479 |
children | de2675bc9afa |
files | trunk/src/docgen/config/configurator.d trunk/src/docgen/config/default.cfg trunk/src/docgen/config/reader.d trunk/src/docgen/docgen.d trunk/src/docgen/document/latexwriter.d trunk/src/docgen/misc/misc.d trunk/src/docgen/tests/common.d trunk/src/docgen/tests/doctemplate.d |
diffstat | 8 files changed, 418 insertions(+), 108 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/config/configurator.d Mon Oct 29 21:27:02 2007 +0200 @@ -0,0 +1,148 @@ +module docgen.config.configurator; + +import docgen.config.reader; +import docgen.misc.misc; + +import Integer = tango.text.convert.Integer; +import tango.io.stream.FileStream; + +interface Configurator { + void mergeConfiguration(char[] cfgFile); + + DocGeneratorOptions *getConfiguration(); +} + +// ugly piece of crap begins. + +char[] _wrong(char[] key) { + return `if (val.length != 1) throw new Exception( + "Wrong number of arguments for `~key~`");`; +} + +char[] _switch(char[] stuff) { + return "switch(key) {" ~ stuff ~ "}"; +} + +char[] _parseI(char[] key) { + return `case "` ~ key ~ `":` ~ _wrong(key) ~ key ~ + "= Integer.parse(val[0]); continue;"; +} + +char[] _parseS(char[] key) { + return `case "` ~ key ~ `":` ~ _wrong(key) ~ key ~ + "= val[0]; continue;"; +} + +char[] _parseB(char[] key) { + return `case "` ~ key ~ `":` ~ _wrong(key) ~ key ~ + `= val[0] == "true" ? true : val[0] == "false" ? false : err(); continue;`; +} + +char[] _parseList(char[] key) { + return `case "` ~ key ~ `":foreach(v; val) ` ~ + key ~ `~= v; continue;`; +} + +template _parseEnum_(bool list, char[] key, V...) { + static if (V.length>1) + const char[] _parseEnum_ = + `case "` ~ V[0] ~ `":` ~ key ~ (list ? "~" : "") ~ `=` ~ V[1] ~ `; continue;` \n ~ + _parseEnum_!(list, key, V[2..$]); + else + const char[] _parseEnum_ = ""; +} + +template _parseEnum(char[] key, V...) { + const char[] _parseEnum = `case "` ~ key ~ + `":` ~ _wrong(key) ~ `switch(val[0]) {` ~ + _parseEnum_!(false, key, V) ~ + `default: err(); }`; +} + +template _parseEnumList(char[] key, V...) { + const char[] _parseEnumList = `case "` ~ key ~ + `":` ~ _wrong(key) ~ `switch(val[0]) {` ~ + _parseEnum_!(true, key, V) ~ + `default: err(); }`; +} + +class DefaultConfigurator : Configurator { + DocGeneratorOptions options; + + const defaultProfileLocation = "docgen/config/default.cfg"; + + this() { + mergeConfiguration(defaultProfileLocation); + } + + this(char[] cfgFile) { + this(); + mergeConfiguration(cfgFile); + } + + void mergeConfiguration(char[] cfgFile) { + + auto inputStream = new FileInput(cfgFile); + auto content = new char[inputStream.length]; + auto bytesRead = inputStream.read (content); + + assert(bytesRead == inputStream.length, "Error reading configuration file"); + + auto tokens = lex(content); + auto configuration = parse(tokens); + + foreach(key, val; configuration) { + bool err() { + throw new Exception( + "Configurator: Invalid key-val pair " ~ key ~ + "=" ~ (val.length ? val[0] : "null")); + } + + mixin(_switch( + _parseEnum!("options.graph.imageFormat", + "PDF", "ImageFormat.PDF", + "SVG", "ImageFormat.SVG", + "PNG", "ImageFormat.PNG", + "GIF", "ImageFormat.GIF" + ) ~ + _parseI("options.graph.depth") ~ + _parseS("options.graph.nodeColor") ~ + _parseS("options.graph.cyclicNodeColor") ~ + _parseS("options.graph.unlocatableNodeColor") ~ + _parseS("options.graph.clusterColor") ~ + _parseB("options.graph.includeUnlocatableModules") ~ + _parseB("options.graph.highlightCyclicEdges") ~ + _parseB("options.graph.highlightCyclicVertices") ~ + _parseB("options.graph.groupByPackageNames") ~ + _parseB("options.graph.groupByFullPackageName") ~ + _parseB("options.listing.literateStyle") ~ + _parseB("options.listing.enableListings") ~ + _parseS("options.templates.title") ~ + _parseS("options.templates.versionString") ~ + _parseS("options.templates.copyright") ~ + _parseS("options.templates.paperSize") ~ + _parseB("options.templates.shortFileNames") ~ + _parseS("options.templates.templateStyle") ~ + _parseList("options.parser.importPaths") ~ + _parseList("options.parser.rootPaths") ~ + _parseList("options.parser.strRegexps") ~ + _parseEnum!("options.parser.commentFormat", + "Doxygen", "CommentFormat.Doxygen", + "Ddoc", "CommentFormat.Ddoc" + ) ~ + _parseEnumList!("options.outputFormats", + "LaTeX", "DocFormat.LaTeX", + "HTML", "DocFormat.HTML", + "XML", "DocFormat.XML", + "PlainText", "DocFormat.PlainText" + ) ~ + _parseS("options.outputDir") ~ + `default: throw new Exception("Illegal configuration key " ~ key);` + )); + } + } + + DocGeneratorOptions *getConfiguration() { + return &options; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/config/default.cfg Mon Oct 29 21:27:02 2007 +0200 @@ -0,0 +1,35 @@ +(options + (graph + (imageFormat PDF) + (depth -1) + (nodeColor tomato) + (cyclicNodeColor red) + (unlocatableNodeColor gray) + (clusterColor blue) + (includeUnlocatableModules false) + (highlightCyclicEdges true) + (highlightCyclicVertices true) + (groupByPackageNames true) + (groupByFullPackageName false) + ) + (listing + (literateStyle true) + (enableListings true) + ) + (templates + (title "Test project") + (versionString 1.0) + (copyright "(C) Me!") + (paperSize a4paper) + (shortFileNames false) + (templateStyle default) + ) + (parser + (importPaths) + (rootPaths) + (strRegexps) + (commentFormat Doxygen) + ) + (outputFormats LaTeX) + (outputDir tmp/) +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/config/reader.d Mon Oct 29 21:27:02 2007 +0200 @@ -0,0 +1,130 @@ +module docgen.config.reader; + +debug import tango.io.Stdout; + +char[][] lex(char[] input) { + char[][] tokens; + + uint state = 0, level = 0; + size_t sidx = 0; + + void err(size_t i, int type = 0) { + auto b = input[i<20 ? 0 : i-20..i]; + auto e = input[i+1..i+21>$ ? $ : i+21]; + + throw new Exception("Lex: " ~ + (type == 0 ? "Illegal character" : + type == 1 ? "Wrong number of parenthesis" : + "Unexpected end of input") ~ + ": " ~ b ~ " >>>" ~ input[i] ~ "<<< " ~ e ~ "." + ); + } + void begin(size_t i) { sidx = i; } + void end(size_t i) { tokens ~= input[sidx..i]; } + + foreach(size_t i, c; input) { + if (sidx > i) continue; + switch(c) { // states space, token, textEnd + case '"': + switch(state) { + case 0: + char[] buf; + bool escape; + char d; + sidx = i; + while(!((d = input[++sidx]) == '"' && !escape) && sidx<input.length) + if (escape) { + if (d != '"' && d != '\\') buf ~= '\\'; + buf ~= d; + escape = false; + } else if (d == '\\') + escape = true; + else + buf ~= d; + + sidx++; + tokens ~= buf; + state = 2; + continue; + default: err(i); + } + case '\\': + switch(state) { + case 0: begin(i); state = 1; continue; + case 1: continue; + case 2: err(i); + } + case ' ': + case '\t': + case '\n': + case '(': + case ')': + switch(state) { + case 1: end(i); + case 0: + case 2: + switch(c) { + case '(': tokens ~= "("; level++; state = 0; break; + case ')': tokens ~= ")"; if (!level--) err(i,1); + default: state = 0; + } + } + break; + default: + switch(state) { + case 0: begin(i); + case 1: state = 1; continue; + case 2: err(i); + } + } + } + + if (state == 3 || level != 0) err(input.length-1,2); + if (state > 0) end(input.length); + + debug { + foreach(i, tok; tokens) + Stdout.format("{}{}", tok, (i != tokens.length-1 ? " " : "")); + Stdout.newline; + } + + return tokens; +} + +char[][][char[]] parse(char[][] tokens) { + char[][][char[]] values; + size_t i = 1; + + void err(size_t j) { + auto b = tokens[j < 5 ? 0 : j-5..j]; + auto e = tokens[j+1..j+6>$ ? $ : j+6]; + char[] tmp; + foreach(t; b) tmp ~= t ~ " "; + tmp ~= ">>>" ~ tokens[j] ~ "<<< "; + foreach(t; e) tmp ~= t ~ " "; + + throw new Exception( + "Parse: Illegal token: " ~ tmp ~ "." + ); + } + + if (tokens[0] != "(") err(0); + + void doParse(char[] prefix = null) { + if (tokens[i] == "(" || + tokens[i] == ")") err(i); + if (prefix) prefix ~= "."; + auto v = prefix ~ tokens[i++]; + //values[v] = null; + while (tokens[i] != ")") + if (tokens[i++] == "(") + doParse(v); + else + values[v] ~= tokens[i-1]; + i++; + } + + doParse(); + + return values; +}
--- a/trunk/src/docgen/docgen.d Fri Oct 26 01:04:09 2007 +0200 +++ b/trunk/src/docgen/docgen.d Mon Oct 29 21:27:02 2007 +0200 @@ -9,87 +9,92 @@ import docgen.graphutils.writers; import docgen.misc.misc; import docgen.misc.parser; +import docgen.config.configurator; import tango.core.Array; import tango.io.stream.FileStream; import tango.text.Ascii; import tango.text.Util : replace; +import tango.io.FilePath; debug import tango.io.Stdout; -abstract class DefaultDocGenerator : DocGenerator { - DocGeneratorOptions m_options; - DocumentWriter docWriter; - GraphWriterFactory graphFactory; - - Module[] modules; - Edge[] edges; - Vertex[char[]] vertices; +template DefaultDocGenerator(char[] genDir) { + abstract class DefaultDocGenerator : DocGenerator { + DocGeneratorOptions m_options; + DocumentWriter docWriter; + GraphWriterFactory graphFactory; + + Module[] modules; + Edge[] edges; + Vertex[char[]] vertices; - this(DocGeneratorOptions options) { - m_options = options; - parseSources(); - graphFactory = new DefaultGraphWriterFactory(this); - } + this(DocGeneratorOptions options) { + m_options = options; + graphFactory = new DefaultGraphWriterFactory(this); + + // create output dir + (new FilePath(options.outputDir ~ "/" ~ genDir)).create(); + } - // TODO: constructor for situations where parsing has happened elsewhere + // TODO: constructor for situations where parsing has happened elsewhere - char[] outPath(char[] file) { - return options.outputDir ~ "/" ~ file; - } + char[] outPath(char[] file) { + return options.outputDir ~ "/" ~ genDir ~ "/" ~ file; + } - void parseSources() { - int id = 1; + void parseSources() { + int id = 1; - Parser.loadModules( - options.parser.rootPaths, - options.parser.importPaths, - options.parser.strRegexps, - options.graph.includeUnlocatableModules, - options.graph.depth, - (char[] fqn, char[] path, Module m) { - if (m is null) { - if (fqn in vertices) { - debug Stdout.format("{} already set.\n", fqn); - return; + Parser.loadModules( + options.parser.rootPaths, + options.parser.importPaths, + options.parser.strRegexps, + options.graph.includeUnlocatableModules, + options.graph.depth, + (char[] fqn, char[] path, Module m) { + if (m is null) { + if (fqn in vertices) { + debug Stdout.format("{} already set.\n", fqn); + return; - } - auto vertex = new Vertex(fqn, path, id++); - vertex.type = VertexType.UnlocatableModule; - vertices[fqn] = vertex; - debug Stdout.format("Setting {} = {}.\n", fqn, path); + } + auto vertex = new Vertex(fqn, path, id++); + vertex.type = VertexType.UnlocatableModule; + vertices[fqn] = vertex; + debug Stdout.format("Setting {} = {}.\n", fqn, path); - } else { - vertices[m.moduleFQN] = new Vertex(m.moduleFQN, m.filePath, id++); - debug Stdout.format("Setting {} = {}.\n", m.moduleFQN, m.filePath); - } - }, - (Module imported, Module importer) { - debug Stdout.format("Connecting {} - {}.\n", imported.moduleFQN, importer.moduleFQN); - edges ~= vertices[imported.moduleFQN].addChild(vertices[importer.moduleFQN]); - }, - modules - ); - } + } else { + vertices[m.moduleFQN] = new Vertex(m.moduleFQN, m.filePath, id++); + debug Stdout.format("Setting {} = {}.\n", m.moduleFQN, m.filePath); + } + }, + (Module imported, Module importer) { + debug Stdout.format("Connecting {} - {}.\n", imported.moduleFQN, importer.moduleFQN); + edges ~= vertices[imported.moduleFQN].addChild(vertices[importer.moduleFQN]); + }, + modules + ); + } - void createDepGraph(char[] depGraphFile) { - auto imgFile = new FileOutput(outPath(depGraphFile)); + void createDepGraph(char[] depGraphFile) { + auto imgFile = new FileOutput(outPath(depGraphFile)); - auto writer = graphFactory.createGraphWriter( docWriter, GraphFormat.Dot ); + auto writer = graphFactory.createGraphWriter( docWriter, GraphFormat.Dot ); - writer.generateDepGraph(vertices.values, edges, imgFile); + writer.generateDepGraph(vertices.values, edges, imgFile); - imgFile.close(); - } + imgFile.close(); + } - public DocGeneratorOptions *options() { - return &m_options; - } + public DocGeneratorOptions *options() { + return &m_options; + } } - +} /** * Main routine for LaTeX doc generation. */ -class LaTeXDocGenerator : DefaultDocGenerator { +class LaTeXDocGenerator : DefaultDocGenerator!("latex") { this(DocGeneratorOptions options) { super(options); } @@ -190,13 +195,15 @@ auto docFileName = "document.tex"; auto depGraphTexFile = "dependencies.tex"; auto depGraphFile = "depgraph.dot"; - auto listingsFile = "files.tex"; + auto listingFile = "files.tex"; auto modulesFile = "modules.tex"; + parseSources(); + generateDoc(docFileName); - if (options.listings.enableListings) - generateListings(listingsFile); + if (options.listing.enableListings) + generateListings(listingFile); generateModules(modulesFile); @@ -208,40 +215,14 @@ } void main(char[][] args) { - DocGeneratorOptions options; - - options.graph.imageFormat = ImageFormat.PDF; - options.graph.depth = -1; - options.graph.nodeColor = "tomato"; - options.graph.cyclicNodeColor = "red"; - options.graph.unlocatableNodeColor = "gray"; - options.graph.clusterColor = "blue"; - options.graph.includeUnlocatableModules = false; - options.graph.highlightCyclicEdges = true; - options.graph.highlightCyclicVertices = true; - options.graph.groupByPackageNames = true; - options.graph.groupByFullPackageName = false; - - options.listings.literateStyle = true; - options.listings.enableListings = true; + Configurator config = new DefaultConfigurator(); - options.templates.title = "Test project"; - options.templates.versionString = "1.0"; - options.templates.copyright = "(C) Me!"; - options.templates.paperSize = "a4paper"; - options.templates.shortFileNames = false; - options.templates.templateStyle = "default"; - - options.parser.importPaths = [ args[2] ]; + auto options = config.getConfiguration(); options.parser.rootPaths = [ args[1] ]; - options.parser.strRegexps = null; + options.parser.importPaths = [ args[2] ]; + options.outputDir = args[3]; - options.outputFormats = [ DocFormat.LaTeX ]; - options.parser.commentFormat = CommentFormat.Doxygen; - options.outputDir = args[3]; - - - auto generator = new LaTeXDocGenerator(options); + auto generator = new LaTeXDocGenerator(*options); generator.generate(); }
--- a/trunk/src/docgen/document/latexwriter.d Fri Oct 26 01:04:09 2007 +0200 +++ b/trunk/src/docgen/document/latexwriter.d Mon Oct 29 21:27:02 2007 +0200 @@ -27,7 +27,7 @@ factory.options.templates.versionString, docgen_version, timeNow(), - factory.options.listings.literateStyle ? "" : "%" + factory.options.listing.literateStyle ? "" : "%" ); } }
--- a/trunk/src/docgen/misc/misc.d Fri Oct 26 01:04:09 2007 +0200 +++ b/trunk/src/docgen/misc/misc.d Mon Oct 29 21:27:02 2007 +0200 @@ -45,39 +45,50 @@ } struct GraphOptions { + /// image format to use for graphs ImageFormat imageFormat; + /// maximum depth of dependencies in graphs uint depth; - char[] nodeColor = "tomato"; - char[] cyclicNodeColor = "red"; - char[] unlocatableNodeColor = "gray"; - char[] clusterColor = "blue"; + /// color of normal modules + char[] nodeColor; + /// color of the modules in cyclic dep relation + char[] cyclicNodeColor; + /// unlocatable module color + char[] unlocatableNodeColor; + /// package color + char[] clusterColor; + /// include unlocatable modules to the dep graph bool includeUnlocatableModules; + /// highlight imports in cyclic dep relation bool highlightCyclicEdges; + /// highlight modules in cyclic dep relation bool highlightCyclicVertices; + /// group modules by package names in dep graph bool groupByPackageNames; + /// group modules hierarchically or by full package name bool groupByFullPackageName; } struct ListingOptions { /// use literate programming symbols [LaTeX] - bool literateStyle = true; + bool literateStyle; /// enable source code listings bool enableListings; } struct TemplateOptions { /// project title - char[] title = "Test project"; + char[] title; /// project version - char[] versionString = "1.0"; + char[] versionString; /// copyright notice char[] copyright; /// paper size [LaTeX] - char[] paperSize = "a4paper"; + char[] paperSize; /// use short file names [HTML] bool shortFileNames; /// page template style to use, customizable via docgen/templates - char[] templateStyle = "default"; + char[] templateStyle; } struct ParserOptions { @@ -95,10 +106,11 @@ /// location for the generated output char[] outputDir; + /// list of document formats to be generated DocFormat[] outputFormats; GraphOptions graph; - ListingOptions listings; + ListingOptions listing; TemplateOptions templates; ParserOptions parser; }
--- a/trunk/src/docgen/tests/common.d Fri Oct 26 01:04:09 2007 +0200 +++ b/trunk/src/docgen/tests/common.d Mon Oct 29 21:27:02 2007 +0200 @@ -5,15 +5,20 @@ module docgen.tests.common; import docgen.misc.misc; +import docgen.config.configurator; class TestDocGenerator : DocGenerator { - DocGeneratorOptions m_options; - + Configurator config; + + this() { + config = new DefaultConfigurator(); + } + public void generate() { } public DocGeneratorOptions *options() { - return &m_options; + return config.getConfiguration(); } -} \ No newline at end of file +}
--- a/trunk/src/docgen/tests/doctemplate.d Fri Oct 26 01:04:09 2007 +0200 +++ b/trunk/src/docgen/tests/doctemplate.d Mon Oct 29 21:27:02 2007 +0200 @@ -12,7 +12,6 @@ //@unittest void doctemplate1() { auto gen = new TestDocGenerator; - gen.options.outputFormats = [ DocFormat.LaTeX ]; auto fname = "doctemplate.tex"; auto gwf = new DefaultDocumentWriterFactory(gen);