4
0
mirror of https://github.com/QuasarApp/QuasarAppLib.git synced 2025-05-08 07:29:43 +00:00

Merge pull request from QuasarApp/optionValidator

Option validator
This commit is contained in:
Andrei Yankovich 2021-07-28 13:28:33 +03:00 committed by GitHub
commit d37c6a1ff0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 448 additions and 47 deletions

@ -35,6 +35,7 @@ CONFIG(release, debug|release): {
SOURCES += \
helpdata.cpp \
optiondata.cpp \
quasarapp.cpp \
params.cpp \
locales.cpp \
@ -43,6 +44,7 @@ SOURCES += \
HEADERS += \
helpdata.h \
optiondata.h \
quasarapp.h \
quasarapp_global.h \
params.h \

@ -3,11 +3,8 @@ Global functions used in applications QuasarApp.
This lib include include next modules:
* Locales - This module use for parse local files. This module allows you to work with translations.
* Params - This module use for parese app params and create log.
* Settings - This is a module that allows you to work with application settings.
* Global - This module contains other global functions.
@ -49,24 +46,13 @@ target_link_libraries(MyBinary PUBLIC QuasarApp)
```
# Usage
Create objects of the BigInt class, and do what you got to do!
```cpp
#include <quasarapp.h>
if (!QuasarAppUtils::Params::parseParams(argc, argv)) {
QuasarAppUtils::Params::log("Warning message", QuasarAppUtils::Warning);
Help::Charters help = {
{
"Main Section ", {
{"-argument1", "description of the argument1"},
{"-argument2", "description of the argument2"},
}
}
};
QuasarAppUtils::Help::print(help);
QuasarAppUtils::Params::showHelp();
exit(0);
}
```

@ -20,7 +20,7 @@ namespace QuasarAppUtils {
namespace Help {
static int MAX_LENGTH = -1;
static int SectionMargin = 3;
static int SectionMargin = 2;
#define EXPANDER(COUNT, ITEM) QString(COUNT, ITEM).toStdString()
#define SPACES(X) EXPANDER(X, ' ')
@ -43,7 +43,7 @@ void print(const QString& key, const QString& value, int keyLength) {
QString expander(keyLength + SectionMargin, ' ');
auto words = value.split(" ");
int currentLength = keyLength;
int currentLength = std::max(keyLength, static_cast<int>(key.size()));
for (const auto& word : words) {
if (currentLength + 2 + word.size() < WIDTH) {
std::cout << " " << word.toStdString();
@ -66,6 +66,8 @@ void print(const QuasarAppUtils::Help::Options &oprionsList) {
maxLength = line.key().size();
}
maxLength = std::min(WIDTH / 3, maxLength);
for (auto line = oprionsList.begin(); line != oprionsList.end(); ++line) {
print(line.key(), line.value(), maxLength + SectionMargin);
std::cout << std::endl;

@ -25,7 +25,7 @@ namespace Help {
*
* @code{cpp}
* Options myOptionsList = {{"argument1", "This is test argumetn1 of my application."},
* {"argument1", "This is test argumetn1 of my application."}};
* {"argument2", "This is test argumetn2 of my application."}};
*
* @endcode
*/
@ -37,7 +37,7 @@ typedef QMultiMap<QString, QString> Options;
* **Example:**
* @code{cpp}
* Options myOptionsList = {{"argument1", "This is test argumetn1 of my application."},
* {"argument1", "This is test argumetn1 of my application."}};
* {"argument2", "This is test argumetn2 of my application."}};
* Section mySections = {{"This Is main section of the help", myOptionsList}};
* QuasarAppUtils::Help::print(mySections);
* @endcode

91
optiondata.cpp Normal file

@ -0,0 +1,91 @@
/*
* Copyright (C) 2021-2021 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "optiondata.h"
#include "global.h"
namespace QuasarAppUtils{
OptionData::OptionData(const QStringList& name,
const QString& arguments,
const QString& description,
const QString& example,
const QString& depricatedMsg,
bool removed) {
setNames(name);
setArguments(arguments);
setDescription(description);
setExample(example);
setDepricatedMsg(depricatedMsg);
_removed = removed;
}
const QStringList &OptionData::names() const {
return _name;
}
void OptionData::setNames(const QStringList &newName) {
_name = newName;
}
const QString &OptionData::description() const {
return _description;
}
void OptionData::setDescription(const QString &newDescription) {
_description = newDescription;
}
const QString &OptionData::example() const {
return _example;
}
void OptionData::setExample(const QString &newExample) {
_example = newExample;
}
const QString &OptionData::arguments() const {
return _arguments;
}
void OptionData::setArguments(const QString &newArguments) {
_arguments = newArguments;
}
const QString &OptionData::depricatedMsg() const {
return _depricatedMsg;
}
void OptionData::setDepricatedMsg(const QString &newDepricatedMsg) {
_depricatedMsg = newDepricatedMsg;
}
bool OptionData::isRemoved() const {
return _removed;
}
bool OptionData::isDepricated() const {
return depricatedMsg().size();
}
Help::Options OptionData::toHelp() const {
QString left = names().join(" / ") + " " + arguments();
QString right = description();
if (example().size()) {
right += " Example: " + example();
}
return {{left, {right}}};
}
bool OptionData::isValid() const {
return names().size();
}
}

152
optiondata.h Normal file

@ -0,0 +1,152 @@
/*
* Copyright (C) 2021-2021 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef OPTIONDATA_H
#define OPTIONDATA_H
#include "quasarapp_global.h"
#include "helpdata.h"
namespace QuasarAppUtils{
/**
* @brief The OptionData class contains information about one option.
*/
class QUASARAPPSHARED_EXPORT OptionData
{
public:
/**
* @brief OptionData This is main constructor
* @param names This is names list of the option. It is a required argument and cannot be empty.
* @param arguments This is input arguments of this option or help meesage about arguments.
* @param description This is description message of this option.
* @param example This is example of use string.
* @param depricatedMsg This is a message that will be printed as a warning if user will use this option. If you set this argument to empty value then warning message will be ignored and option not be marked asa a depricated. An option will be marked as a depricated when this arguments will not equal empty string.
* @param removed This option show depricatedMsg as a error and force the parseParams method return false. This option will be ignored if the depricatedMsg will be empty.
*/
OptionData(const QStringList& names,
const QString& arguments = "",
const QString& description = "",
const QString& example = "",
const QString& depricatedMsg = "",
bool removed = false);
/**
* @brief name This is name of the option. It is a required argument and cannot be empty.
* @return return name of this option.
*/
const QStringList &names() const;
/**
* @brief description This is description message of this option.
* @return return description of this option.
*/
const QString &description() const;
/**
* @brief example This is example of use string.
* @return return example if use of this option.
*/
const QString &example() const;
/**
* @brief arguments This is input arguments of this option or help meesage about arguments.
* @return return arguments of this option.
*/
const QString &arguments() const;
/**
* @brief depricatedWarning This is a message that will be printed as a warning if user will use this option. If you set this argument to empty value then warning message will be ignored and option not be marked asa a depricated. An option will be marked as a depricated when this arguments will not equal empty string.
* @note if this value is empty the option are not depricated.
* @return warning meessage of the depricated options.
*/
const QString &depricatedMsg() const;
/**
* @brief toHelp This method convert this option into help line.
* The help line have next structure :
*
* Key: {name [arguments]}
* Value: {description examples}
* @return The Help::Options set with one line.
*/
Help::Options toHelp() const;
/**
* @brief isValid This method return true if the option is valid. If option do not contain a name then it is invalid.
* @return true if the option valid else false.
*/
bool isValid() const;
/**
* @brief isRemoved This method return true if the option is removed.
* @return true if option is removed else false.
*/
bool isRemoved() const;
/**
* @brief isDepricated This method return true if this option is depricated.
* @return true if options is depricated else false
*/
bool isDepricated() const;
protected:
/**
* @brief setNames This method sets new value of the option name.
* @param newNames This is a new value of the options name.
* @note see the OptionData::name method.
*/
void setNames(const QStringList &newNames);
/**
* @brief setDescription This method sets new description of this options.
* @param newDescription This is new value of optons description
* @note See the OptionData::description method.
*/
void setDescription(const QString &newDescription);
/**
* @brief setExample This method sets a new example value of this option
* @param newExample This is a new value of the options example.
* @note See the OptionData::example method.
*/
void setExample(const QString &newExample);
/**
* @brief setArguments This method sets new value of the options arguments
* @param newArguments new value of the options arguments
* @note See the OptionData::arguments method.
*/
void setArguments(const QString &newArguments);
/**
* @brief setDepricatedMsg This method sets new value of the depricated warnning message of this option.
* @param newDepricatedMsg This is new value of the depricated message.
* @note See the OptionData::depricatedMsg method.
*/
void setDepricatedMsg(const QString &newDepricatedMsg);
private:
QStringList _name;
QString _description;
QString _example;
QString _arguments;
QString _depricatedMsg;
bool _removed;
};
/**
* @brief OptionsList is Hash map of the OptionData items. Where the key it is group name and value it is option data.
*/
typedef QMultiHash<QString, OptionData> OptionsDataList;
}
#endif // OPTIONDATA_H

@ -24,6 +24,8 @@ using namespace QuasarAppUtils;
QMap<QString, QString> Params::params = QMap<QString, QString>();
QString Params::appPath = "";
QString Params::appName = "";
Help::Section Params::userHelp = {};
OptionsDataList Params::inputOptions = {};
bool Params::isEndable(const QString& key) {
@ -55,16 +57,6 @@ void Params::log(const QString &log, VerboseLvl vLvl) {
}
}
Help::Charters Params::getParamsHelp() {
return {
{
"Base Options", {
{"-verbose (level 1 - 3)", "Shows debug log"},
{"-fileLog (path to file)", "Sets path of log file. Default it is path to executable file with suffix '.log'"},
}
}
};
}
VerboseLvl Params::getVerboseLvl() {
return static_cast<VerboseLvl>(getArg("verbose", DEFAULT_VERBOSE_LVL).toInt());
@ -83,7 +75,34 @@ bool Params::isDebugBuild() {
}
void Params::showHelp() {
Help::print(getParamsHelp());
if (inputOptions.size() > 1) {
showHelpForInputOptions();
} else {
Help::print(userHelp);
}
}
void Params::showHelpForInputOptions() {
Help::print(getHelpOfInputOptions());
}
Help::Section Params::getHelpOfInputOptions() {
if (inputOptions.size() <= 1 ) {
return {};
}
Help::Options help;
for (const auto &optionData: qAsConst(inputOptions) ) {
help.unite(optionData.toHelp());
}
return Help::Section{{"Information about using options", help}};
}
const Help::Section &Params::getHelp() {
return userHelp;
}
const QMap<QString, QString>& Params::getUserParamsMap() {
@ -104,6 +123,24 @@ QString Params::getCurrentExecutableDir() {
return appPath;
}
OptionsDataList Params::availableArguments() {
return OptionsDataList{
{
"Base Options",
OptionData{
{"-verbose"}, "(level 1 - 3)", "Shows debug log"
}
},
{
"Base Options",
OptionData{
{"-fileLog"}, "(path to file)", "Sets path of log file. Default it is path to executable file with suffix '.log'"
}
}
};
}
int Params::size() {
return params.size();
}
@ -165,22 +202,27 @@ bool Params::writeLoginFile(const QString &log, VerboseLvl vLvl) {
return true;
}
bool Params::parseParams(const int argc, const char *argv[]) {
bool Params::parseParams(const int argc, const char *argv[], const OptionsDataList& options) {
QStringList params;
for (int i = 1; i < argc; i++) {
params.push_back(argv[i]);
}
return parseParams(params);
return parseParams(params, options);
}
bool Params::parseParams(int argc, char *argv[]) {
return parseParams(argc, const_cast<const char**>(argv));
bool Params::parseParams(int argc, char *argv[], const OptionsDataList& options) {
return parseParams(argc, const_cast<const char**>(argv), options);
}
bool Params::parseParams(const QStringList &paramsArray) {
bool Params::parseParams(const QStringList &paramsArray, const OptionsDataList &options) {
params.clear();
OptionsDataList availableOptions;
parseAvailableOptions(OptionsDataList{}.unite(options).unite(availableArguments()),
&availableOptions,
&userHelp);
#ifdef Q_OS_WIN
char buffer[MAX_PATH];
@ -209,6 +251,14 @@ bool Params::parseParams(const QStringList &paramsArray) {
}
for (int i = 0 ; i < paramsArray.size(); ++i) {
auto optionData = availableOptions.value(paramsArray[i], {{}});
if (options.size() && !checkOption(optionData, paramsArray[i])) {
return false;
}
inputOptions.insert(paramsArray[i], optionData);
if (paramsArray[i][0] == '-') {
if (i < (paramsArray.size() - 1) && paramsArray[i + 1][0] != '-') {
params[paramsArray[i].mid(1)] = paramsArray[i + 1];
@ -251,6 +301,61 @@ void Params::printWorkingOptions() {
QuasarAppUtils::Debug);
}
bool Params::checkOption(const OptionData& optionData, const QString& rawOptionName) {
if (!optionData.isValid()) {
QuasarAppUtils::Params::log(QString("The '%0' option not exists!"
" You use wrong option name, please check the help before run your commnad.").arg(
rawOptionName),
QuasarAppUtils::Error);
return false;
}
if (optionData.isDepricated()) {
if (optionData.isRemoved()) {
QuasarAppUtils::Params::log(optionData.depricatedMsg(),
QuasarAppUtils::Error);
return false;
}
QuasarAppUtils::Params::log(optionData.depricatedMsg(),
QuasarAppUtils::Warning);
}
return true;
}
void Params::parseAvailableOptions(const OptionsDataList &availableOptionsListIn,
OptionsDataList *availableOptionsListOut,
Help::Section *helpOut) {
if (!(availableOptionsListOut && helpOut))
return;
helpOut->clear();
QHash<QString, Help::Options> options;
for (auto it = availableOptionsListIn.begin(); it != availableOptionsListIn.end(); ++it) {
if (availableOptionsListOut) {
for (const auto &name : qAsConst(it.value().names())) {
availableOptionsListOut->insert(name, it.value());
}
}
if (helpOut) {
options[it.key()].unite(it.value().toHelp());
}
}
for (auto it = options.begin(); it != options.end(); ++it) {
helpOut->insert(it.key(), it.value());
}
}
QString Params::getArg(const QString& key,const QString& def) {
return params.value(key, def);
}

@ -12,9 +12,11 @@
#include <QVariant>
#include "quasarapp_global.h"
#include "helpdata.h"
#include "optiondata.h"
namespace QuasarAppUtils {
/**
* @brief The VerboseLvl enum uses for sets log level.
*/
@ -41,6 +43,18 @@ enum VerboseLvl {
* This Class support next comandline arguments.
* * **-verbose** (level 1 - 3) Shows debug log
* * **-fileLog** (path to file) Sets path of log file. Default it is path to executable file with suffix '.log'
*
* ### Usage
*
* ```cpp
#include <quasarapp.h>
if (!QuasarAppUtils::Params::parseParams(argc, argv)) {
QuasarAppUtils::Params::log("Warning message", QuasarAppUtils::Warning);
QuasarAppUtils::Params::showHelp();
exit(0);
}
```
*/
class QUASARAPPSHARED_EXPORT Params
{
@ -51,24 +65,30 @@ public:
* @brief parseParams Parse input data of started application.
* @param argc Count of arguments.
* @param argv Array of arguments.
* @param options This is list of the available options for parse. See the OptionData class for more inforamtion.
* If you skip thi argument then QuasarAppLib will not check input options.
* @return true if all arguments read successful else false.
*/
static bool parseParams(const int argc, const char *argv[]);
static bool parseParams(const int argc, const char *argv[], const OptionsDataList& options = {});
/**
* @brief parseParams Parse input data of started application.
* @param argc Count of arguments.
* @param argv Array of arguments.
* @param options This is list of the available options for parse. See the OptionData class for more inforamtion.
* If you skip thi argument then QuasarAppLib will not check input options.
* @return true if all arguments read successful else false.
*/
static bool parseParams(int argc, char *argv[]);
static bool parseParams(int argc, char *argv[], const OptionsDataList& options = {});
/**
* @brief parseParams Parse input data of started application.
* @param paramsArray Arguments.
* @param options This is list of the available options for parse. See the OptionData class for more inforamtion.
* If you skip thi argument then QuasarAppLib will not check input options.
* @return true if all arguments read successful else false.
*/
static bool parseParams(const QStringList& paramsArray);
static bool parseParams(const QStringList& paramsArray, const OptionsDataList& options = {});
/**
* @brief getArg return string value of a @a key if key is exits else return a @a def value.
@ -110,13 +130,6 @@ public:
*/
static void log(const QString& log, VerboseLvl vLvl = VerboseLvl::Debug);
/**
* @brief getParamsHelp This method return help object of the params class.
* @note All Options from the Params class can be used on any application that incuded this library. So if you printing your own help do not forget print this help.
* @return help object of default params.
*/
static Help::Section getParamsHelp();
/**
* @brief getVerboseLvl This method return the verbose log level.
* @return verbose log lvl.
@ -135,7 +148,6 @@ public:
*/
static bool isDebugBuild();
/**
* @brief size This method return count of the all input arguments.
* @return size of all params array.
@ -143,10 +155,35 @@ public:
static int size();
/**
* @brief showHelp This method shows help of the Params class of the QuasarAppLib.
* @brief showHelp This method shows all help message.
*/
static void showHelp();
/**
* @brief showHelpForInputOptions This method show help for each input option.
* @note Befor using of this method invoke the parseParams method. This is needed for generate the help message.
*
* **Example:**
*
* ```bash
* myTool help option1 -option2 argumets
* ```
*/
static void showHelpForInputOptions();
/**
* @brief getHelpOfInputOptions This method return help abut input options only. Exept help and h options.
* @return help abut input options only. Exept help and h options.
*/
static Help::Section getHelpOfInputOptions();
/**
* @brief getHelp This method return options help page.
* @note Befor using of this method invoke the parseParams method. This is needed for generate the help message.
* @return help of available options.
*/
static const Help::Section& getHelp();
/**
* @brief getUserParamsMap This method return const reference to the parsed arguments map.
* @return A map object with parsed arguments.
@ -170,6 +207,12 @@ public:
*/
static QString getCurrentExecutableDir();
/**
* @brief availableArguments This method return list of the available arguments of QuasarAppLibrary
* @return list of the available arguments
*/
static OptionsDataList availableArguments();
private:
static QString timeString();
static std::string lvlToString(VerboseLvl vLvl);
@ -182,8 +225,28 @@ private:
*/
static void printWorkingOptions();
/**
* @brief checkOption return tru if the option is supported
* @param option checked option
* @return true if option is supported
*/
static bool checkOption(const OptionData &option, const QString &rawOptionName);
/**
* @brief parseAvailableOptions This is private method for parsing availabel options.
* @param availableOptionsListIn input data of the available options.
* @param availableOptionsListOut hash of available options wher key it options name and value it is options data
* @param helpOut This is help object that generated from the
*/
static void parseAvailableOptions(const OptionsDataList& availableOptionsListIn,
OptionsDataList* availableOptionsListOut,
Help::Section* helpOut);
static QMap<QString, QString> params;
static OptionsDataList inputOptions;
static Help::Section userHelp;
static QString appPath;
static QString appName;