From 7167ce41b61d2ba2cdb526777a4233eb84a3b66a Mon Sep 17 00:00:00 2001 From: Unit 193 Date: Sat, 6 Dec 2014 17:33:25 -0500 Subject: Imported Upstream version 2.99.6 --- SQLiteStudio3/sqlitestudiocli/clicommandsyntax.cpp | 433 +++++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 SQLiteStudio3/sqlitestudiocli/clicommandsyntax.cpp (limited to 'SQLiteStudio3/sqlitestudiocli/clicommandsyntax.cpp') diff --git a/SQLiteStudio3/sqlitestudiocli/clicommandsyntax.cpp b/SQLiteStudio3/sqlitestudiocli/clicommandsyntax.cpp new file mode 100644 index 0000000..732b0f0 --- /dev/null +++ b/SQLiteStudio3/sqlitestudiocli/clicommandsyntax.cpp @@ -0,0 +1,433 @@ +#include "clicommandsyntax.h" +#include "commands/clicommand.h" +#include "commands/clicommandfactory.h" +#include "cli.h" +#include + +CliCommandSyntax::CliCommandSyntax() +{ +} + +CliCommandSyntax::~CliCommandSyntax() +{ + foreach (Argument* arg, arguments) + delete arg; + + arguments.clear(); + argumentMap.clear(); + + foreach (Option* opt, options) + delete opt; + + optionMap.clear(); + optionsLongNameMap.clear(); + optionsShortNameMap.clear(); + options.clear(); +} + +void CliCommandSyntax::addArgument(int id, const QString& name, bool mandatory) +{ + addArgumentInternal(id, {name}, mandatory, Argument::REGULAR); +} + +void CliCommandSyntax::addStrictArgument(int id, const QStringList& values, bool mandatory) +{ + addArgumentInternal(id, values, mandatory, Argument::STRICT); +} + +void CliCommandSyntax::addAlternatedArgument(int id, const QStringList& names, bool mandatory) +{ + addArgumentInternal(id, names, mandatory, Argument::ALTERNATED); +} + +void CliCommandSyntax::addOptionShort(int id, const QString& shortName) +{ + addOptionInternal(id, shortName, QString(), QString()); +} + +void CliCommandSyntax::addOptionLong(int id, const QString& longName) +{ + addOptionInternal(id, QString(), longName, QString()); +} + +void CliCommandSyntax::addOption(int id, const QString& shortName, const QString& longName) +{ + addOptionInternal(id, shortName, longName, QString()); +} + +void CliCommandSyntax::addOptionWithArgShort(int id, const QString& shortName, const QString& argName) +{ + addOptionInternal(id, shortName, QString(), argName); +} + +void CliCommandSyntax::addOptionWithArgLong(int id, const QString& longName, const QString& argName) +{ + addOptionInternal(id, QString(), longName, argName); +} + +void CliCommandSyntax::addOptionWithArg(int id, const QString& shortName, const QString& longName, const QString& argName) +{ + addOptionInternal(id, shortName, longName, argName); +} + +CliCommandSyntax::Argument* CliCommandSyntax::addArgumentInternal(int id, const QStringList& names, bool mandatory, Argument::Type type) +{ + checkNewArgument(mandatory); + + Argument* arg = new Argument; + arg->mandatory = mandatory; + arg->id = id; + arg->type = type; + arg->names = names; + arguments << arg; + argumentMap[id] = arg; + return arg; +} + +CliCommandSyntax::Option* CliCommandSyntax::addOptionInternal(int id, const QString& shortName, const QString& longName, const QString& argName) +{ + Option* opt = new Option; + opt->shortName = shortName; + opt->longName = longName; + opt->id = id; + opt->argName = argName; + optionMap[id] = opt; + options << opt; + optionsShortNameMap[shortName] = opt; + optionsLongNameMap[longName] = opt; + return opt; +} + +bool CliCommandSyntax::getStrictArgumentCount() const +{ + return strictArgumentCount; +} + +void CliCommandSyntax::setStrictArgumentCount(bool value) +{ + strictArgumentCount = value; +} + +bool CliCommandSyntax::parse(const QStringList& args) +{ + pastOptions = (options.size() == 0); + lastParsedOption = nullptr; + QString arg; + bool res = false; + int argCnt = args.size(); + for (int argIdx = 0; argIdx < argCnt; argIdx++) + { + arg = args[argIdx]; + + if (arg == "--help") + { + CliCommand* help = CliCommandFactory::getCommand("help"); + help->setup(CLI::getInstance()); + help->parseArgs({getName()}); + help->execute(); + return false; + } + else if (pastOptions) + { + res = parseArg(arg); + } + else if (arg == "--") + { + pastOptions = true; + res = true; + } + else if (arg.startsWith("-")) + { + res = parseOpt(arg, args, argIdx); + } + else + { + pastOptions = true; + res = parseArg(arg); + } + + if (!res) + return false; + } + + if (strictArgumentCount && argPosition < requiredArguments()) + { + parsingErrorText = QObject::tr("Insufficient number of arguments."); + return false; + } + + return true; +} + +QString CliCommandSyntax::getErrorText() const +{ + return parsingErrorText; +} + +QStringList CliCommandSyntax::getStrictArgumentCandidates() +{ + QStringList results; + if (!pastOptions) + { + if (lastParsedOption && !lastParsedOption->argName.isEmpty()) + return results; // this case is covered by getRegularArgumentCandidates() + + foreach (Option* opt, options) + { + if (opt->requested) + continue; + + if (!opt->shortName.isEmpty()) + results << "-"+opt->shortName; + + if (!opt->longName.isEmpty()) + results << "--"+opt->longName; + } + results << "--"; + } + + if (argPosition < arguments.size() && arguments[argPosition]->type == Argument::STRICT) + results += arguments[argPosition]->names; + + return results; +} + +QList CliCommandSyntax::getRegularArgumentCandidates() +{ + QList results; + + if (!pastOptions && lastParsedOption && !lastParsedOption->argName.isEmpty()) + { + // We're exactly at the spot where the option argument is expected + results << lastParsedOption->id; + return results; + } + + if (argPosition < arguments.size()) + { + switch (arguments[argPosition]->type) + { + case Argument::REGULAR: + case Argument::ALTERNATED: + results << arguments[argPosition]->id; + break; + case Argument::STRICT: + break; + } + } + + return results; +} + +void CliCommandSyntax::addAlias(const QString& alias) +{ + aliases << alias; +} + +QStringList CliCommandSyntax::getAliases() const +{ + return aliases; +} + +QString CliCommandSyntax::getSyntaxDefinition() const +{ + return getSyntaxDefinition(name); +} + +QString CliCommandSyntax::getSyntaxDefinition(const QString& usedName) const +{ + static const QString mandatoryArgTempl = "<%1>"; + static const QString optionalArgTempl = "[<%1>]"; + static const QString mandatoryStrictTempl = "%1"; + static const QString optionalStrictTempl = "[%1]"; + static const QString optionTempl = "[%1]"; + static const QString optionWithArgTempl = "[%1 <%2>]"; + + QStringList words; + words << usedName; + + QString optName; + QStringList optNameParts; + foreach (Option* opt, options) + { + optNameParts.clear();; + if (!opt->shortName.isEmpty()) + optNameParts << "-"+opt->shortName; + + if (!opt->longName.isEmpty()) + optNameParts += "--"+opt->longName; + + optName = optNameParts.join("|"); + + words << (opt->argName.isEmpty() ? optionTempl.arg(optName) : optionWithArgTempl.arg(optName).arg(opt->argName)); + } + + QString templ; + QString argName; + foreach (Argument* arg, arguments) + { + templ = (arg->mandatory ? mandatoryArgTempl : optionalArgTempl); + switch (arg->type) + { + case CliCommandSyntax::Argument::ALTERNATED: + argName = arg->names.join("|"); + break; + case CliCommandSyntax::Argument::REGULAR: + argName = arg->names.first(); + break; + case CliCommandSyntax::Argument::STRICT: + argName = arg->names.join("|"); + templ = (arg->mandatory ? mandatoryStrictTempl : optionalStrictTempl); + break; + } + words << templ.arg(argName); + } + + return words.join(" "); +} + +bool CliCommandSyntax::isArgumentSet(int id) const +{ + if (!argumentMap.contains(id)) + return false; + + return argumentMap[id]->defined; +} + +QString CliCommandSyntax::getArgument(int id) const +{ + if (!argumentMap.contains(id)) + return QString::null; + + return argumentMap[id]->value; +} + +bool CliCommandSyntax::isOptionSet(int id) const +{ + if (!optionMap.contains(id)) + return false; + + return optionMap[id]->requested; +} + +QString CliCommandSyntax::getOptionValue(int id) const +{ + if (!optionMap.contains(id)) + return QString::null; + + return optionMap[id]->value; +} + +bool CliCommandSyntax::parseArg(const QString& arg) +{ + if (strictArgumentCount && arguments.size() < (argPosition + 1)) + { + parsingErrorText = QObject::tr("Too many arguments."); + return false; + } + + switch (arguments[argPosition]->type) + { + case CliCommandSyntax::Argument::ALTERNATED: + { + arguments[argPosition]->value = arg; + arguments[argPosition]->defined = true; + break; + } + case CliCommandSyntax::Argument::REGULAR: + { + arguments[argPosition]->value = arg; + arguments[argPosition]->defined = true; + break; + } + case CliCommandSyntax::Argument::STRICT: + { + if (!arguments[argPosition]->names.contains(arg)) + { + parsingErrorText = QObject::tr("Invalid argument value: %1.\nExpected one of: %2").arg(arg) + .arg(arguments[argPosition]->names.join(", ")); + + return false; + } + arguments[argPosition]->value = arg; + arguments[argPosition]->defined = true; + break; + } + default: + qCritical() << "Invalid argument type in CliCommandSyntax:" << arguments[argPosition]->type; + return false; + } + + argPosition++; + return true; +} + +bool CliCommandSyntax::parseOpt(const QString& arg, const QStringList& args, int& argIdx) +{ + Option* opt = nullptr; + if (arg.startsWith("--")) + { + QString longName = arg.mid(2); + if (optionsLongNameMap.contains(longName)) + opt = optionsLongNameMap.value(longName); + } + else + { + QString shortName = arg.mid(1); + if (optionsShortNameMap.contains(shortName)) + opt = optionsShortNameMap.value(shortName); + } + + if (!opt) + { + parsingErrorText = QObject::tr("Unknown option: %1", "CLI command syntax").arg(arg); + return false; + } + + opt->requested = true; + lastParsedOption = opt; + + if (!opt->argName.isEmpty()) + { + if (args.size() <= (argIdx + 1)) + { + parsingErrorText = QObject::tr("Option %1 requires an argument.", "CLI command syntax").arg(arg); + return false; + } + + argIdx++; + opt->value = args[argIdx]; + } + return true; +} + +int CliCommandSyntax::requiredArguments() const +{ + int cnt = 0; + foreach (Argument* arg, arguments) + { + if (arg->mandatory) + cnt++; + } + return cnt; +} + +void CliCommandSyntax::checkNewArgument(bool mandatory) +{ + if (arguments.size() > 0 && !arguments.last()->mandatory && mandatory) + { + qWarning() << "Adding mandatory CLI command argument after optional argument. This will result in invalid syntax definition. The command is:" + << this->name; + } +} + +QString CliCommandSyntax::getName() const +{ + return name; +} + +void CliCommandSyntax::setName(const QString& value) +{ + name = value; +} + -- cgit v1.2.3