Skip to content

Commit

Permalink
Extending startuml with extra figure types
Browse files Browse the repository at this point in the history
Not all diagrams can be created with the PlantUML `@startuml` command but need another
PlantUML `@start...` command. This wil look like `@start<engine>` where currently supported are
the following `<engine>`'s: `uml`, `bpm`, `wire`, `dot`, `ditaa`, `salt`, `math`, `latex`,
`gantt`, `mindmap`, `wbs`, `yaml`, `creole`, `json` and `flow`. By default the `<engine>` is
`uml`. The `<engine>` can be specified as an option.

Explicitly the option variant has been chosen so we won't get an explosion of extra commands.
  • Loading branch information
albert-github committed Apr 4, 2021
1 parent 97415f7 commit afa248d
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 18 deletions.
22 changes: 17 additions & 5 deletions doc/commands.doc
Expand Up @@ -2907,19 +2907,31 @@ class Receiver
\sa section \ref cmdmscfile "\\mscfile".

<hr>
\section cmdstartuml \\startuml [{file}] ["caption"] [<sizeindication>=<size>]
\section cmdstartuml \\startuml ['{'option[,option]'}'] ["caption"] [<sizeindication>=<size>]

\addindex \\startuml

Starts a text fragment which should contain a valid description of a
PlantUML diagram. See https://plantuml.com/ for examples.
The text fragment ends with \ref cmdenduml "\\enduml".
\note You need to install Java and the PlantUML's jar file,
if you want to use this command. The location of the jar file should be specified
using \ref cfg_plantuml_jar_path "PLANTUML_JAR_PATH".
if you want to use this command. When using PlantUML in \LaTeX you have to download
some more `jar` files, for details see the PlantUML documentation.
The location of the jar file should be specified using
\ref cfg_plantuml_jar_path "PLANTUML_JAR_PATH".

Not all diagrams can be created with the PlantUML `@startuml` command but need another
PlantUML `@start...` command. This wil look like `@start<engine>` where currently supported are
the following `<engine>`'s: `uml`, `bpm`, `wire`, `dot`, `ditaa`, `salt`, `math`, `latex`,
`gantt`, `mindmap`, `wbs`, `yaml`, `creole`, `json` and `flow`. By default the `<engine>` is
`uml`. The `<engine>` can be specified as an option.
Also the file to write the resulting image to can be specified by means of an option, see the
description of the first (optional) argument for details.
Of course only one `<engine>` can be specified and also the filename can only be specified once.

The first argument is optional and is for compatibility with running PlantUML as a preprocessing
step before running doxygen, you can also add the name of the image file after \c \\startuml
and inside curly brackets, i.e.
step before running doxygen, you can also add the name of the image file after `\startuml`
and inside curly brackets as option, i.e.
\verbatim
@startuml{myimage.png} "Image Caption" width=5cm
Alice -> Bob : Hello
Expand Down
2 changes: 1 addition & 1 deletion src/docbookvisitor.cpp
Expand Up @@ -395,7 +395,7 @@ DB_VIS_C
case DocVerbatim::PlantUML:
{
static QCString docbookOutput = Config_getString(DOCBOOK_OUTPUT);
QCString baseName = PlantumlManager::instance().writePlantUMLSource(docbookOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_BITMAP);
QCString baseName = PlantumlManager::instance().writePlantUMLSource(docbookOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_BITMAP,s->engine());
QCString shortName = baseName;
int i;
if ((i=shortName.findRev('/'))!=-1)
Expand Down
65 changes: 64 additions & 1 deletion src/docparser.cpp
Expand Up @@ -79,6 +79,9 @@ static const char *sectionLevelToName[] =
"subparagraph"
};

static const char *plantumlStart[] = {"uml", "bpm", "wire", "dot", "ditaa",
"salt", "math", "latex", "gantt", "mindmap",
"wbs", "yaml", "creole", "json", "flow" };
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
Expand Down Expand Up @@ -5535,8 +5538,68 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok)
static QCString jarPath = Config_getString(PLANTUML_JAR_PATH);
doctokenizerYYsetStatePlantUMLOpt();
retval = doctokenizerYYlex();
QCString plantFile(g_token->sectionId);

