From d7044d310387d3752774831c1a8a768c0ca1ed67 Mon Sep 17 00:00:00 2001 From: deva Date: Tue, 29 Mar 2011 10:04:47 +0000 Subject: Examples in docs. --- client/docgen/doc.h | 8 +++ client/docgen/docgen.cc | 26 +++---- client/docgen/docgen.pro | 2 + client/docgen/footer.html | 2 + client/docgen/generate.cc | 81 ++++++++++++++------- client/docgen/generate.h | 3 +- client/docgen/header.html | 9 +++ client/docgen/highlight.cc | 172 +++++++++++++++++++++++++++++++++++++++++++++ client/docgen/highlight.h | 41 +++++++++++ client/docgen/parse.cc | 113 +++++++++++++++++++++++------ client/docgen/style.css | 167 +++++++++++++++++++++++++++---------------- 11 files changed, 501 insertions(+), 123 deletions(-) create mode 100644 client/docgen/footer.html create mode 100644 client/docgen/header.html create mode 100644 client/docgen/highlight.cc create mode 100644 client/docgen/highlight.h (limited to 'client/docgen') diff --git a/client/docgen/doc.h b/client/docgen/doc.h index fc400fc..5a1d5dd 100644 --- a/client/docgen/doc.h +++ b/client/docgen/doc.h @@ -31,6 +31,12 @@ #include #include +class Example { +public: + QString name; + QString code; +}; + class Parameter { public: QString name; @@ -43,6 +49,7 @@ public: QString description; QString returns; QVector parameters; + QVector examples; }; class Attribute { @@ -60,6 +67,7 @@ public: bool screenshot; bool container; QString description; + QVector examples; QVector attributes; QVector methods; }; diff --git a/client/docgen/docgen.cc b/client/docgen/docgen.cc index ee5b8f4..e4af0a3 100644 --- a/client/docgen/docgen.cc +++ b/client/docgen/docgen.cc @@ -44,20 +44,8 @@ QString output; -QString header = - "\n" - "\n" - " \n" - " Pracro Widget Documentation\n" - " \n" - " \n" - " \n" - " \n"; - -QString footer = - " \n" - "\n"; +QString header; +QString footer; void getInheritedAttributes(QMap > &atts, QMap &docs, @@ -88,7 +76,7 @@ void writeDoc(QMap &docs, QString name) QMap > meths; getInheritedMethods(meths, docs, doc.extends); - QString out = generate(doc, meths, atts); + QString out = generate(doc, meths, atts, docs); QFile::remove(output + "/" + name + ".html"); QFile ofile(output + "/" + name + ".html"); @@ -133,6 +121,14 @@ int main(int argc, char *argv[]) QMap docs; + QFile hfile("header.html"); + hfile.open(QIODevice::ReadOnly | QIODevice::Text); + header = hfile.readAll(); + + QFile ffile("footer.html"); + ffile.open(QIODevice::ReadOnly | QIODevice::Text); + footer = ffile.readAll(); + QDir d; d.mkdir(output); QFile::remove(output + "/style.css"); QFile::copy("style.css", output + "/style.css"); diff --git a/client/docgen/docgen.pro b/client/docgen/docgen.pro index d495439..79308b8 100644 --- a/client/docgen/docgen.pro +++ b/client/docgen/docgen.pro @@ -28,6 +28,7 @@ SOURCES += \ genimage.cc \ generate.cc \ parse.cc \ + highlight.cc \ ../debug.cc \ ../lua.cc \ ../luawidget.cc \ @@ -67,6 +68,7 @@ HEADERS += \ generate.h \ parse.h \ doc.h \ + highlight.h \ ../debug.h \ ../lua.h \ ../luawidget.h \ diff --git a/client/docgen/footer.html b/client/docgen/footer.html new file mode 100644 index 0000000..b605728 --- /dev/null +++ b/client/docgen/footer.html @@ -0,0 +1,2 @@ + + diff --git a/client/docgen/generate.cc b/client/docgen/generate.cc index 5cff6b7..db7d0c9 100644 --- a/client/docgen/generate.cc +++ b/client/docgen/generate.cc @@ -32,6 +32,23 @@ #include #include "genimage.h" +#include "highlight.h" + +static QString generateExamples(QVector &examples, lang_t lang) +{ + QString out; + QVector::iterator k = examples.begin(); + while(k != examples.end()) { + Example &e = *k; + out += "
\n"; + out += "
" + e.name + + "
\n"; + out += "
" + highlight(e.code, lang) + "
"; + out += "
"; + k++; + } + return out; +} static QString function(QString f) { @@ -75,12 +92,18 @@ static QString generateMethods(QVector meths) QString out; foreach(Method meth, meths) { + QString f = meth.name; + QString name = f.mid(f.indexOf(" ") + 1, + f.indexOf("(") - f.indexOf(" ") - 1); + out += "
\n"; - out += "
" + function(meth.name) + "
\n"; out += "
" + meth.description + "
\n"; - + + out += generateExamples(meth.examples, lua); + if(meth.parameters.size()) { out += "
\n"; foreach(Parameter parm, meth.parameters) { @@ -150,7 +173,10 @@ static QString generateMethodOverview(Doc &doc, out += "
    \n"; foreach(Method meth, meths) { - out += "
  • "+meth.name+" " + + QString f = meth.name; + QString name = f.mid(f.indexOf(" ") + 1, + f.indexOf("(") - f.indexOf(" ") - 1); + out += "
  • "+meth.name+" " + meth.description.left(meth.description.indexOf(".") + 1) + "
  • \n"; } out += "
\n"; @@ -158,8 +184,28 @@ static QString generateMethodOverview(Doc &doc, return out; } +static QString extendedBy(QString name, QMap &docs) +{ + QString out; + + QMap::iterator i = docs.begin(); + while(i != docs.end()) { + Doc &d = i.value(); + if(d.extends == name) { + if(out != "") out += ", "; + out += "" + d.name + ""; + } + i++; + } + + if(out != "") out = "Extended by: " + out + "."; + + return out; +} + QString generate(Doc &doc, QMap > &meths, - QMap > &atts) + QMap > &atts, + QMap &docs) { QString out; @@ -169,7 +215,8 @@ QString generate(Doc &doc, QMap > &meths, out += "
\n"; out += "

" + doc.title + "

\n"; if(doc.tag != "" ){ - out += "
<" + doc.tag + " />
\n"; + out += "
" +
+      highlight("<" + doc.tag + " />", xml) + "
\n"; } if(doc.container) { @@ -177,10 +224,12 @@ QString generate(Doc &doc, QMap > &meths, } if(doc.extends != "") { - out += " \n"; } + out += extendedBy(doc.name, docs); + if(doc.screenshot) { genImage(doc.tag); out += "
\n"; @@ -192,6 +241,8 @@ QString generate(Doc &doc, QMap > &meths, out += doc.description; out += "
\n"; + out += generateExamples(doc.examples, xml); + out += "

Attributes

\n"; out += "
\n"; if(doc.attributes.size()) { @@ -232,21 +283,3 @@ QString generate(Doc &doc, QMap > &meths, return out; } - -#ifdef TEST_GENERATE -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). -TEST_TRUE(false, "No tests yet!"); - -TEST_END; - -#endif/*TEST_GENERATE*/ diff --git a/client/docgen/generate.h b/client/docgen/generate.h index 24a3191..c706e52 100644 --- a/client/docgen/generate.h +++ b/client/docgen/generate.h @@ -34,6 +34,7 @@ #include "doc.h" QString generate(Doc &doc, QMap > &meths, - QMap > &atts); + QMap > &atts, + QMap &docs); #endif/*__PRACRO_GENERATE_H__*/ diff --git a/client/docgen/header.html b/client/docgen/header.html new file mode 100644 index 0000000..660e0c8 --- /dev/null +++ b/client/docgen/header.html @@ -0,0 +1,9 @@ + + + + Pracro Widget Documentation + + + + diff --git a/client/docgen/highlight.cc b/client/docgen/highlight.cc new file mode 100644 index 0000000..0857320 --- /dev/null +++ b/client/docgen/highlight.cc @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * highlight.cc + * + * Tue Mar 29 09:12:06 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "highlight.h" + +#include + +typedef enum { + none, + intag, + instring, + inname, + inattribute +} xml_state_t; + +static bool isChar(QChar c) +{ + return + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '_'; +} + +static QString highlight_xml(QString code) +{ + QString out; + xml_state_t state = none; + bool hasname = false; + + QString::iterator c = code.begin(); + while(c != code.end()) { + if(*c == '<') { + out += "<"; + state = intag; + hasname = false; + } else if(state == intag && *c == '>') { + out += ">"; + state = none; + } else if(state == intag && *c == '/') { + out += "/"; + + } else if(state == intag && hasname == false && isChar(*c)) { + state = inname; + hasname = true; + out += "" + QString(*c); + } else if(state == inname && isChar(*c)) { + out += *c; + } else if(state == inname) { + out += "" + QString(*c); + state = intag; + + } else if(state == intag && hasname == true && isChar(*c)) { + state = inattribute; + out += "" + QString(*c); + } else if(state == inattribute && isChar(*c)) { + out += *c; + } else if(state == inattribute) { + out += "" + QString(*c); + state = intag; + + } else if(state == intag && *c == '\"') { + state = instring; + out += """; + } else if(state == instring && *c == '\"') { + state = intag; + out += """; + } else if(state == instring) { + out += *c; + + } else out += *c; + c++; + } + + /* + QXmlStreamWriter w(&e->code); + w.writeCharacters(line + "\n"); + */ + + return out; +} + +static bool isLuaChar(QChar c) +{ + return + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '_'; +} + +static bool isKeyword(QString code) +{ + return code == "if" || + code == "then" || + code == "else" || + code == "end" || + code == "this" || + code == "function" || + code == "local" || + code == "and" || + code == "or" || + code == "not"; +} + +static QString highlight_lua(QString code) +{ + QString out; + QString word; + + bool instring = false; + + QString::iterator c = code.begin(); + while(c != code.end()) { + if(isLuaChar(*c)) { + word += *c; + } else { + if(instring && *c == '\'') { + out += word + "'"; + instring = false; + } else if(instring) { + out += word + QString(*c); + } else if(isKeyword(word)) { + out += ""+word+"" + QString(*c); + } else if(*c == '(') { + out += ""+word+"" + QString(*c); + } else if(instring == false && *c == '\'') { + out += word + "'"; + instring = true; + } else { + out += word + QString(*c); + } + word = ""; + } + + c++; + } + + return out; +} + +QString highlight(QString code, lang_t lang) +{ + switch(lang) { + case lua: + return highlight_lua(code); + case xml: + return highlight_xml(code); + } +} diff --git a/client/docgen/highlight.h b/client/docgen/highlight.h new file mode 100644 index 0000000..e099801 --- /dev/null +++ b/client/docgen/highlight.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * highlight.h + * + * Tue Mar 29 09:12:06 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __PRACRO_HIGHLIGHT_H__ +#define __PRACRO_HIGHLIGHT_H__ + +#include + +typedef enum { + xml, + lua +} lang_t; + +QString highlight(QString code, lang_t lang); + + +#endif/*__PRACRO_HIGHLIGHT_H__*/ diff --git a/client/docgen/parse.cc b/client/docgen/parse.cc index d1631c1..6303eae 100644 --- a/client/docgen/parse.cc +++ b/client/docgen/parse.cc @@ -29,16 +29,61 @@ #include #include +#include typedef enum { none, indesc, + indescex, inatt, inmeth, + inmethex, inpar, inret, } state_t; +static QString convert(QString in) +{ + QString out; + bool linkme = false; + QStringList tokens = in.split(QRegExp("\\s+")); + QStringList::iterator i = tokens.begin(); + while(i != tokens.end()) { + if(linkme) { + QString link = *i; + + if(i->right(1) == ".") link = link.left(link.length() - 1); + + if(link.indexOf("(") != -1 && link.indexOf(")") != -1 ) { + // method link + out += ""+link+""; + } else { + // tag link + out += ""+link+""; + } + + if(i->right(1) == ".") out += "."; + out += " "; + + i++; + linkme = false; + continue; + } + + if(*i == "@see") { + linkme = true; + i++; + continue; + } + + out += *i + " "; + + i++; + } + + return out; +} + Doc parse(QString filename) { Doc doc; @@ -68,13 +113,14 @@ Doc parse(QString filename) if(line.contains("*/")) running = false; if(running) { - line.remove(QRegExp("^[ \t*]*")); - // printf("line [%s]\n", line.toStdString().c_str()); + line.remove(QRegExp("^[ \t]*[*][ \t]")); if(state == indesc && line.left(1) == "@") state = none; + if(state == indescex && line.left(1) == "@") state = none; if(state == inatt && line.left(1) == "@") state = none; if(state == inpar && line.left(1) == "@") state = inmeth; if(state == inret && line.left(1) == "@") state = inmeth; + if(state == inmethex && line.left(1) == "@") state = inmeth; if(state == none && doc.title == "") { doc.title = line; @@ -83,6 +129,7 @@ Doc parse(QString filename) if(state == none && line.left(4) == "@tag") { doc.tag = line.right(line.length() - line.indexOf(" ") - 1); + doc.name = doc.tag; continue; } @@ -105,12 +152,41 @@ Doc parse(QString filename) state = indesc; } - if(state == indesc) { doc.description += line + "\n"; continue; } + if((state == none || state == indesc || state == inmeth) + && line.left(8) == "@example") { + + Example e; + e.name = line.right(line.length() - 8); + + if(state == none || state == indesc) { + doc.examples.push_back(e); + state = indescex; + } else { + Method &m = doc.methods[doc.methods.size() - 1]; + m.examples.push_back(e); + state = inmethex; + } + + continue; + } + + if(state == indescex || state == inmethex) { + Example *e; + if(state == indescex) { + e = &doc.examples[doc.examples.size() - 1]; + } else { + Method &m = doc.methods[doc.methods.size() - 1]; + e = &m.examples[m.examples.size() - 1]; + } + e->code += line + "\n"; + continue; + } + if(state == none && line.left(4) == "@att") { Attribute att; att.name = line.mid(5, line.indexOf(" ", 5) - 5); @@ -176,23 +252,18 @@ Doc parse(QString filename) if(line == "/***") running = true; } + // Convert all @see to links + doc.description = convert(doc.description); + QVector::iterator i = doc.attributes.begin(); + while(i != doc.attributes.end()) { + i->description = convert(i->description); + i++; + } + QVector::iterator j = doc.methods.begin(); + while(j != doc.methods.end()) { + j->description = convert(j->description); + j++; + } + return doc; } - -#ifdef TEST_PARSE -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). -TEST_TRUE(false, "No tests yet!"); - -TEST_END; - -#endif/*TEST_PARSE*/ diff --git a/client/docgen/style.css b/client/docgen/style.css index 9ef9a68..c13b0e5 100644 --- a/client/docgen/style.css +++ b/client/docgen/style.css @@ -1,18 +1,18 @@ body { - font-family: Verdana; - font-size: 12px; + font-family: Verdana; + font-size: 12px; } a { - color: #5c7b8b; + color: #5c7b8b; } a:visited { - color: #465d69; + color: #465d69; } a:hover { - color: #000; + color: #000; } .doc { @@ -20,102 +20,145 @@ a:hover { } .doc .title { - font-weight: bold; - font-size: 1.5em; - text-align: center; + font-weight: bold; + font-size: 1.5em; + text-align: center; } .doc .tagname { - text-align: center; - font-family: courier; + text-align: center; } - .doc .extends {} .doc .container {} .doc .screenshot { - text-align: center; + text-align: center; } .doc .description { - padding-top: 4px; - padding-bottom: 4px; + padding-top: 4px; + padding-bottom: 4px; +} + +.example { + border: solid #DEDEEE 1px; + margin-top: 4px; + margin-bottom: 4px; + border-radius: 8px 8px 8px 8px; +} +.example .header { + background-color: #D5E1E8; + border-radius: 8px 8px 0px 0px; + border: solid #84B0C7 1px; + padding: 4px; + margin: -1px; +} +.example .header .name { + border: 0px; + background-color: transparent; + padding: 0px; + border-radius: 0px; +} +.example .code { + padding-left: 4px; } .attributes {} .attribute {} .attribute .name { - font-weight: normal; - font-style: italic; - border: 0px; - border-radius: 0px 0px 0px 0px; - background-color: transparent; - display: inline; - color: green; - font-family: courier; - padding-right: 4px; - padding-left: 4px; - font-size: 1.2em; + font-weight: normal; + font-style: italic; + border: 0px; + border-radius: 0px 0px 0px 0px; + background-color: transparent; + display: inline; + color: green; + font-family: courier; + padding-right: 4px; + padding-left: 4px; + font-size: 1.2em; } .attribute .name:before { - content:"- "; + content:"- "; } .attribute .description { - display: inline; + display: inline; } .attributes, .parameters { - margin-top: 8px; - border-top: solid #DEDEEE 1px; - padding-top: 8px; + margin-top: 8px; + border-top: solid #DEDEEE 1px; + padding-top: 8px; - margin-bottom: 8px; - border-bottom: solid #DEDEEE 1px; - padding-bottom: 8px; + margin-bottom: 8px; + border-bottom: solid #DEDEEE 1px; + padding-bottom: 8px; } .method { - background-color: #EEF3F5; - border: solid #DEDEEE 1px; - padding: 4px; - border-radius: 8px 8px 8px 8px; - margin-bottom: 8px; + background-color: #EEF3F5; + border: solid #DEDEEE 1px; + padding: 4px; + border-radius: 8px 8px 8px 8px; + margin-bottom: 8px; } - .method .name { - background-color: #D5E1E8; - width: *; - border: solid #84B0C7 1px; - padding: 4px; - border-radius: 8px 8px 8px 8px; + background-color: #D5E1E8; + width: *; + border: solid #84B0C7 1px; + padding: 4px; + border-radius: 8px 8px 8px 8px; } - - .method .description {} .method .returns {} +.method .luamethod { + font-weight: bold; +} +.method .luatype { + font-style: italic; + color: blue; +} +.method .luaparms { + font-style: italic; + color: green; +} .parameter {} .parameter .name { - font-weight: normal; - font-style: italic; - border: 0px; - border-radius: 0px 0px 0px 0px; - background-color: transparent; - display: inline; + font-weight: normal; + font-style: italic; + border: 0px; + border-radius: 0px 0px 0px 0px; + background-color: transparent; + display: inline; } .parameter .description { - display: inline; + display: inline; } -.method .luamethod { - font-weight: bold; +.code .tag { + color: #0000FF; +} +.code .attribute { + color: #B8840A; +} +.code .string { + color: #BC8F8F; +} +.code .characters { + color: #000000; +} +.code .brackets { + color: #000000; } -.method .luatype { - font-style: italic; - color: blue; +.code .keyword { + color: #9D20F0; +} +.code .function { + color: #0000FF; +} +.code .identifier { + color: #000000; } -.method .luaparms { - font-style: italic; - color: green; -} \ No newline at end of file + -- cgit v1.2.3