Skip to content

Commit

Permalink
Additional tweaks to get markdown tables inside ALIASES work
Browse files Browse the repository at this point in the history
- Changed \_linebr to \ilinebr
- \ilinebr is now also passed to doctokenizer
- Also fixes issue #7493 regarding \snippet inside markdown tables and
  dealing with wrong line on issues detected by docparser after a
  markdown table.
- Added function tracing to markdown (enabled with -d markdown in a
  debug build)
  • Loading branch information
doxygen committed Jul 27, 2020
1 parent ab7dfc4 commit fdefd30
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 82 deletions.
26 changes: 13 additions & 13 deletions doc/custcmd.doc
@@ -1,12 +1,12 @@
/******************************************************************************
*
*
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
Expand All @@ -18,11 +18,11 @@

\tableofcontents{html,latex}

Doxygen provides a large number of \ref commands "special commands",
Doxygen provides a large number of \ref commands "special commands",
\ref xmlcmds "XML commands", and \ref htmlcmds "HTML commands".
that can be used to enhance or structure the documentation inside a comment block.
that can be used to enhance or structure the documentation inside a comment block.
If you for some reason have a need to define new commands you can do
so by means of an \e alias definition.
so by means of an \e alias definition.

The definition of an alias should be specified in the configuration file using
the \ref cfg_aliases "ALIASES" configuration tag.
Expand All @@ -32,15 +32,15 @@ The simplest form of an alias is a simple substitution of the form
\verbatim
name=value
\endverbatim
For example defining the following alias:
For example defining the following alias:
\verbatim
ALIASES += sideeffect="\par Side Effects:\n"
ALIASES += sideeffect="\par Side Effects:\n"
\endverbatim
will allow you to
put the command `\sideeffect` (or `@sideeffect`) in the documentation, which
put the command `\sideeffect` (or `@sideeffect`) in the documentation, which
will result in a user-defined paragraph with heading <b>Side Effects:</b>.

Note that you can put `\n`'s in the value part of an alias to insert newlines
Note that you cannot put `\n`'s in the value part of an alias to insert newlines
(in the resulting output). You can put `^^` in the value part of an alias to
insert a newline as if a physical newline was in the original file.

Expand All @@ -52,7 +52,7 @@ use a double escape (\c \\\\{ and \c \\\\})
Also note that you can redefine existing special commands if you wish.

Some commands, such as \ref cmdxrefitem "\\xrefitem" are designed to be used in
combination with aliases.
combination with aliases.

\section custcmd_complex Aliases with arguments
Aliases can also have one or more arguments. In the alias definition you then need
Expand Down Expand Up @@ -101,9 +101,9 @@ ALIASES += reminder="\xreflist{reminders,Reminder,Reminders}"

Note that if for aliases with more than one argument a comma is used as a separator,
if you want to put a comma inside the command, you will need to escape it with a backslash,
i.e.
i.e.
\verbatim
\l{SomeClass,Some text\, with an escaped comma}
\l{SomeClass,Some text\, with an escaped comma}
\endverbatim
given the alias definition of `\l` in the example above.

Expand Down
62 changes: 31 additions & 31 deletions src/commentscan.l
Expand Up @@ -163,7 +163,7 @@ struct DocCmdMap
static const std::map< std::string, DocCmdMap > docCmdMap =
{
// command name handler function command spacing
{ "_linebr", { &handleLineBr, CommandSpacing::Inline }},
{ "ilinebr", { &handleLineBr, CommandSpacing::Inline }},
{ "addindex", { &handleAddIndex, CommandSpacing::Invisible }},
{ "addtogroup", { &handleAddToGroup, CommandSpacing::Invisible }},
{ "anchor", { &handleAnchor, CommandSpacing::Invisible }},
Expand Down Expand Up @@ -472,7 +472,7 @@ BL [ \t\r]*"\n"
B [ \t]
BS ^(({B}*"//")?)(({B}*"*"+)?){B}*
ATTR ({B}+[^>\n]*)?
DOCNL "\n"|"\\_linebr"
DOCNL "\n"|"\\ilinebr"
LC "\\"{B}*"\n"
NW [^a-z_A-Z0-9]
FILESCHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+@&#]
Expand Down Expand Up @@ -505,34 +505,34 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
%x XRefItemParam3
%x FileDocArg1
%x ParamArg1
%x EnumDocArg1
%x NameSpaceDocArg1
%x PackageDocArg1
%x GroupDocArg1
%x GroupDocArg2
%x SectionLabel
%x SectionTitle
%x SubpageLabel
%x SubpageTitle
%x FormatBlock
%x LineParam
%x GuardParam
%x GuardParamEnd
%x SkipGuardedSection
%x SkipInternal
%x EnumDocArg1
%x NameSpaceDocArg1
%x PackageDocArg1
%x GroupDocArg1
%x GroupDocArg2
%x SectionLabel
%x SectionTitle
%x SubpageLabel
%x SubpageTitle
%x FormatBlock
%x LineParam
%x GuardParam
%x GuardParamEnd
%x SkipGuardedSection
%x SkipInternal
%x NameParam
%x InGroupParam
%x FnParam
%x OverloadParam
%x InheritParam
%x ExtendsParam
%x InGroupParam
%x FnParam
%x OverloadParam
%x InheritParam
%x ExtendsParam
%x ReadFormulaShort
%x ReadFormulaLong
%x AnchorLabel
%x ReadFormulaLong
%x AnchorLabel
%x HtmlComment
%x SkipLang
%x CiteLabel
%x CopyDoc
%x CiteLabel
%x CopyDoc
%x GuardExpr
%x CdataSection
%x Noop
Expand Down Expand Up @@ -833,7 +833,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
<Comment>".."[\.]?/[^ \t\n] { // internal ellipsis
addOutput(yyscanner,yytext);
}
<Comment>(\n|\\_linebr)({B}*(\n|\\_linebr))+ { // at least one blank line (or blank line command)
<Comment>(\n|\\ilinebr)({B}*(\n|\\ilinebr))+ { // at least one blank line (or blank line command)
if (yyextra->inContext==OutputXRef)
{
// see bug 613024, we need to put the newlines after ending the XRef section.
Expand All @@ -842,7 +842,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
for (i=0;i<(yy_size_t)yyleng;)
{
if (yytext[i]=='\n') addOutput(yyscanner,'\n'),i++;
else if (strcmp(yytext+i,"\\_linebr")==0) addOutput(yyscanner,'\n'),i+=8;
else if (strcmp(yytext+i,"\\ilinebr")==0) addOutput(yyscanner,"\\ilinebr"),i+=8;
else i++;
}
}
Expand All @@ -852,7 +852,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
for (i=0;i<(yy_size_t)yyleng;)
{
if (yytext[i]=='\n') addOutput(yyscanner,'\n'),i++;
else if (strcmp(yytext+i,"\\_linebr")==0) addOutput(yyscanner,'\n'),i+=8;
else if (strcmp(yytext+i,"\\ilinebr")==0) addOutput(yyscanner,"\\ilinebr"),i+=8;
else i++;
}
setOutput(yyscanner,OutputDoc);
Expand Down Expand Up @@ -1342,7 +1342,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
addOutput(yyscanner,yytext);
BEGIN( Comment );
}
<SectionTitle>[^\n@\\]*/"\\_linebr" { // end of section title
<SectionTitle>[^\n@\\]*/"\\ilinebr" { // end of section title
addSection(yyscanner);
addOutput(yyscanner,yytext);
BEGIN( Comment );
Expand Down Expand Up @@ -2540,7 +2540,7 @@ static bool handleInternal(yyscan_t yyscanner,const QCString &, const QCStringLi

static bool handleLineBr(yyscan_t yyscanner,const QCString &, const QCStringList &)
{
addOutput(yyscanner,'\n');
addOutput(yyscanner,"\\ilinebr");
return FALSE;
}

Expand Down
61 changes: 39 additions & 22 deletions src/doctokenizer.l
Expand Up @@ -114,6 +114,20 @@ bool doctokenizerYYpopContext()
return TRUE;
}

QCString extractPartAfterNewLine(const QCString &text)
{
int nl1 = text.findRev('\n');
if (nl1!=-1)
{
return text.mid(nl1+1);
}
int nl2 = text.findRev("\\ilinebr");
if (nl2!=-1)
{
return text.mid(nl2+8);
}
return text;
}

//--------------------------------------------------------------------------

Expand Down Expand Up @@ -520,43 +534,38 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
return TK_LISTITEM;
}
}
<St_Para>{BLANK}*\n{LISTITEM} { /* list item on next line */
QCString text=yytext;
text=text.right(text.length()-text.find('\n')-1);
<St_Para>{BLANK}*(\n|"\\ilinebr"){LISTITEM} { /* list item on next line */
QCString text=extractPartAfterNewLine(yytext);
int dashPos = text.findRev('-');
g_token->isEnumList = text.at(dashPos+1)=='#';
g_token->id = -1;
g_token->indent = computeIndent(text,dashPos);
return TK_LISTITEM;
}
<St_Para>{BLANK}*\n{MLISTITEM} { /* list item on next line */
<St_Para>{BLANK}*(\n|"\\ilinebr"){MLISTITEM} { /* list item on next line */
if (!g_markdownSupport || g_insidePre)
{
REJECT;
}
else
{
QCString text=yytext;
QCString text=extractPartAfterNewLine(yytext);
static QRegExp re("[*+]");
text=text.right(text.length()-text.find('\n')-1);
int markPos = text.findRev(re);
g_token->isEnumList = FALSE;
g_token->id = -1;
g_token->indent = computeIndent(text,markPos);
return TK_LISTITEM;
}
}
<St_Para>{BLANK}*\n{OLISTITEM} { /* list item on next line */
<St_Para>{BLANK}*(\n|"\\ilinebr"){OLISTITEM} { /* list item on next line */
if (!g_markdownSupport || g_insidePre)
{
REJECT;
}
else
{
QCString text=yytext;
int nl=text.findRev('\n');
int len=text.length();
text=text.right(len-nl-1);
QCString text=extractPartAfterNewLine(yytext);
static QRegExp re("[1-9]");
int digitPos = text.find(re);
int dotPos = text.find('.',digitPos);
Expand All @@ -571,11 +580,10 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
g_token->indent = computeIndent(yytext,dotPos);
return TK_ENDLIST;
}
<St_Para>{BLANK}*\n{ENDLIST} { /* end list on next line */
QCString text=yytext;
text=text.right(text.length()-text.find('\n')-1);
<St_Para>{BLANK}*(\n|"\\ilinebr"){ENDLIST} { /* end list on next line */
QCString text=extractPartAfterNewLine(yytext);
int dotPos = text.findRev('.');
g_token->indent = computeIndent(text,dotPos);
g_token->indent = computeIndent(text,dotPos);
return TK_ENDLIST;
}
<St_Para>"{"{BLANK}*"@link"/{BLANK}+ {
Expand All @@ -586,9 +594,9 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
g_token->name = "inheritdoc";
return TK_COMMAND_AT;
}
<St_Para>"@_fakenl" { // artificial new line
yylineno++;
}
<St_Para>"@_fakenl" { // artificial new line
yylineno++;
}
<St_Para>{SPCMD3} {
g_token->name = "_form";
bool ok;
Expand All @@ -603,6 +611,8 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
g_token->paramDir=TokenInfo::Unspecified;
return TK_COMMAND_SEL();
}
<St_Para>"\\ilinebr" {
}
<St_Para>{SPCMD1} |
<St_Para>{SPCMD2} |
<St_Para>{SPCMD5} |
Expand Down Expand Up @@ -1367,17 +1377,23 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
warn(g_fileName,yylineno,"Unexpected character '%s' while looking for section label or title",yytext);
}

<St_Snippet>[^\n]+ |
<St_Snippet>[^\n]*\n {
g_token->name = yytext;
<St_Snippet>[^\\\n]+ {
g_token->name += yytext;
}
<St_Snippet>"\\" {
g_token->name += yytext;
}
<St_Snippet>(\n|"\\ilinebr") {
g_token->name = g_token->name.stripWhiteSpace();
return TK_WORD;
return TK_WORD;
}

/* Generic rules that work for all states */
<*>\n {
warn(g_fileName,yylineno,"Unexpected new line character");
}
<*>"\\ilinebr" {
}
<*>[\\@<>&$#%~"=] { /* unescaped special character */
//warn(g_fileName,yylineno,"Unexpected character '%s', assuming command \\%s was meant.",yytext,yytext);
g_token->name = yytext;
Expand Down Expand Up @@ -1571,6 +1587,7 @@ void doctokenizerYYsetStateAnchor()

void doctokenizerYYsetStateSnippet()
{
g_token->name="";
BEGIN(St_Snippet);
}

Expand Down
4 changes: 2 additions & 2 deletions src/doxygen.cpp
Expand Up @@ -9628,7 +9628,7 @@ static void escapeAliases()
value.mid(in,14)!="\\nosubgrouping"
)
{
newValue+="\\_linebr ";
newValue+="\\ilinebr ";
}
else
{
Expand All @@ -9643,7 +9643,7 @@ static void escapeAliases()
while ((in=value.find("^^",p))!=-1)
{
newValue+=value.mid(p,in-p);
newValue+="\\\\_linebr ";
newValue+="\\ilinebr ";
p=in+2;
}
newValue+=value.mid(p,value.length()-p);
Expand Down

0 comments on commit fdefd30

Please sign in to comment.