From ba848363081c44c9aa9e91b193054983f562e90c Mon Sep 17 00:00:00 2001 From: albert-github Date: Sun, 21 Aug 2016 14:17:20 +0200 Subject: Introducing commands includedoc and snippetdoc Purpose to have the possibility to have repeating texts not repeated in the comments. The commands include and snippet introduce code blocks whilst the commands includedoc and snippetdoc inclode the text as is and it will be parsed by doxygen. --- doc/commands.doc | 44 ++++++++++++++++++++++++++++++++++++++++---- src/cmdmapper.cpp | 2 ++ src/cmdmapper.h | 4 +++- src/docparser.cpp | 50 +++++++++++++++++++++++++++++++++++++++----------- src/docparser.h | 2 +- src/util.cpp | 24 ++++++++++++++++++++++++ src/util.h | 1 + 7 files changed, 110 insertions(+), 17 deletions(-) diff --git a/doc/commands.doc b/doc/commands.doc index dbc7504..d9d38e8 100644 --- a/doc/commands.doc +++ b/doc/commands.doc @@ -115,6 +115,7 @@ documentation: \refitem cmdimage \\image \refitem cmdimplements \\implements \refitem cmdinclude \\include +\refitem cmdincludedoc \\includedoc \refitem cmdincludelineno \\includelineno \refitem cmdingroup \\ingroup \refitem cmdinternal \\internal @@ -177,6 +178,7 @@ documentation: \refitem cmdskip \\skip \refitem cmdskipline \\skipline \refitem cmdsnippet \\snippet +\refitem cmdsnippetdoc \\snippetdoc \refitem cmdstartuml \\startuml \refitem cmdstruct \\struct \refitem cmdsubpage \\subpage @@ -2171,8 +2173,8 @@ Commands for displaying examples \note Doxygen's special commands do not work inside blocks of code. It is allowed to nest C-style comments inside a code block though. - \sa sections \ref cmdexample "\\example", \ref cmddontinclude "\\dontinclude", and - \ref cmdverbatim "\\verbatim". + \sa sections \ref cmdexample "\\example", \ref cmddontinclude "\\dontinclude", + \ref cmdverbatim "\\verbatim" and \ref cmdincludedoc "\\includedoc".
\section cmdincludelineno \\includelineno @@ -2184,6 +2186,22 @@ Commands for displaying examples \sa section \ref cmdinclude "\\include".
+\section cmdincludedoc \\includedoc + + \addindex \\includedoc + This command works the same way as \ref cmdinclude "\\include", but it will include + the content of the file as if it were at the place where this command is called. + The result is that the content is parsed by doxygen and placed in the documentation. + + \note Some commands like \ref cmdcond "\\cond" and \ref cmdif "\\if" don't work with + this command due to the moment of parsing. + + \note The included documentation should not have comment signs in it as the will appear + in the documentation as well. + + \sa section \ref cmdinclude "\\include". + +
\section cmdline \\line ( pattern ) \addindex \\line @@ -2285,6 +2303,23 @@ Commands for displaying examples see section \ref cmddontinclude "\\dontinclude" for an alternative way to include fragments of a source file that does not require markers. + \sa section \ref cmdsnippetdoc "\\snippetdoc". +
+\section cmdsnippetdoc \\snippetdoc ( block_id ) + + \addindex \\snippetdoc + This command works the same way as \ref cmdsnippet "\\snippet", but it will include + the content of the file between the `block-id`s as if it were at the place where this command is called. + The result is that the content is parsed by doxygen and placed in the documentation. + + \note Some commands like \ref cmdcond "\\cond" and \ref cmdif "\\if" don't work with + this command due to the moment of parsing. + + \note The included documentation should not have comment signs in it as the will appear + in the documentation as well. + + \sa section \ref cmdsnippet "\\snippet" and \ref cmdincludedoc "\\includedoc". +
\section cmduntil \\until ( pattern ) @@ -3177,8 +3212,9 @@ class Receiver \c \\verbatim command or the parser will get confused! \sa sections \ref cmdcode "\\code", - \ref cmdendverbatim "\\endverbatim", and - \ref cmdverbinclude "\\verbinclude". + \ref cmdendverbatim "\\endverbatim", + \ref cmdverbinclude "\\verbinclude", and + \ref cmdverbincludedooc "\\verbincludedooc".
\section cmdxmlonly \\xmlonly diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp index 6784b3e..5ed25cc 100644 --- a/src/cmdmapper.cpp +++ b/src/cmdmapper.cpp @@ -88,6 +88,7 @@ CommandMap cmdMap[] = { "secreflist", CMD_SECREFLIST }, { "section", CMD_SECTION }, { "snippet", CMD_SNIPPET }, + { "snippetdoc", CMD_SNIPPETDOC }, { "subpage", CMD_SUBPAGE }, { "subsection", CMD_SUBSECTION }, { "subsubsection", CMD_SUBSUBSECTION }, @@ -130,6 +131,7 @@ CommandMap cmdMap[] = { "manonly", CMD_MANONLY }, { "endmanonly", CMD_ENDMANONLY }, { "includelineno", CMD_INCWITHLINES }, + { "includedoc", CMD_INCLUDEDOC }, { "inheritdoc", CMD_INHERITDOC }, { "mscfile", CMD_MSCFILE }, { "rtfonly", CMD_RTFONLY }, diff --git a/src/cmdmapper.h b/src/cmdmapper.h index 92c906a..8800c38 100644 --- a/src/cmdmapper.h +++ b/src/cmdmapper.h @@ -133,7 +133,9 @@ enum CommandType CMD_SETSCOPE = 103, CMD_PUNT = 104, CMD_PLUS = 105, - CMD_MINUS = 106 + CMD_MINUS = 106, + CMD_INCLUDEDOC = 107, + CMD_SNIPPETDOC = 108 }; enum HtmlTagType diff --git a/src/docparser.cpp b/src/docparser.cpp index f06f6cd..afeb35f 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -123,6 +123,7 @@ struct DocParserContext QStack initialStyleStack; QList copyStack; QCString fileName; + int lineNo; QCString relPath; bool hasParamCommand; @@ -144,7 +145,6 @@ struct DocParserContext static QStack g_parserStack; //--------------------------------------------------------------------------- - static void docParserPushContext(bool saveParamInfo=TRUE) { //QCString indent; @@ -163,6 +163,7 @@ static void docParserPushContext(bool saveParamInfo=TRUE) ctx->initialStyleStack = g_initialStyleStack; ctx->copyStack = g_copyStack; ctx->fileName = g_fileName; + ctx->lineNo = doctokenizerYYlineno; ctx->relPath = g_relPath; if (saveParamInfo) @@ -201,6 +202,7 @@ static void docParserPopContext(bool keepParamInfo=FALSE) g_initialStyleStack = ctx->initialStyleStack; g_copyStack = ctx->copyStack; g_fileName = ctx->fileName; + doctokenizerYYlineno = ctx->lineNo; g_relPath = ctx->relPath; if (!keepParamInfo) @@ -5140,7 +5142,6 @@ endref: doctokenizerYYsetStatePara(); } - void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) { DBG(("handleInclude(%s)\n",qPrint(cmdName))); @@ -5168,7 +5169,7 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) } QCString fileName = g_token->name; QCString blockId; - if (t==DocInclude::Snippet) + if (t==DocInclude::Snippet || t==DocInclude::SnippetDoc) { if (fileName == "this") fileName=g_fileName; doctokenizerYYsetStateSnippet(); @@ -5182,9 +5183,31 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) } blockId = "["+g_token->name+"]"; } - DocInclude *inc = new DocInclude(this,fileName,g_context,t,g_isExample,g_exampleName,blockId); - m_children.append(inc); - inc->parse(); + + // This is the only place to handle the \includedoc and \snippetdoc commands, + // as the content is included here as if it is really here. + if (t==DocInclude::IncludeDoc || t==DocInclude::SnippetDoc) + { + QCString inc_text; + int inc_line = 1; + readTextFileByName(fileName,inc_text); + if (t==DocInclude::SnippetDoc) + { + inc_line = lineBlock(inc_text, blockId); + inc_text = extractBlock(inc_text, blockId); + } + docParserPushContext(); + g_fileName = fileName; + doctokenizerYYlineno=inc_line; + internalValidatingParseDoc(this,m_children,inc_text); + docParserPopContext(); + } + else + { + DocInclude *inc = new DocInclude(this,fileName,g_context,t,g_isExample,g_exampleName,blockId); + m_children.append(inc); + inc->parse(); + } } void DocPara::handleSection(const QCString &cmdName) @@ -5419,15 +5442,15 @@ int DocPara::handleCommand(const QCString &cmdName) break; case CMD_LI: { - DocSimpleList *sl=new DocSimpleList(this); - m_children.append(sl); + DocSimpleList *sl=new DocSimpleList(this); + m_children.append(sl); retval = sl->parse(); } break; case CMD_SECTION: { handleSection(cmdName); - retval = RetVal_Section; + retval = RetVal_Section; } break; case CMD_SUBSECTION: @@ -5673,6 +5696,12 @@ int DocPara::handleCommand(const QCString &cmdName) case CMD_SNIPPET: handleInclude(cmdName,DocInclude::Snippet); break; + case CMD_INCLUDEDOC: + handleInclude(cmdName,DocInclude::IncludeDoc); + break; + case CMD_SNIPPETDOC: + handleInclude(cmdName,DocInclude::SnippetDoc); + break; case CMD_SKIP: handleIncludeOperator(cmdName,DocIncOperator::Skip); break; @@ -6160,8 +6189,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta case XML_INHERITDOC: handleInheritDoc(); break; - - default: + default: // we should not get here! ASSERT(0); break; diff --git a/src/docparser.h b/src/docparser.h index e2751d8..1fe5e95 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -483,7 +483,7 @@ class DocVerbatim : public DocNode class DocInclude : public DocNode { public: - enum Type { Include, DontInclude, VerbInclude, HtmlInclude, LatexInclude, IncWithLines, Snippet }; + enum Type { Include, DontInclude, VerbInclude, HtmlInclude, LatexInclude, IncWithLines, Snippet , IncludeDoc, SnippetDoc}; DocInclude(DocNode *parent,const QCString &file, const QCString context, Type t, bool isExample,const QCString exampleFile, diff --git a/src/util.cpp b/src/util.cpp index 543291c..efd3d3c 100755 --- a/src/util.cpp +++ b/src/util.cpp @@ -8085,6 +8085,7 @@ bool copyFile(const QCString &src,const QCString &dest) /** Returns the section of text, in between a pair of markers. * Full lines are returned, excluding the lines on which the markers appear. + * \sa routine lineBlock */ QCString extractBlock(const QCString text,const QCString marker) { @@ -8128,6 +8129,29 @@ QCString extractBlock(const QCString text,const QCString marker) return l2>l1 ? text.mid(l1,l2-l1) : QCString(); } +/** Returns the line number of the line following the line with the marker. + * \sa routine extractBlock + */ +int lineBlock(const QCString text,const QCString marker) +{ + int result = 1; + int p=0,i; + bool found=FALSE; + + // find the character positions of the first marker + int m1 = text.find(marker); + if (m1==-1) return result; + + // find start line positions for the markers + while (!found && (i=text.find('\n',p))!=-1) + { + found = (p<=m1 && m1