QCString fullMatch = g_token->sectionId;
QCString sectionId = "";
int idx = fullMatch.find('{');
int idxEnd = fullMatch.find("}",idx+1);
QCString cmdName;
StringVector optList;
QCString engine;
if (idx != -1) // options present
{
QCString optStr = fullMatch.mid(idx+1,idxEnd-idx-1).stripWhiteSpace();
optList = split(optStr.str(),",");
for (const auto &opt : optList)
{
if (opt.empty()) continue;
bool found = false;
QCString locOpt = opt;
locOpt = locOpt.lower();
for (int i = 0; i < sizeof(plantumlStart) / sizeof(*plantumlStart); i++)
{
if (locOpt == plantumlStart[i])
{
if (!engine.isEmpty())
{
warn(g_fileName,getDoctokinizerLineNr(), "Multiple definition of engine for '\\startuml'");
}
engine = plantumlStart[i];
found = true;
break;
}
}
if (!found)
{
if (sectionId.isEmpty())
{
sectionId = opt;
}
else
{
warn(g_fileName,getDoctokinizerLineNr(),"Multiple use of of filename for '\\startuml'");
}
}
}
}
else
{
sectionId = g_token->sectionId;
}
if (engine.isEmpty()) engine = "uml";

if (sectionId.isEmpty())
{
doctokenizerYYsetStatePlantUMLOpt();
retval = doctokenizerYYlex();

sectionId = g_token->sectionId;
sectionId = sectionId.stripWhiteSpace();
}

QCString plantFile(sectionId);
DocVerbatim *dv = new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::PlantUML,FALSE,plantFile);
dv->setEngine(engine);
doctokenizerYYsetStatePara();
QCString width,height;
defaultHandleTitleAndSize(CMD_STARTUML,dv,dv->children(),width,height);
Expand Down
3 changes: 3 additions & 0 deletions src/docparser.h
Expand Up @@ -507,11 +507,13 @@ class DocVerbatim : public DocNode
bool hasCaption() const { return !m_children.empty(); }
QCString width() const { return m_width; }
QCString height() const { return m_height; }
QCString engine() const { return m_engine; }
const DocNodeList &children() const { return m_children; }
DocNodeList &children() { return m_children; }
void setText(const QCString &t) { m_text=t; }
void setWidth(const QCString &w) { m_width=w; }
void setHeight(const QCString &h) { m_height=h; }
void setEngine(const QCString &e) { m_engine=e; }

private:
QCString m_context;
Expand All @@ -524,6 +526,7 @@ class DocVerbatim : public DocNode
bool m_isBlock = false;
QCString m_width;
QCString m_height;
QCString m_engine;
DocNodeList m_children;
};

