aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2018-12-07 20:47:51 +0100
committerAqua-sama <aqua@iserlohn-fortress.net>2018-12-07 20:47:51 +0100
commit53594eabccfb7cd94f4b4d42745af1c0c21fe1ec (patch)
tree95b8543f3592fd269c3bd923aff85c1071dd3b03
parentPKGBUILD: add gpg key signing for plugins (diff)
downloadsmolbote-53594eabccfb7cd94f4b4d42745af1c0c21fe1ec.tar.xz
Configuration: parse command line after parsing config file
- Split CommandLine off Configuration
-rw-r--r--lib/configuration/commandline.cpp59
-rw-r--r--lib/configuration/commandline.h79
-rw-r--r--lib/configuration/configuration.cpp22
-rw-r--r--lib/configuration/configuration.h13
-rw-r--r--lib/configuration/meson.build2
-rw-r--r--src/browser.cpp2
-rw-r--r--src/main.cpp53
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();