diff options
-rw-r--r-- | lib/configuration/commandline.cpp | 59 | ||||
-rw-r--r-- | lib/configuration/commandline.h | 79 | ||||
-rw-r--r-- | lib/configuration/configuration.cpp | 22 | ||||
-rw-r--r-- | lib/configuration/configuration.h | 13 | ||||
-rw-r--r-- | lib/configuration/meson.build | 2 | ||||
-rw-r--r-- | src/browser.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 53 |
7 files changed, 166 insertions, 64 deletions
diff --git a/lib/configuration/commandline.cpp b/lib/configuration/commandline.cpp new file mode 100644 index 0000000..4581c84 --- /dev/null +++ b/lib/configuration/commandline.cpp @@ -0,0 +1,59 @@ +/* + * This file is part of smolbote. It's copyrighted by the contributors recorded + * in the version control history of the file, available from its original + * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#include "commandline.h" +#include "config.h" +#include <QStandardPaths> + +namespace po = boost::program_options; + +inline std::string defaultUserConfigLocation() +{ +#ifdef CONFIG_PATH_CONFIG + return CONFIG_PATH_CONFIG; +#else + // try to locate an existing config + QString path = QStandardPaths::locate(QStandardPaths::ConfigLocation, "smolbote/smolbote.cfg"); + + // it's possible there is no config, so set the path properly + if(path.isEmpty()) + path = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/smolbote/smolbote.cfg"; + + return path.toStdString(); +#endif +} + +CommandLine::CommandLine(int argc, char **argv) + : m_homePath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString()) +{ + m_description.add_options() + ("help,h", "Display command-line options list.") + ("version,v", "Display version information.") + ("build", "Display build commit.") + + ("config,c", po::value<std::string>()->default_value(defaultUserConfigLocation()), "Set the configuration file.") + ("no-remote", "Do not accept or send remote commands.") + + ("session,s", po::value<std::string>(), "Open the selected session.") + ("pick-session", "Show all available sessions and select which one to open.") + + ("args", po::value<std::vector<std::string>>(), "Command(s) and/or URL(s).") + ; + + m_arguments.add("args", -1); + + try { + auto cmd = po::command_line_parser(argc, argv); + cmd.allow_unregistered(); + cmd.options(m_description); + cmd.positional(m_arguments); + po::store(cmd.run(), vm); + } catch(const po::error &e) { + qWarning("Error parsing cmd: %s", e.what()); + } +} diff --git a/lib/configuration/commandline.h b/lib/configuration/commandline.h new file mode 100644 index 0000000..68361cb --- /dev/null +++ b/lib/configuration/commandline.h @@ -0,0 +1,79 @@ +/* + * This file is part of smolbote. It's copyrighted by the contributors recorded + * in the version control history of the file, available from its original + * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#ifndef SMOLBOTE_COMMANDLINE_H +#define SMOLBOTE_COMMANDLINE_H + +#include <QString> +#include <QStringList> +#include <boost/program_options.hpp> + +class CommandLine +{ +public: + CommandLine(int argc, char **argv); + + bool exists(const char *path) const + { + return (vm.count(path) > 0); + } + + template <typename T> + std::optional<T> value(const char *path) const + { + if(vm.count(path) == 0) { + return std::nullopt; + } + + if constexpr(std::is_same_v<T, QString>) { + return std::optional<QString>(QString::fromStdString(this->value<std::string>(path).value())); + //return std::optional<QString>(vm[path].as<const char*>()); + + } else if constexpr(std::is_same_v<T, QStringList>) { + QStringList r; + for(const std::string &item : this->value<std::vector<std::string>>(path).value()) { + r.append(QString::fromStdString(item)); + } + return std::optional<QStringList>(r); + + } else if constexpr(std::is_same_v<T, std::string>) { + + if(vm[path].value().type() == typeid(int)) { + return std::optional<std::string>(std::to_string(vm[path].as<int>())); + } + + if(vm[path].value().type() == typeid(bool)) { + return std::optional<std::string>(vm[path].as<bool>() ? "true" : "false"); + } + + std::string r = vm[path].as<std::string>(); + + // check if it's a path + if(r.front() == '~') { + r.replace(0, 1, m_homePath); + } + + return std::optional<std::string>(r); + + } else + return std::optional<T>(vm[path].as<T>()); + } + + const boost::program_options::options_description description() const + { + return m_description; + } + +private: + const std::string m_homePath; + boost::program_options::options_description m_description; + boost::program_options::positional_options_description m_arguments; + boost::program_options::variables_map vm; +}; + +#endif // SMOLBOTE_COMMANDLINE_H diff --git a/lib/configuration/configuration.cpp b/lib/configuration/configuration.cpp index 98ab20a..5ddb960 100644 --- a/lib/configuration/configuration.cpp +++ b/lib/configuration/configuration.cpp @@ -36,22 +36,6 @@ Configuration::Configuration(QObject *parent) : QObject(parent) , m_homePath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString()) { - commandLine_desc.add_options() - ("help,h", "Display command-line options list.") - ("version,v", "Display version information.") - ("build", "Display build commit.") - - ("config,c", po::value<std::string>()->default_value(defaultUserConfigLocation()), "Set the configuration file.") - ("no-remote", "Do not accept or send remote commands.") - - ("session,s", po::value<std::string>(), "Open the selected session.") - ("pick-session", "Show all available sessions and select which one to open.") - - ("args", po::value<std::vector<std::string>>(), "Command(s) and/or URL(s).") - ; - - arguments_desc.add("args", -1); - configuration_desc.add_options() ("browser.stylesheet", po::value<std::string>()) ("browser.locale", po::value<std::string>(), "Set Qt localization.") @@ -148,10 +132,8 @@ bool Configuration::parse(int argc, char **argv) { try { auto cmd = po::command_line_parser(argc, argv); - po::options_description desc; - desc.add(commandLine_desc).add(configuration_desc); - cmd.options(desc); - cmd.positional(arguments_desc); + cmd.allow_unregistered(); + cmd.options(configuration_desc); po::store(cmd.run(), vm); } catch(const po::error &e) { qWarning("Error parsing command line: %s", e.what()); diff --git a/lib/configuration/configuration.h b/lib/configuration/configuration.h index 1524536..fd18fc9 100644 --- a/lib/configuration/configuration.h +++ b/lib/configuration/configuration.h @@ -29,11 +29,6 @@ public: bool parse(const std::string &path); bool parse(int argc, char **argv); - const std::vector<boost::shared_ptr<boost::program_options::option_description>> &options() - { - return configuration_desc.options(); - } - bool exists(const char *path) { return vm.count(path) ? true : false; @@ -110,11 +105,7 @@ public: } QHash<QString, QString> section(const std::string &prefix) const; - const boost::program_options::options_description commandlineOptions() const - { - return commandLine_desc; - } - const boost::program_options::options_description configurationOptions() const + const boost::program_options::options_description description() const { return configuration_desc; } @@ -123,9 +114,7 @@ signals: void settingChanged(const std::string &path, const QString &value); private: - boost::program_options::options_description commandLine_desc; boost::program_options::options_description configuration_desc; - boost::program_options::positional_options_description arguments_desc; boost::program_options::variables_map vm; const std::string m_homePath; diff --git a/lib/configuration/meson.build b/lib/configuration/meson.build index 79daa78..e93eca9 100644 --- a/lib/configuration/meson.build +++ b/lib/configuration/meson.build @@ -4,7 +4,7 @@ configuration_moc = qt5.preprocess( dependencies: dep_qt5 ) -configuration_lib = static_library('configuration', ['configuration.cpp', configuration_moc], +configuration_lib = static_library('configuration', ['commandline.cpp', 'configuration.cpp', configuration_moc], dependencies: [dep_boost, dep_qt5, dep_genheaders] ) diff --git a/src/browser.cpp b/src/browser.cpp index 3a80439..18ccc92 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -64,7 +64,7 @@ void Browser::about() const QStringList Browser::configurationOptions() const { QStringList options; - for(const auto &option : m_config->options()) { + for(const auto &option : m_config->description().options()) { options.append(QString::fromStdString(option->long_name())); } return options; diff --git a/src/main.cpp b/src/main.cpp index e1e7618..2a0d355 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,19 +8,18 @@ #include "browser.h" #include "builtins.h" +#include "commandline.h" #include "configuration.h" #include "session/session.h" #include "session/sessiondialog.h" #include "util.h" +#include "version.h" #include <QFile> #include <QLibraryInfo> #include <QPluginLoader> #include <QTranslator> -#include <QVersionNumber> -#include <iostream> #include <memory> #include <plugininterface.h> -#include <version.h> #ifdef _WIN32 #include <cstdio> #include <windows.h> @@ -80,6 +79,17 @@ int main(int argc, char **argv) } #endif + const std::unique_ptr<CommandLine> cmd = std::make_unique<CommandLine>(argc, argv); + // --version + if(cmd->exists("version")) { + return builtins::version(); + } + + // --build + if(cmd->exists("build")) { + return builtins::build(); + } + // Disable Chromium's crash handler so breakpad can capture crashes instead. // This has to be done before QtWebEngine gets initialized. const auto chromiumFlags = qgetenv("QTWEBENGINE_CHROMIUM_FLAGS"); @@ -89,23 +99,11 @@ int main(int argc, char **argv) // create and load configuration std::unique_ptr<Configuration> config = std::make_unique<Configuration>(nullptr); - - if(!config->parse(argc, argv)) { - qWarning("Error parsing command line, check --help for usage."); - return -1; - } - if(!config->parse(config->value<std::string>("config").value())) { + if(!config->parse(cmd->value<std::string>("config").value())) { qWarning("Error parsing config file."); } - - // --version - if(config->exists("version")) { - return builtins::version(); - } - - // --build - if(config->exists("build")) { - return builtins::build(); + if(!config->parse(argc, argv)) { + qWarning("Error parsing command line."); } QVector<QPluginLoader *> plugins; @@ -129,9 +127,8 @@ int main(int argc, char **argv) } } - if(config->exists("help")) { - - return builtins::help(argv[0], config->commandlineOptions(), config->configurationOptions(), pluginCommands); + if(cmd->exists("help")) { + return builtins::help(argv[0], cmd->description(), config->description(), pluginCommands); } // argc, argv, allowSecondary @@ -179,18 +176,14 @@ int main(int argc, char **argv) delete translator; } - // command line arguments - const bool isStandalone = config->exists("no-remote"); - const auto arguments = config->value<std::vector<std::string>>("args"); - const bool pickSession = config->exists("pick-session"); - const auto session = config->value<QString>("session"); + const bool isStandalone = cmd->exists("no-remote"); const auto profile = config->value<QString>("profile.default"); - app.setConfiguration(config); + app.setConfiguration(config); // app takes ownership of config app.setup(plugins); QStringList urls; - if(arguments) { + if(const auto arguments = cmd->value<std::vector<std::string>>("args")) { for(const auto &u : arguments.value()) { if(pluginCommands.contains(QString::fromStdString(u))) { return pluginCommands.value(QString::fromStdString(u))(); @@ -214,13 +207,13 @@ int main(int argc, char **argv) { QJsonObject sessionData; - if(pickSession) { + if(cmd->exists("pick-session")) { auto *dlg = new SessionDialog(); if(const auto pick = dlg->pickSession()) sessionData = pick.value(); else sessionData = Session::fromCommandLine(profile.value(), urls); - } else if(session) { + } else if(const auto session = cmd->value<QString>("session")) { QFile sessionJson(session.value()); if(sessionJson.open(QIODevice::ReadOnly | QIODevice::Text)) { sessionData = QJsonDocument::fromJson(sessionJson.readAll()).object(); |