diff options
| author | 2022-04-29 10:48:09 +0200 | |
|---|---|---|
| committer | 2022-04-29 10:48:09 +0200 | |
| commit | 07c5f6ec23fcf9237a24e71adcfacabce677f818 (patch) | |
| tree | 588e8c5f82b9163181fad3581f610e6f1d88cba4 /src/bin/cli/main.cpp | |
| parent | a9153f1615a842cfb9e9bcda4d9071e202618569 (diff) | |
| download | OneRoll-07c5f6ec23fcf9237a24e71adcfacabce677f818.tar.gz OneRoll-07c5f6ec23fcf9237a24e71adcfacabce677f818.zip | |
Change file organization.
Diffstat (limited to 'src/bin/cli/main.cpp')
| -rw-r--r-- | src/bin/cli/main.cpp | 621 |
1 files changed, 621 insertions, 0 deletions
diff --git a/src/bin/cli/main.cpp b/src/bin/cli/main.cpp new file mode 100644 index 0000000..0420ac3 --- /dev/null +++ b/src/bin/cli/main.cpp @@ -0,0 +1,621 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * http://www.rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser 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. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <QCommandLineOption> +#include <QCommandLineParser> +#include <QDebug> +#include <QFile> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> +#include <QRegularExpression> +#include <QSettings> +#include <QStringList> +#include <QTextStream> +#include <set> + +#ifdef PAINTER_OP +#include <QGuiApplication> +#else +#include <QCoreApplication> +#endif + +#include "diceparser/dicealias.h" +#include "diceparser/diceparser.h" +#include "diceparser/highlightdice.h" +#include "diceparser/parsingtoolbox.h" +#include "displaytoolbox.h" + +/** + * @page Dice + * The cli for DiceParser the new dice system from rolisteam. + * @section Build and install + * To build this program, type these command: + * - mkdir build + * - cd build + * - cmake ../ + * - make + * - make install + * @return + */ + +QTextStream out(stdout, QIODevice::WriteOnly); +QTextStream err(stderr, QIODevice::WriteOnly); +bool markdown= false; +constexpr char const* colorkey= {"dicecolor"}; +#ifdef PAINTER_OP +enum EXPORTFORMAT +{ + TERMINAL, + SVG, + IMAGE, + MARKDOWN, + JSON, + BOT, + TEXT +}; +#else +enum EXPORTFORMAT +{ + TERMINAL, + SVG, + MARKDOWN, + JSON, + BOT, + TEXT +}; +#endif +int returnValue= 0; + +void displayJSon(QString json) +{ + out << json << "\n"; +} +void displayMarkdown(QString json) +{ + QJsonDocument doc= QJsonDocument::fromJson(json.toUtf8()); + auto obj= doc.object(); + auto error= obj["error"].toString(); + auto warning= obj["warning"].toString(); + auto comment= obj["comment"].toString(); + auto arrayInst= obj["instructions"].toArray(); + QStringList diceResults; + for(auto inst : arrayInst) + { + auto obj= inst.toObject(); + auto diceVals= obj["diceval"].toArray(); + for(auto diceval : diceVals) + { + auto objval= diceval.toObject(); + auto resultStr= QString::number(objval["value"].toDouble()); + + auto subvalues= objval["subvalues"].toArray(); + QStringList subValueStr; + for(auto sub : subvalues) + { + subValueStr << QString::number(sub.toDouble()); + } + diceResults << resultStr; + if(!subValueStr.isEmpty()) + diceResults << QString("[%1]").arg(subValueStr.join(" ")); + } + } + auto diceList= diceResults.join(" "); + auto resultStr= obj["string"].toString(); + auto scalarText= obj["scalar"].toString(); + auto cmd= obj["command"].toString(); + + QString str("```Markdown\n"); + if(!error.isEmpty()) + { + str.append(QStringLiteral("Error: %1\n").arg(error)); + } + else + { + if(!warning.isEmpty()) + str.append(QStringLiteral("Warning: %1\n").arg(warning)); + + if(!comment.isEmpty()) + { + str.prepend(QStringLiteral("%1\n").arg(comment)); + } + if(!resultStr.isEmpty() && resultStr != scalarText) + { + // resultStr.replace("%2", diceList.trimmed()); + str.append(QStringLiteral("%1\n").arg(resultStr)); + } + else + { + str.append(QStringLiteral("# %1\nDetails:[%3 (%2)]\n").arg(scalarText).arg(diceList).arg(cmd)); + } + } + str.append(QStringLiteral("```")); + out << str; +} +QString displaySVG(QString json, bool withColor) +{ + QJsonDocument doc= QJsonDocument::fromJson(json.toUtf8()); + auto obj= doc.object(); + auto error= obj["error"].toString(); + auto warning= obj["warning"].toString(); + auto comment= obj["warning"].toString(); + auto arrayInst= obj["instructions"].toArray(); + QStringList diceResults; + for(auto inst : arrayInst) + { + auto obj= inst.toObject(); + auto diceVals= obj["diceval"].toArray(); + for(auto diceval : diceVals) + { + auto objval= diceval.toObject(); + auto resultStr= objval["string"].toString(); + diceResults << resultStr; + } + } + auto diceList= diceResults.join(","); + auto resultStr= obj["string"].toString(); + auto scalarText= obj["scalar"].toString(); + auto cmd= obj["command"].toString(); + + QString str("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<svg version=\"1.1\" " + "xmlns=\"http://www.w3.org/2000/svg\" " + "xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n"); + if(!error.isEmpty()) + { + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"20\"><tspan " + "fill=\"red\">%1</tspan></text>") + .arg(error)); + } + else + { + if(!warning.isEmpty()) + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"20\"><tspan " + "fill=\"orange\">%1</tspan></text>") + .arg(warning)); + + int y= 20; + if(!comment.isEmpty()) + { + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"%2\"><tspan " + "fill=\"blue\">%1</tspan></text>") + .arg(comment) + .arg(y)); + y+= 20; + } + // auto diceList= DisplayToolBox::diceToSvg(array, withColor, allSameColor, allSameFaceCount); + if(!resultStr.isEmpty() && resultStr != scalarText) + { + resultStr.replace("%2", diceList.trimmed()); + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"%2\">%1</text>").arg(resultStr).arg(y)); + } + else + { + if(withColor) + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"%4\"><tspan " + "fill=\"red\">%1</tspan>\n" + "<tspan x=\"0\" y=\"%5\">details:</tspan>[%3 (%2)]</text>") + .arg(scalarText) + .arg(diceList) + .arg(cmd) + .arg(y) + .arg(y * 2)); + else + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"%4\"><tspan>%1</tspan>\n" + "<tspan x=\"0\" y=\"%5\">details:</tspan>[%3 (%2)]</text>") + .arg(scalarText) + .arg(diceList) + .arg(cmd) + .arg(y) + .arg(y * 2)); + } + } + str.append(QStringLiteral("</svg>\n")); + return str; +} + +#ifdef PAINTER_OP +void displayImage(QString json, bool withColor) +{ + auto svg= displaySVG(json, withColor); + out << DisplayToolBox::makeImage(svg.toUtf8()); +} +#endif + +void displayCommandResult(QString json, bool withColor, QString color) +{ + QJsonDocument doc= QJsonDocument::fromJson(json.toUtf8()); + auto obj= doc.object(); + auto error= obj["error"].toString(); + auto warning= obj["warning"].toString(); + auto comment= obj["comment"].toString(); + auto arrayInst= obj["instructions"].toArray(); + QStringList diceResults; + for(const auto& inst : qAsConst(arrayInst)) + { + auto obj= inst.toObject(); + auto diceVals= obj["diceval"].toArray(); + for(const auto& diceval : qAsConst(diceVals)) + { + auto objval= diceval.toObject(); + auto resultStr= objval["string"].toString(); + diceResults << resultStr; + } + } + auto diceList= diceResults.join(","); + auto scalarText= obj["scalar"].toString(); + auto cmd= obj["command"].toString(); + auto resultStr= obj["string"].toString(); + + if(!error.isEmpty()) + { + err << "Error" << error << "\n"; + return; + } + + if(!warning.isEmpty()) + err << "Warning: " << warning << "\n"; + + QString str; + + if(withColor) + str= QString("Result: \e[0;%4;1m%1\e[0m - details:[%3 (%2)]") + .arg(scalarText, diceList, cmd, DisplayToolBox::colorToIntCode(color)); + else + str= QString("Result: %1 - details:[%3 (%2)]").arg(scalarText, diceList, cmd); + + if(!resultStr.isEmpty() && resultStr != scalarText) + { + resultStr.replace("%2", diceList.trimmed()); + str= resultStr; + } + + if(!comment.isEmpty()) + { + if(withColor) + out << "\033[1m" << comment << "\033[0m\n"; + else + out << comment << " "; + } + out << str << "\n"; +} + +int startDiceParsing(QStringList& cmds, bool withColor, QString baseColor, EXPORTFORMAT format, QJsonArray array, + const QString& filePath) +{ + DiceParser parser; + parser.insertAlias(new DiceAlias("L5R5R", QStringLiteral("L[-,⨀,⨀⬢,❂⬢,❁,❁⬢]")), 0); + parser.insertAlias(new DiceAlias("L5R5S", QStringLiteral("L[-,-,⨀,⨀,⨀❁,⨀⬢,⨀⬢,❂,❂⬢,❁,❁,❁]")), 1); + int i= 2; + for(auto alias : array) + { + auto objAlias= alias.toObject(); + parser.insertAlias(new DiceAlias(objAlias["pattern"].toString(), objAlias["cmd"].toString(), + objAlias["comment"].toString(), !objAlias["regexp"].toBool()), + i++); + } + + int rt= 0; + bool in_markdown= true; + + for(QString cmd : cmds) + { + if(cmd.startsWith('&') && format == BOT) + { + cmd= cmd.remove(0, 1); + in_markdown= false; + } + + if(parser.parseLine(cmd)) + { + parser.start(); + + std::set<EXPORTFORMAT> svgFormat({SVG, IMAGE, BOT}); + QString json; + bool allSameColor= true; + if(svgFormat.find(format) != svgFormat.end()) + { + allSameColor= true; + QString colorP; + json= parser.resultAsJSon( + [&colorP, &allSameColor](const QString& value, const QString& color, bool) { + if(colorP.isNull()) + colorP= color; + else if(colorP != color) + allSameColor= false; + + return value; + }, + true); + + if(!allSameColor) + { + json= parser.resultAsJSon([](const QString& value, const QString& color, bool highlight) { + QString result= value; + bool hasColor= !color.isEmpty(); + QString style; + if(hasColor) + { + style+= QStringLiteral("fill=\"%1\" ").arg(color); + } + if(highlight) + { + if(style.isEmpty()) + style+= QStringLiteral("fill=\"%1\" ") + .arg("red"); // default color must get the value from the setting object + style+= QStringLiteral("font-weight=\"bold\" "); + } + if(!style.isEmpty()) + result= QString("<tspan %2>%1</tspan>").arg(value).arg(style); + return result; + }); + } + } + else if(TERMINAL == format) + { + allSameColor= true; + QString colorP; + json= parser.resultAsJSon( + [&colorP, &allSameColor, &baseColor](const QString& result, const QString& color, bool hightlight) { + auto trueColor= color; + if(color.isEmpty()) + trueColor= baseColor; + + if(colorP.isEmpty()) + colorP= trueColor; + else if(colorP != trueColor) + allSameColor= false; + + auto front= DisplayToolBox::colorToTermCode(trueColor); + auto end= front.isEmpty() ? "" : DisplayToolBox::colorToTermCode("reset"); + return hightlight ? QString("%1%2%3").arg(front).arg(result).arg(end) : result; + }); + } + else + { + allSameColor= true; + json= parser.resultAsJSon([](const QString& result, const QString&, bool) { return result; }); + } + + if(format == BOT) + { + if(allSameColor) + { + format= in_markdown ? MARKDOWN : TEXT; + } + else + { +#ifdef PAINTER_OP + format= IMAGE; +#else + format= MARKDOWN; +#endif + } + if(!parser.humanReadableError().isEmpty()) + { + format= MARKDOWN; + } + } + if(!withColor && format == TERMINAL) + format= TEXT; + + // qDebug().noquote() << json << format; + + switch(format) + { + case TERMINAL: + displayCommandResult(json, withColor, baseColor); + break; + case SVG: + out << displaySVG(json, withColor) << "\n"; + break; + case BOT: + case MARKDOWN: + displayMarkdown(json); + break; + case TEXT: + displayCommandResult(json, false, baseColor); + break; + case JSON: + displayJSon(json); + break; +#ifdef PAINTER_OP + case IMAGE: + displayImage(json, withColor); + break; +#endif + } + if(!filePath.isEmpty()) + { + parser.writeDownDotTree(filePath); + } + } + else + rt= 1; + } + return rt; +} + +int main(int argc, char* argv[]) +{ +#ifdef PAINTER_OP + QGuiApplication a(argc, argv); +#else + QCoreApplication a(argc, argv); +#endif + + QStringList commands; + QString cmd; + QString dotFileStr; + bool colorb= true; + QSettings settings("rolisteam", "diceparser"); + QString formatColor; + EXPORTFORMAT format= TERMINAL; + + QCommandLineParser optionParser; + QCommandLineOption color(QStringList() << "c" + << "color-off", + "Disable color to highlight result"); + QCommandLineOption version(QStringList() << "v" + << "version", + "Show the version and quit."); + QCommandLineOption reset(QStringList() << "reset-settings", "Erase the settings and use the default parameters"); + QCommandLineOption alias(QStringList() << "a" + << "alias", + "path to alias json files: <aliasfile>", "aliasfile"); + + QCommandLineOption aliasData(QStringList() << "alias-data", "alias in json data <aliasdata>", "aliasdata"); + + QCommandLineOption character(QStringList() << "s" + << "charactersheet", + "set Parameters to simulate character sheet: <sheetfile>", "sheetfile"); + QCommandLineOption markdown(QStringList() << "m" + << "markdown", + "The output is formatted in markdown."); + QCommandLineOption bot(QStringList() << "b" + << "bot", + "Discord bot."); + QCommandLineOption svg(QStringList() << "g" + << "svg", + "The output is formatted in svg."); + QCommandLineOption outColor(QStringList() << "C" + << "color", + "Use color for result: <color>", "color"); + QCommandLineOption json(QStringList() << "j" + << "json", + "The output is formatted in json."); + QCommandLineOption line(QStringList() << "l" + << "line", + "The output is in one line [default]."); + QCommandLineOption dotFile(QStringList() << "d" + << "dot-file", + "Instead of rolling dice, generate the execution tree and write it in " + "<dotfile>", + "dotfile"); + QCommandLineOption translation(QStringList() << "t" + << "translation", + "path to the translation file: <translationfile>", "translationfile"); + QCommandLineOption help(QStringList() << "h" + << "help", + "Display this help"); + + optionParser.addOption(color); + optionParser.addOption(version); + optionParser.addOption(reset); + optionParser.addOption(dotFile); + optionParser.addOption(alias); + optionParser.addOption(aliasData); + optionParser.addOption(character); + optionParser.addOption(line); + optionParser.addOption(markdown); + optionParser.addOption(bot); + optionParser.addOption(svg); + optionParser.addOption(outColor); + optionParser.addOption(json); + optionParser.addOption(translation); + optionParser.addOption(help); + for(int i= 0; i < argc; ++i) + { + commands << QString::fromUtf8(argv[i]); + } + + optionParser.process(commands); + + if(optionParser.isSet(color)) + { + commands.removeAt(0); + colorb= false; + } + else if(optionParser.isSet(version)) + { + out << "Rolisteam DiceParser v1.0.0" + << "\n"; + out << "More Details: www.rolisteam.org" + << "\n"; + return 0; + } + else if(optionParser.isSet(reset)) + { + return 0; + } + else if(optionParser.isSet(dotFile)) + { + dotFileStr= optionParser.value(dotFile); + } + if(optionParser.isSet(markdown)) + { + format= MARKDOWN; + } + else if(optionParser.isSet(bot)) + { + format= BOT; + } + else if(optionParser.isSet(svg)) + { + format= SVG; + } + else if(optionParser.isSet(json)) + { + format= JSON; + } + else if(optionParser.isSet(line)) + { + format= TEXT; + } + if(optionParser.isSet(outColor)) + { + settings.setValue(colorkey, optionParser.value(outColor)); + } + + if(optionParser.isSet(help)) + { + cmd= "help"; + } + QStringList cmdList= optionParser.positionalArguments(); + + QJsonArray aliases; + if(optionParser.isSet(alias)) + { + auto aliasstr= optionParser.value(alias); + + QFile file(aliasstr); + + if(file.open(QIODevice::ReadOnly)) + { + QJsonDocument doc= QJsonDocument::fromJson(file.readAll()); + aliases= doc.array(); + } + } + else if(optionParser.isSet(aliasData)) + { + auto aliasstr= optionParser.value(aliasData); + QJsonDocument doc= QJsonDocument::fromJson(aliasstr.toUtf8()); + aliases= doc.array(); + } + + formatColor= settings.value(colorkey, "red").value<QString>(); + returnValue= startDiceParsing(cmdList, colorb, formatColor, format, aliases, dotFileStr); + if(optionParser.isSet(help)) + { + out << optionParser.helpText(); + } + return returnValue; +} |