From 2110693ff442fb4391e6aeb0cb24f085dc79e38c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Sun, 5 Feb 2012 22:26:47 +0100 Subject: [PATCH] Tools.AutoDoc: Added syntax and markup for documenting cpp directives. --- .../Tools.pmod/AutoDoc.pmod/DocParser.pmod | 20 +++++ .../Tools.pmod/AutoDoc.pmod/PikeObjects.pmod | 14 +++ .../Tools.pmod/AutoDoc.pmod/ProcessXML.pmod | 4 +- .../Standalone.pmod/autodoc_to_html.pike | 9 +- .../autodoc_to_split_html.pike | 87 ++++++++++++++++--- refdoc/keywords.txt | 26 ++++++ 6 files changed, 145 insertions(+), 15 deletions(-) diff --git a/lib/modules/Tools.pmod/AutoDoc.pmod/DocParser.pmod b/lib/modules/Tools.pmod/AutoDoc.pmod/DocParser.pmod index 635e5caeb6..d2d6c53071 100644 --- a/lib/modules/Tools.pmod/AutoDoc.pmod/DocParser.pmod +++ b/lib/modules/Tools.pmod/AutoDoc.pmod/DocParser.pmod @@ -61,6 +61,7 @@ mapping(string : DocTokenType) keywordtype = "namespace" : METAKEYWORD, "endnamespace" : METAKEYWORD, "decl" : METAKEYWORD, + "directive" : METAKEYWORD, "inherit" : METAKEYWORD, "enum" : METAKEYWORD, "endenum" : METAKEYWORD, @@ -966,6 +967,25 @@ protected class DocParserClass { } break; + case "directive": + { + if (endkeyword) + parseError("@%s must stand alone", endkeyword); + int first = !meta->type; + if (!meta->type) + meta->type = "decl"; + else if (meta->type != "decl") + parseError("@directive can not be combined with @%s", meta->type); + if (meta->appears) + parseError("@appears before @directive"); + if (meta->belongs) + parseError("@belongs before @directive"); + meta->type = "decl"; + string s = String.trim_all_whites(arg); + meta->decls += ({ .PikeObjects.CppDirective(s) }); + } + break; + case "appears": { if (endkeyword) diff --git a/lib/modules/Tools.pmod/AutoDoc.pmod/PikeObjects.pmod b/lib/modules/Tools.pmod/AutoDoc.pmod/PikeObjects.pmod index 4014da0816..650dcf66fb 100644 --- a/lib/modules/Tools.pmod/AutoDoc.pmod/PikeObjects.pmod +++ b/lib/modules/Tools.pmod/AutoDoc.pmod/PikeObjects.pmod @@ -601,6 +601,20 @@ class Import { } } +//! Representation of an inherit. +class CppDirective { + //! + inherit PikeObject; + + //! + constant objtype = "directive"; + + protected void create(string directive) + { + name = directive; + } +} + //! Base class for representing classes, modules and namespaces. //! //! @seealso diff --git a/lib/modules/Tools.pmod/AutoDoc.pmod/ProcessXML.pmod b/lib/modules/Tools.pmod/AutoDoc.pmod/ProcessXML.pmod index badaad7694..4a05268a92 100644 --- a/lib/modules/Tools.pmod/AutoDoc.pmod/ProcessXML.pmod +++ b/lib/modules/Tools.pmod/AutoDoc.pmod/ProcessXML.pmod @@ -68,6 +68,7 @@ protected private void processWarning(string message, mixed ... args) { // <constant/> // <typedef/> // <inherit/> +// <directive/> // <doc/> // </docgroup> // @@ -408,7 +409,7 @@ protected int isText(SimpleNode node) { return node->get_node_type() == XML_TEXT protected string renderType(SimpleNode node) { SimpleNode type_node; - if ((< "method", "variable", "constant", + if ((< "method", "variable", "constant", "directive", "typedef", "inherit", "import" >)[node->get_any_name()]) { type_node = node; } else { @@ -416,6 +417,7 @@ protected string renderType(SimpleNode node) node->get_first_element("method") || node->get_first_element("variable") || node->get_first_element("constant") || + node->get_first_element("directive") || node->get_first_element("typedef") || node->get_first_element("inherit") || node->get_first_element("import"); diff --git a/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_html.pike b/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_html.pike index 9ad00582b4..b1901bddc7 100644 --- a/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_html.pike +++ b/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_html.pike @@ -1035,6 +1035,7 @@ void resolve_class_paths(Node n, string|void path, Node|void parent) case "import": case "typedef": case "variable": + case "directive": // These don't have children. attrs->class_path = path; return; @@ -1108,7 +1109,7 @@ string render_class_path(Node n,int|void class_only) string parse_not_doc(Node n) { string ret = ""; - int method, argument, variable, const, typedf; + int method, argument, variable, const, typedf, cppdir; if (!n) return ""; @@ -1234,6 +1235,12 @@ string parse_not_doc(Node n) { case "import": break; + case "directive": + if(cppdir++) ret += "<br />\n"; + ret += "<tt><font color='#006666'>" + c->get_attributes()->name + + "</font></tt>"; + break; + default: error( "Illegal element " + c->get_any_name() + " in !doc.\n" ); break; diff --git a/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_split_html.pike b/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_split_html.pike index 3eeecb6184..c8f3adcd4f 100644 --- a/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_split_html.pike +++ b/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_split_html.pike @@ -90,6 +90,7 @@ class Node array(Node) class_children = ({ }); array(Node) module_children = ({ }); array(Node) enum_children = ({ }); + array(Node) directive_children = ({ }); array(Node) method_children = ({ }); Node parent; @@ -112,6 +113,7 @@ class Node sort(class_children->name, class_children); sort(module_children->name, module_children); sort(enum_children->name, enum_children); + sort(directive_children->name, directive_children); sort(method_children->name, method_children); method_children = check_uniq(method_children); @@ -206,6 +208,33 @@ class Node return ({ "" }); break; + case "directive": + if( m["homogen-name"] ) { + string name = m["homogen-name"]; + directive_children += + ({ Node( "directive", name, c, this_object() ) }); + return ({ "" }); + } + + // Several different directives documented with the same blurb. + array directives = ({}); + Parser.HTML dirparser = Parser.HTML(); + dirparser->case_insensitive_tag(1); + dirparser->xml_tag_syntax(3); + dirparser->add_tag("directive", + lambda(Parser.HTML p, mapping m) { + directives += ({ + Parser.parse_html_entities(m->name) + }); + } ); + dirparser->finish(c); + foreach(Array.uniq(directives) - ({ 0, "" }), string name) { + directive_children += + ({ Node( "directive", name, c, this_object() ) }); + } + return ({ "" }); + break; + case "constant": case "variable": case "inherit": @@ -262,9 +291,10 @@ class Node string make_faked_wrapper(string s) { - if(type=="method") - s = sprintf("<docgroup homogen-type='method' homogen-name='%s'>\n" + if((type == "method") || (type == "directive")) + s = sprintf("<docgroup homogen-type='%s' homogen-name='%s'>\n" "%s\n</docgroup>\n", + type, Parser.encode_html_entities(name), s); else s = sprintf("<%s name='%s'>\n%s\n</%s>\n", @@ -489,6 +519,7 @@ class Node res += make_navbar_really_low(root->namespace_children, "Namespaces"); else { res += make_navbar_really_low(root->enum_children, "Enums"); + res += make_navbar_really_low(root->directive_children, "Directives"); res += make_navbar_really_low(root->method_children, "Methods"); } @@ -497,7 +528,7 @@ class Node string make_navbar() { - if(type=="method") + if((type == "method") || (type == "directive")) return make_navbar_low(parent); else return make_navbar_low(this_object()); @@ -509,6 +540,7 @@ class Node parent->class_children+ parent->module_children+ parent->enum_children+ + parent->directive_children+ parent->method_children; } @@ -518,6 +550,7 @@ class Node class_children+ module_children+ enum_children+ + directive_children+ method_children; } @@ -585,6 +618,7 @@ class Node class_children->make_html(template, path, exporter); module_children->make_html(template, path, exporter); enum_children->make_html(template, path, exporter); + directive_children->make_html(template, path, exporter); method_children->make_html(template, path, exporter); int num_segments = sizeof(make_filename()/"/")-1; @@ -666,6 +700,7 @@ class TopNode { class_children += x->class_children; module_children += x->module_children; enum_children += x->enum_children; + directive_children += x->directive_children; method_children += x->method_children; } type = "autodoc"; @@ -684,7 +719,7 @@ class TopNode { int(0..0) find_prev_node() { return 0; } int(0..0) find_next_node() { return 0; } string make_class_path(void|int(0..1) header) { - if(header && sizeof(method_children)) { + if(header && (sizeof(method_children) + sizeof(directive_children))) { if(default_namespace) return "namespace "+default_namespace; else @@ -706,20 +741,46 @@ class TopNode { return (string)res; } + string make_directive_page(array(Node) children) + { + String.Buffer res = String.Buffer(3500); + foreach(children, Node node) + res->add(" <a href='", make_link(node), "'>", + Parser.encode_html_entities(node->name), + "</a><br />\n"); + return (string)res; + } + string make_content() { resolve_reference = my_resolve_reference; - if(!sizeof(method_children)) return ""; - - string contents = "<nav><table class='sidebar' style='width:100%;'><tr>"; - foreach(method_children/( sizeof(method_children)/4.0 ), - array(Node) children) - contents += "<td nowrap='nowrap' valign='top'>" + - make_method_page(children) + "</td>"; + if(!sizeof(method_children) && !sizeof(directive_children)) return ""; + + string contents = "<nav><table class='sidebar' style='width:100%;'>\n"; + if (sizeof(directive_children)) { + contents += "<tr>\n"; + foreach(directive_children/( sizeof(directive_children)/4.0 ), + array(Node) children) + contents += "<td nowrap='nowrap' valign='top'>" + + make_directive_page(children) + "</td>"; + contents += "</tr>\n"; + if (sizeof(method_children)) { + contents += "<tr><td colspan='4'><hr /></td></tr>\n"; + } + } + if (sizeof(method_children)) { + contents += "<tr>\n"; + foreach(method_children/( sizeof(method_children)/4.0 ), + array(Node) children) + contents += "<td nowrap='nowrap' valign='top'>" + + make_method_page(children) + "</td>"; + contents += "</tr>\n"; + } - contents += "</tr><tr><td colspan='4' nowrap='nowrap'>" + + contents += "<tr><td colspan='4' nowrap='nowrap'>" + parse_children(Parser.XML.Tree.parse_input(data), "docgroup", parse_docgroup, 1) + - "</td></tr></table></nav>"; + "</td></tr>\n" + "</table></nav>"; return contents; } diff --git a/refdoc/keywords.txt b/refdoc/keywords.txt index abc812269b..cc2355f1d6 100644 --- a/refdoc/keywords.txt +++ b/refdoc/keywords.txt @@ -112,6 +112,32 @@ Examples: _______________________________________________________________________________ +Keyword: @directive + +Description: Document a Pike cpp directive. + + The rest of the line should be the cpp directive to document. + +Arguments: [name] + Where: + [name] is a cpp directive. +Children: Documentation for the directive. +Groups with: @directive +Note: Typically only used in the cpp:: namespace. +Examples: + //! @directive #include + //! + //! The @tt{#include@} directive is used + //! to include source code from a different file. + + //! @directive #if + //! @directive #endif + //! + //! This is how to document multiple related directives + //! with one documentation string. + +_______________________________________________________________________________ + Keyword: @endclass Description: Leave the class scope entered by @class. Arguments: [name] -- GitLab