Expand Down
4 changes: 1 addition & 3 deletions src/doctokenizer.l
Expand Up @@ -964,10 +964,8 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio
lineCount(yytext,yyleng);
g_token->verb+=yytext;
}
<St_PlantUMLOpt>{BLANK}*"{"[^}]*"}" { // case 1: file name is specified as {filename}
<St_PlantUMLOpt>{BLANK}*"{"[a-zA-Z_,:0-9\. ]*"}" { // case 1: options present
g_token->sectionId = QCString(yytext).stripWhiteSpace();
// skip curly brackets around the optional image name
g_token->sectionId = g_token->sectionId.mid(1,g_token->sectionId.length()-2).stripWhiteSpace();
return RetVal_OK;
}
<St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANK}+/{ID}"=" { // case 2: plain file name specified followed by an attribute
Expand Down
2 changes: 1 addition & 1 deletion src/htmldocvisitor.cpp
Expand Up @@ -628,7 +628,7 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
{
format = PlantumlManager::PUML_SVG;
}
QCString baseName = PlantumlManager::instance().writePlantUMLSource(htmlOutput,s->exampleFile(),s->text(),format);
QCString baseName = PlantumlManager::instance().writePlantUMLSource(htmlOutput,s->exampleFile(),s->text(),format,s->engine());
m_t << "<div class=\"plantumlgraph\">\n";
writePlantUMLFile(baseName,s->relPath(),s->context());
visitPreCaption(m_t, s);
Expand Down
2 changes: 1 addition & 1 deletion src/latexdocvisitor.cpp
Expand Up @@ -432,7 +432,7 @@ void LatexDocVisitor::visit(DocVerbatim *s)
case DocVerbatim::PlantUML:
{
QCString latexOutput = Config_getString(LATEX_OUTPUT);
QCString baseName = PlantumlManager::instance().writePlantUMLSource(latexOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_EPS);
QCString baseName = PlantumlManager::instance().writePlantUMLSource(latexOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_EPS,s->engine());

writePlantUMLFile(baseName, s);
}
Expand Down
6 changes: 3 additions & 3 deletions src/plantuml.cpp
Expand Up @@ -22,7 +22,7 @@
#include "debug.h"
#include "fileinfo.h"

QCString PlantumlManager::writePlantUMLSource(const QCString &outDirArg,const QCString &fileName,const QCString &content,OutputFormat format)
QCString PlantumlManager::writePlantUMLSource(const QCString &outDirArg,const QCString &fileName,const QCString &content,OutputFormat format, const QCString &engine)
{
QCString baseName;
QCString puName;
Expand Down Expand Up @@ -71,9 +71,9 @@ QCString PlantumlManager::writePlantUMLSource(const QCString &outDirArg,const QC
Debug::print(Debug::Plantuml,0,"*** %s puName: %s\n","writePlantUMLSource",qPrint(puName));
Debug::print(Debug::Plantuml,0,"*** %s imgName: %s\n","writePlantUMLSource",qPrint(imgName));

QCString text = "@startuml "+imgName+"\n";
QCString text = "@start"+engine+" "+imgName+"\n";
text+=content;
text+="\n@enduml\n";
text+="\n@end"+engine+"\n";

QCString qcOutDir(outDir);
uint pos = qcOutDir.findRev("/");
Expand Down
3 changes: 2 additions & 1 deletion src/plantuml.h
Expand Up @@ -58,12 +58,13 @@ class PlantumlManager
* @param[in] format the image format to generate.
* @returns The name of the generated file.
*/
QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content, OutputFormat format);
QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content, OutputFormat format, const QCString &engine);

/** Convert a PlantUML file to an image.
* @param[in] baseName the name of the generated file (as returned by writePlantUMLSource())
* @param[in] outDir the directory to write the resulting image into.
* @param[in] format the image format to generate.
* @param[in] engine the plantuml engine to be used so the start command will be `@start<engine>`
*/
void generatePlantUMLOutput(const char *baseName,const char *outDir,OutputFormat format);

Expand Down
2 changes: 1 addition & 1 deletion src/rtfdocvisitor.cpp
Expand Up @@ -383,7 +383,7 @@ void RTFDocVisitor::visit(DocVerbatim *s)
case DocVerbatim::PlantUML:
{
static QCString rtfOutput = Config_getString(RTF_OUTPUT);
QCString baseName = PlantumlManager::instance().writePlantUMLSource(rtfOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_BITMAP);
QCString baseName = PlantumlManager::instance().writePlantUMLSource(rtfOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_BITMAP,s->engine());

writePlantUMLFile(baseName, s->hasCaption());
visitCaption(this, s->children());
Expand Down
2 changes: 1 addition & 1 deletion src/vhdldocgen.cpp
Expand Up @@ -3344,7 +3344,7 @@ void FlowChart::printUmlTree()
QCString htmlOutDir = Config_getString(HTML_OUTPUT);

QCString n=convertNameToFileName();
n=PlantumlManager::instance().writePlantUMLSource(htmlOutDir,n,qcs,PlantumlManager::PUML_SVG);
n=PlantumlManager::instance().writePlantUMLSource(htmlOutDir,n,qcs,PlantumlManager::PUML_SVG,"uml");
PlantumlManager::instance().generatePlantUMLOutput(n,htmlOutDir,PlantumlManager::PUML_SVG);
}

Expand Down

0 comments on commit afa248d

Please sign in to comment.