aboutsummaryrefslogtreecommitdiff
path: root/launcher
diff options
context:
space:
mode:
authorSefa Eyeoglu <contact@scrumplex.net>2022-09-26 12:30:49 +0200
committerSefa Eyeoglu <contact@scrumplex.net>2022-09-26 13:21:27 +0200
commit1cdadafdf8b59988fb8d89a29d0698620e09dfb5 (patch)
treeb0213172f07fe046aaa709d6299ff268a1c6b0cd /launcher
parent58a5331f7bafb149c18f560a0363daab65521262 (diff)
downloadPrismLauncher-1cdadafdf8b59988fb8d89a29d0698620e09dfb5.tar.gz
PrismLauncher-1cdadafdf8b59988fb8d89a29d0698620e09dfb5.tar.bz2
PrismLauncher-1cdadafdf8b59988fb8d89a29d0698620e09dfb5.zip
refactor: use QCommandLineParser instead
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
Diffstat (limited to 'launcher')
-rw-r--r--launcher/Application.cpp97
-rw-r--r--launcher/Commandline.cpp408
-rw-r--r--launcher/Commandline.h213
3 files changed, 21 insertions, 697 deletions
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index 0d1db11c..7ac36e71 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -78,6 +78,7 @@
#include <iostream>
#include <QAccessible>
+#include <QCommandLineParser>
#include <QDir>
#include <QFileInfo>
#include <QNetworkAccessManager>
@@ -110,7 +111,6 @@
#include "translations/TranslationsModel.h"
#include "meta/Index.h"
-#include <Commandline.h>
#include <FileSystem.h>
#include <DesktopServices.h>
#include <LocalPeer.h>
@@ -136,8 +136,6 @@
static const QLatin1String liveCheckFile("live.check");
-using namespace Commandline;
-
#define MACOS_HINT "If you are on macOS Sierra, you might have to move the app to your /Applications or ~/Applications folder. "\
"This usually fixes the problem and you can move the application elsewhere afterwards.\n"\
"\n"
@@ -242,80 +240,27 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
this->setQuitOnLastWindowClosed(false);
// Commandline parsing
- QHash<QString, QVariant> args;
- {
- Parser parser(FlagStyle::GNU, ArgumentStyle::SpaceAndEquals);
-
- // --help
- parser.addSwitch("help");
- parser.addShortOpt("help", 'h');
- parser.addDocumentation("help", "Display this help and exit.");
- // --version
- parser.addSwitch("version");
- parser.addShortOpt("version", 'V');
- parser.addDocumentation("version", "Display program version and exit.");
- // --dir
- parser.addOption("dir");
- parser.addShortOpt("dir", 'd');
- parser.addDocumentation("dir", "Use the supplied folder as application root instead of the binary location (use '.' for current)");
- // --launch
- parser.addOption("launch");
- parser.addShortOpt("launch", 'l');
- parser.addDocumentation("launch", "Launch the specified instance (by instance ID)");
- // --server
- parser.addOption("server");
- parser.addShortOpt("server", 's');
- parser.addDocumentation("server", "Join the specified server on launch (only valid in combination with --launch)");
- // --profile
- parser.addOption("profile");
- parser.addShortOpt("profile", 'a');
- parser.addDocumentation("profile", "Use the account specified by its profile name (only valid in combination with --launch)");
- // --alive
- parser.addSwitch("alive");
- parser.addDocumentation("alive", "Write a small '" + liveCheckFile + "' file after the launcher starts");
- // --import
- parser.addOption("import");
- parser.addShortOpt("import", 'I');
- parser.addDocumentation("import", "Import instance from specified zip (local path or URL)");
-
- // parse the arguments
- try
- {
- args = parser.parse(arguments());
- }
- catch (const ParsingError &e)
- {
- std::cerr << "CommandLineError: " << e.what() << std::endl;
- if(argc > 0)
- std::cerr << "Try '" << argv[0] << " -h' to get help on command line parameters."
- << std::endl;
- m_status = Application::Failed;
- return;
- }
-
- // display help and exit
- if (args["help"].toBool())
- {
- std::cout << qPrintable(parser.compileHelp(arguments()[0]));
- m_status = Application::Succeeded;
- return;
- }
+ QCommandLineParser parser;
+ parser.setApplicationDescription(BuildConfig.LAUNCHER_NAME);
+
+ parser.addOptions({
+ {{"d", "dir"}, "Use a custom path as application root (use '.' for current directory)", "directory"},
+ {{"l", "launch"}, "Launch the specified instance (by instance ID)", "instance"},
+ {{"s", "server"}, "Join the specified server on launch (only valid in combination with --launch)", "address"},
+ {{"a", "profile"}, "Use the account specified by its profile name (only valid in combination with --launch)", "profile"},
+ {"alive", "Write a small '" + liveCheckFile + "' file after the launcher starts"},
+ {{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"}
+ });
+ parser.addHelpOption();
+ parser.addVersionOption();
- // display version and exit
- if (args["version"].toBool())
- {
- std::cout << "Version " << BuildConfig.printableVersionString().toStdString() << std::endl;
- std::cout << "Git " << BuildConfig.GIT_COMMIT.toStdString() << std::endl;
- m_status = Application::Succeeded;
- return;
- }
- }
+ parser.process(arguments());
- m_instanceIdToLaunch = args["launch"].toString();
- m_serverToJoin = args["server"].toString();
- m_profileToUse = args["profile"].toString();
- m_liveCheck = args["alive"].toBool();
- m_zipToImport = args["import"].toUrl();
+ m_instanceIdToLaunch = parser.value("launch");
+ m_serverToJoin = parser.value("server");
+ m_profileToUse = parser.value("profile");
+ m_liveCheck = parser.isSet("alive");
+ m_zipToImport = parser.value("import");
// error if --launch is missing with --server or --profile
if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty())
@@ -346,7 +291,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
QString adjustedBy;
QString dataPath;
// change folder
- QString dirParam = args["dir"].toString();
+ QString dirParam = parser.value("dir");
if (!dirParam.isEmpty())
{
// the dir param. it makes multimc data path point to whatever the user specified
diff --git a/launcher/Commandline.cpp b/launcher/Commandline.cpp
index 8e7356bb..6d97918d 100644
--- a/launcher/Commandline.cpp
+++ b/launcher/Commandline.cpp
@@ -92,412 +92,4 @@ QStringList splitArgs(QString args)
argv << current;
return argv;
}
-
-Parser::Parser(FlagStyle::Enum flagStyle, ArgumentStyle::Enum argStyle)
-{
- m_flagStyle = flagStyle;
- m_argStyle = argStyle;
-}
-
-// styles setter/getter
-void Parser::setArgumentStyle(ArgumentStyle::Enum style)
-{
- m_argStyle = style;
-}
-ArgumentStyle::Enum Parser::argumentStyle()
-{
- return m_argStyle;
-}
-
-void Parser::setFlagStyle(FlagStyle::Enum style)
-{
- m_flagStyle = style;
-}
-FlagStyle::Enum Parser::flagStyle()
-{
- return m_flagStyle;
-}
-
-// setup methods
-void Parser::addSwitch(QString name, bool def)
-{
- if (m_params.contains(name))
- throw "Name not unique";
-
- OptionDef *param = new OptionDef;
- param->type = otSwitch;
- param->name = name;
- param->metavar = QString("<%1>").arg(name);
- param->def = def;
-
- m_options[name] = param;
- m_params[name] = (CommonDef *)param;
- m_optionList.append(param);
-}
-
-void Parser::addOption(QString name, QVariant def)
-{
- if (m_params.contains(name))
- throw "Name not unique";
-
- OptionDef *param = new OptionDef;
- param->type = otOption;
- param->name = name;
- param->metavar = QString("<%1>").arg(name);
- param->def = def;
-
- m_options[name] = param;
- m_params[name] = (CommonDef *)param;
- m_optionList.append(param);
-}
-
-void Parser::addArgument(QString name, bool required, QVariant def)
-{
- if (m_params.contains(name))
- throw "Name not unique";
-
- PositionalDef *param = new PositionalDef;
- param->name = name;
- param->def = def;
- param->required = required;
- param->metavar = name;
-
- m_positionals.append(param);
- m_params[name] = (CommonDef *)param;
-}
-
-void Parser::addDocumentation(QString name, QString doc, QString metavar)
-{
- if (!m_params.contains(name))
- throw "Name does not exist";
-
- CommonDef *param = m_params[name];
- param->doc = doc;
- if (!metavar.isNull())
- param->metavar = metavar;
-}
-
-void Parser::addShortOpt(QString name, QChar flag)
-{
- if (!m_params.contains(name))
- throw "Name does not exist";
- if (!m_options.contains(name))
- throw "Name is not an Option or Swtich";
-
- OptionDef *param = m_options[name];
- m_flags[flag] = param;
- param->flag = flag;
-}
-
-// help methods
-QString Parser::compileHelp(QString progName, int helpIndent, bool useFlags)
-{
- QStringList help;
- help << compileUsage(progName, useFlags) << "\r\n";
-
- // positionals
- if (!m_positionals.isEmpty())
- {
- help << "\r\n";
- help << "Positional arguments:\r\n";
- QListIterator<PositionalDef *> it2(m_positionals);
- while (it2.hasNext())
- {
- PositionalDef *param = it2.next();
- help << " " << param->metavar;
- help << " " << QString(helpIndent - param->metavar.length() - 1, ' ');
- help << param->doc << "\r\n";
- }
- }
-
- // Options
- if (!m_optionList.isEmpty())
- {
- help << "\r\n";
- QString optPrefix, flagPrefix;
- getPrefix(optPrefix, flagPrefix);
-
- help << "Options & Switches:\r\n";
- QListIterator<OptionDef *> it(m_optionList);
- while (it.hasNext())
- {
- OptionDef *option = it.next();
- help << " ";
- int nameLength = optPrefix.length() + option->name.length();
- if (!option->flag.isNull())
- {
- nameLength += 3 + flagPrefix.length();
- help << flagPrefix << option->flag << ", ";
- }
- help << optPrefix << option->name;
- if (option->type == otOption)
- {
- QString arg = QString("%1%2").arg(
- ((m_argStyle == ArgumentStyle::Equals) ? "=" : " "), option->metavar);
- nameLength += arg.length();
- help << arg;
- }
- help << " " << QString(helpIndent - nameLength - 1, ' ');
- help << option->doc << "\r\n";
- }
- }
-
- return help.join("");
-}
-
-QString Parser::compileUsage(QString progName, bool useFlags)
-{
- QStringList usage;
- usage << "Usage: " << progName;
-
- QString optPrefix, flagPrefix;
- getPrefix(optPrefix, flagPrefix);
-
- // options
- QListIterator<OptionDef *> it(m_optionList);
- while (it.hasNext())
- {
- OptionDef *option = it.next();
- usage << " [";
- if (!option->flag.isNull() && useFlags)
- usage << flagPrefix << option->flag;
- else
- usage << optPrefix << option->name;
- if (option->type == otOption)
- usage << ((m_argStyle == ArgumentStyle::Equals) ? "=" : " ") << option->metavar;
- usage << "]";
- }
-
- // arguments
- QListIterator<PositionalDef *> it2(m_positionals);
- while (it2.hasNext())
- {
- PositionalDef *param = it2.next();
- usage << " " << (param->required ? "<" : "[");
- usage << param->metavar;
- usage << (param->required ? ">" : "]");
- }
-
- return usage.join("");
-}
-
-// parsing
-QHash<QString, QVariant> Parser::parse(QStringList argv)
-{
- QHash<QString, QVariant> map;
-
- QStringListIterator it(argv);
- QString programName = it.next();
-
- QString optionPrefix;
- QString flagPrefix;
- QListIterator<PositionalDef *> positionals(m_positionals);
- QStringList expecting;
-
- getPrefix(optionPrefix, flagPrefix);
-
- while (it.hasNext())
- {
- QString arg = it.next();
-
- if (!expecting.isEmpty())
- // we were expecting an argument
- {
- QString name = expecting.first();
-/*
- if (map.contains(name))
- throw ParsingError(
- QString("Option %2%1 was given multiple times").arg(name, optionPrefix));
-*/
- map[name] = QVariant(arg);
-
- expecting.removeFirst();
- continue;
- }
-
- if (arg.startsWith(optionPrefix))
- // we have an option
- {
- // qDebug("Found option %s", qPrintable(arg));
-
- QString name = arg.mid(optionPrefix.length());
- QString equals;
-
- if ((m_argStyle == ArgumentStyle::Equals ||
- m_argStyle == ArgumentStyle::SpaceAndEquals) &&
- name.contains("="))
- {
- int i = name.indexOf("=");
- equals = name.mid(i + 1);
- name = name.left(i);
- }
-
- if (m_options.contains(name))
- {
- /*
- if (map.contains(name))
- throw ParsingError(QString("Option %2%1 was given multiple times")
- .arg(name, optionPrefix));
-*/
- OptionDef *option = m_options[name];
- if (option->type == otSwitch)
- map[name] = true;
- else // if (option->type == otOption)
- {
- if (m_argStyle == ArgumentStyle::Space)
- expecting.append(name);
- else if (!equals.isNull())
- map[name] = equals;
- else if (m_argStyle == ArgumentStyle::SpaceAndEquals)
- expecting.append(name);
- else
- throw ParsingError(QString("Option %2%1 reqires an argument.")
- .arg(name, optionPrefix));
- }
-
- continue;
- }
-
- throw ParsingError(QString("Unknown Option %2%1").arg(name, optionPrefix));
- }
-
- if (arg.startsWith(flagPrefix))
- // we have (a) flag(s)
- {
- // qDebug("Found flags %s", qPrintable(arg));
-
- QString flags = arg.mid(flagPrefix.length());
- QString equals;
-
- if ((m_argStyle == ArgumentStyle::Equals ||
- m_argStyle == ArgumentStyle::SpaceAndEquals) &&
- flags.contains("="))
- {
- int i = flags.indexOf("=");
- equals = flags.mid(i + 1);
- flags = flags.left(i);
- }
-
- for (int i = 0; i < flags.length(); i++)
- {
- QChar flag = flags.at(i);
-
- if (!m_flags.contains(flag))
- throw ParsingError(QString("Unknown flag %2%1").arg(flag, flagPrefix));
-
- OptionDef *option = m_flags[flag];
-/*
- if (map.contains(option->name))
- throw ParsingError(QString("Option %2%1 was given multiple times")
- .arg(option->name, optionPrefix));
-*/
- if (option->type == otSwitch)
- map[option->name] = true;
- else // if (option->type == otOption)
- {
- if (m_argStyle == ArgumentStyle::Space)
- expecting.append(option->name);
- else if (!equals.isNull())
- if (i == flags.length() - 1)
- map[option->name] = equals;
- else
- throw ParsingError(QString("Flag %4%2 of Argument-requiring Option "
- "%1 not last flag in %4%3")
- .arg(option->name, flag, flags, flagPrefix));
- else if (m_argStyle == ArgumentStyle::SpaceAndEquals)
- expecting.append(option->name);
- else
- throw ParsingError(QString("Option %1 reqires an argument. (flag %3%2)")
- .arg(option->name, flag, flagPrefix));
- }
- }
-
- continue;
- }
-
- // must be a positional argument
- if (!positionals.hasNext())
- throw ParsingError(QString("Don't know what to do with '%1'").arg(arg));
-
- PositionalDef *param = positionals.next();
-
- map[param->name] = arg;
- }
-
- // check if we're missing something
- if (!expecting.isEmpty())
- throw ParsingError(QString("Was still expecting arguments for %2%1").arg(
- expecting.join(QString(", ") + optionPrefix), optionPrefix));
-
- while (positionals.hasNext())
- {
- PositionalDef *param = positionals.next();
- if (param->required)
- throw ParsingError(
- QString("Missing required positional argument '%1'").arg(param->name));
- else
- map[param->name] = param->def;
- }
-
- // fill out gaps
- QListIterator<OptionDef *> iter(m_optionList);
- while (iter.hasNext())
- {
- OptionDef *option = iter.next();
- if (!map.contains(option->name))
- map[option->name] = option->def;
- }
-
- return map;
-}
-
-// clear defs
-void Parser::clear()
-{
- m_flags.clear();
- m_params.clear();
- m_options.clear();
-
- QMutableListIterator<OptionDef *> it(m_optionList);
- while (it.hasNext())
- {
- OptionDef *option = it.next();
- it.remove();
- delete option;
- }
-
- QMutableListIterator<PositionalDef *> it2(m_positionals);
- while (it2.hasNext())
- {
- PositionalDef *arg = it2.next();
- it2.remove();
- delete arg;
- }
-}
-
-// Destructor
-Parser::~Parser()
-{
- clear();
-}
-
-// getPrefix
-void Parser::getPrefix(QString &opt, QString &flag)
-{
- if (m_flagStyle == FlagStyle::Windows)
- opt = flag = "/";
- else if (m_flagStyle == FlagStyle::Unix)
- opt = flag = "-";
- // else if (m_flagStyle == FlagStyle::GNU)
- else
- {
- opt = "--";
- flag = "-";
- }
-}
-
-// ParsingError
-ParsingError::ParsingError(const QString &what) : std::runtime_error(what.toStdString())
-{
-}
}
diff --git a/launcher/Commandline.h b/launcher/Commandline.h
index a4e7aa61..8bd79180 100644
--- a/launcher/Commandline.h
+++ b/launcher/Commandline.h
@@ -17,12 +17,7 @@
#pragma once
-#include <exception>
-#include <stdexcept>
-
#include <QString>
-#include <QVariant>
-#include <QHash>
#include <QStringList>
/**
@@ -39,212 +34,4 @@ namespace Commandline
* @return a QStringList containing all arguments
*/
QStringList splitArgs(QString args);
-
-/**
- * @brief The FlagStyle enum
- * Specifies how flags are decorated
- */
-
-namespace FlagStyle
-{
-enum Enum
-{
- GNU, /**< --option and -o (GNU Style) */
- Unix, /**< -option and -o (Unix Style) */
- Windows, /**< /option and /o (Windows Style) */
-#ifdef Q_OS_WIN32
- Default = Windows
-#else
- Default = GNU
-#endif
-};
-}
-
-/**
- * @brief The ArgumentStyle enum
- */
-namespace ArgumentStyle
-{
-enum Enum
-{
- Space, /**< --option value */
- Equals, /**< --option=value */
- SpaceAndEquals, /**< --option[= ]value */
-#ifdef Q_OS_WIN32
- Default = Equals
-#else
- Default = SpaceAndEquals
-#endif
-};
-}
-
-/**
- * @brief The ParsingError class
- */
-class ParsingError : public std::runtime_error
-{
-public:
- ParsingError(const QString &what);
-};
-
-/**
- * @brief The Parser class
- */
-class Parser
-{
-public:
- /**
- * @brief Parser constructor
- * @param flagStyle the FlagStyle to use in this Parser
- * @param argStyle the ArgumentStyle to use in this Parser
- */
- Parser(FlagStyle::Enum flagStyle = FlagStyle::Default,
- ArgumentStyle::Enum argStyle = ArgumentStyle::Default);
-
- /**
- * @brief set the flag style
- * @param style
- */
- void setFlagStyle(FlagStyle::Enum style);
-
- /**
- * @brief get the flag style
- * @return
- */
- FlagStyle::Enum flagStyle();
-
- /**
- * @brief set the argument style
- * @param style
- */
- void setArgumentStyle(ArgumentStyle::Enum style);
-
- /**
- * @brief get the argument style
- * @return
- */
- ArgumentStyle::Enum argumentStyle();
-
- /**
- * @brief define a boolean switch
- * @param name the parameter name
- * @param def the default value
- */
- void addSwitch(QString name, bool def = false);
-
- /**
- * @brief define an option that takes an additional argument
- * @param name the parameter name
- * @param def the default value
- */
- void addOption(QString name, QVariant def = QVariant());
-
- /**
- * @brief define a positional argument
- * @param name the parameter name
- * @param required wether this argument is required
- * @param def the default value
- */
- void addArgument(QString name, bool required = true, QVariant def = QVariant());
-
- /**
- * @brief adds a flag to an existing parameter
- * @param name the (existing) parameter name
- * @param flag the flag character
- * @see addSwitch addArgument addOption
- * Note: any one parameter can only have one flag
- */
- void addShortOpt(QString name, QChar flag);
-
- /**
- * @brief adds documentation to a Parameter
- * @param name the parameter name
- * @param metavar a string to be displayed as placeholder for the value
- * @param doc a QString containing the documentation
- * Note: on positional arguments, metavar replaces the name as displayed.
- * on options , metavar replaces the value placeholder
- */
- void addDocumentation(QString name, QString doc, QString metavar = QString());
-
- /**
- * @brief generate a help message
- * @param progName the program name to use in the help message
- * @param helpIndent how much the parameter documentation should be indented
- * @param flagsInUsage whether we should use flags instead of options in the usage
- * @return a help message
- */
- QString compileHelp(QString progName, int helpIndent = 22, bool flagsInUsage = true);
-
- /**
- * @brief generate a short usage message
- * @param progName the program name to use in the usage message
- * @param useFlags whether we should use flags instead of options
- * @return a usage message
- */
- QString compileUsage(QString progName, bool useFlags = true);
-
- /**
- * @brief parse
- * @param argv a QStringList containing the program ARGV
- * @return a QHash mapping argument names to their values
- */
- QHash<QString, QVariant> parse(QStringList argv);
-
- /**
- * @brief clear all definitions
- */
- void clear();
-
- ~Parser();
-
-private:
- FlagStyle::Enum m_flagStyle;
- ArgumentStyle::Enum m_argStyle;
-
- enum OptionType
- {
- otSwitch,
- otOption
- };
-
- // Important: the common part MUST BE COMMON ON ALL THREE structs
- struct CommonDef
- {
- QString name;
- QString doc;
- QString metavar;
- QVariant def;
- };
-
- struct OptionDef
- {
- // common
- QString name;
- QString doc;
- QString metavar;
- QVariant def;
- // option
- OptionType type;
- QChar flag;
- };
-
- struct PositionalDef
- {
- // common
- QString name;
- QString doc;
- QString metavar;
- QVariant def;
- // positional
- bool required;
- };
-
- QHash<QString, OptionDef *> m_options;
- QHash<QChar, OptionDef *> m_flags;
- QHash<QString, CommonDef *> m_params;
- QList<PositionalDef *> m_positionals;
- QList<OptionDef *> m_optionList;
-
- void getPrefix(QString &opt, QString &flag);
-};
}