aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2019-10-22 10:35:37 +0300
committerAqua-sama <aqua@iserlohn-fortress.net>2019-10-22 10:35:37 +0300
commitc72b2de3794c7c5100cc8e007b3c199a2f237fe6 (patch)
treeefa0370529cc128b36c00364d2fc950b1496ec45 /src
parentImprove meson.build files (diff)
downloadsmolbote-c72b2de3794c7c5100cc8e007b3c199a2f237fe6.tar.xz
Use github.com/Taywee/args to parse command line
- This adds 3rd-party/args/args.git subrepository
Diffstat (limited to 'src')
-rw-r--r--src/builtins.cpp27
-rw-r--r--src/builtins.h5
-rw-r--r--src/main.cpp120
-rw-r--r--src/meson.build2
4 files changed, 91 insertions, 63 deletions
diff --git a/src/builtins.cpp b/src/builtins.cpp
index 55bdc31..1af2dc8 100644
--- a/src/builtins.cpp
+++ b/src/builtins.cpp
@@ -34,30 +34,3 @@ int builtins::build()
std::cout << poi_Version << std::endl;
return 0;
}
-
-int builtins::help(const char *cmd,
- const boost::program_options::options_description &cmd_opts,
- const boost::program_options::options_description &config_opts,
- const CommandHash_t &pluginCommands, const QTranslator *translator)
-{
- const auto version = QVersionNumber::fromString(QLatin1String(poi_Version)).toString().toStdString();
- std::cout << tr(translator, "smolbote ") << version << tr(translator, ": yet another no-frills browser\n");
- std::cout << tr(translator, "Usage: ") << cmd << tr(translator, " [options] [command/URL(s)]\n\n");
-
- std::cout << tr(translator, "Command-line Options:\n") << cmd_opts << '\n';
-
- std::cout << tr(translator, "Commands: \n");
- for(auto it = pluginCommands.constBegin(); it != pluginCommands.constEnd(); ++it)
- std::cout << " " << it.key().toStdString() << '\n';
- std::cout << '\n';
-
- std::cout << tr(translator, "Configuration Options:\n") << config_opts << '\n';
-
-#ifdef Q_OS_UNIX
- std::cout << tr(translator, "For more information on usage, refer to the manual page smolbote.7\n");
- std::cout << tr(translator, "For more information on configuration, refer to the manual page smolbote.5\n");
-#endif
-
- std::cout << std::endl;
- return 0;
-}
diff --git a/src/builtins.h b/src/builtins.h
index e151e8d..a3b9b07 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -16,11 +16,6 @@ namespace builtins
{
int version();
int build();
-int help(const char *cmd,
- const boost::program_options::options_description &cmd_opts,
- const boost::program_options::options_description &config_opts,
- const CommandHash_t &pluginCommands,
- const QTranslator *translator);
}
#endif
diff --git a/src/main.cpp b/src/main.cpp
index 8063b86..02a1168 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -8,22 +8,57 @@
#include "browser.h"
#include "builtins.h"
-#include "commandline.h"
#include "configuration.h"
+#include "crashhandler.h"
#include "session/session.h"
#include "session/sessiondialog.h"
#include "util.h"
-#include "crashhandler.h"
#include "version.h"
#include <QFile>
#include <QLibraryInfo>
#include <QPluginLoader>
-#include <pluginloader.h>
#include <QTranslator>
+#include <args.hxx>
+#include <iostream>
#include <memory>
#include <plugininterface.h>
+#include <pluginloader.h>
#include <spdlog/spdlog.h>
+typedef std::function<void(const std::string &, std::vector<std::string>::const_iterator, std::vector<std::string>::const_iterator)> subcommand_func;
+typedef std::unordered_map<std::string, subcommand_func> command_map;
+
+// a helper function to join the keys of a command_map into a string
+inline std::string join_keys(const command_map &map, const std::string sep = ", ")
+{
+ std::vector<std::string> keys(map.size());
+ std::transform(map.begin(), map.end(), keys.begin(), [](auto pair) { return pair.first; });
+ std::sort(keys.begin(), keys.end());
+
+ std::string k;
+ std::for_each(keys.begin(), keys.end() - 1, [&k, &sep](const std::string &piece) { k += piece + sep; });
+ k += keys.back();
+
+ return k;
+}
+
+#include <QStandardPaths>
+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
+}
+
#include "config.h"
#if defined(CONFIG_USEPLASMA) && !defined(PLASMA)
#error "You have enabled Plasma integration, but Frameworks was not found."
@@ -41,15 +76,40 @@ int main(int argc, char **argv)
spdlog::set_level(spdlog::level::debug); // Set global log level to debug
#endif
- const std::unique_ptr<CommandLine> cmd = std::make_unique<CommandLine>(argc, argv);
- // --version
- if(cmd->exists("version")) {
- return builtins::version();
- }
+ const std::vector<std::string> args(argv + 1, argv + argc);
+ args::ArgumentParser parser("smolbote: yet another no-frills browser", "For more information on usage, refer to the manual page.");
+ parser.Prog(argv[0]);
+
+ args::HelpFlag cmd_help(parser, "help", "Display this help message.", { 'h', "help" });
+ args::Flag cmd_version(parser, "version", "Display version information.", { 'v', "version" });
+ args::Flag cmd_build(parser, "build", "Display build commit.", { 'b', "build" });
+
+ args::ValueFlag<std::string> cmd_config(parser, "config", "Set the configuration file.", { 'c', "config" });
+
+ args::Flag cmd_noRemote(parser, "no-remote", "Do not accept or send remote commands.", { "no-remote" });
+
+ args::Flag cmd_pickSession(parser, "pick-session", "Show all available sessions and select which one to open", { "pick-session" });
+ args::ValueFlag<std::string> cmd_session(parser, "session", "Open the specified session.", { 's', "session" });
+
+ args::PositionalList<std::string> cmd_args(parser, "URL(s)", "List of URLs to open");
+
+ try {
+ auto next = parser.ParseArgs(args);
+
+ if(cmd_version)
+ return builtins::version();
+ if(cmd_build)
+ return builtins::build();
- // --build
- if(cmd->exists("build")) {
- return builtins::build();
+ } catch(args::Help) {
+ std::cout << parser;
+ //std::cout << "Available subcommands: " << command_keys << std::endl;
+ return 0;
+
+ } catch(args::Error e) {
+ std::cerr << e.what() << std::endl;
+ std::cerr << parser;
+ return -1;
}
// Disable Chromium's crash handler so breakpad can capture crashes instead.
@@ -60,7 +120,13 @@ int main(int argc, char **argv)
}
// create and load configuration
- std::unique_ptr<Configuration> config = std::make_unique<Configuration>(argc, argv, cmd->value<std::string>("config").value());
+ const std::string config_path = [&]() {
+ if(cmd_config)
+ return args::get(cmd_config);
+ else
+ return defaultUserConfigLocation();
+ }();
+ std::unique_ptr<Configuration> config = std::make_unique<Configuration>(argc, argv, config_path);
QTranslator translator;
if(config->exists("browser.translation")) {
translator.load(config->value<QString>("browser.translation").value());
@@ -70,7 +136,7 @@ int main(int argc, char **argv)
CommandHash_t pluginCommands;
// Load plugins
- for(const QString &path : Util::files(config->value<QString>("plugins.path").value(), {"*.so", "*.dll"})) {
+ for(const QString &path : Util::files(config->value<QString>("plugins.path").value(), { "*.so", "*.dll" })) {
auto *loader = new PluginLoader(path);
const bool loaded = loader->load();
spdlog::info("{} plugin {}", loaded ? "Loaded" : "Failed to load", qUtf8Printable(path));
@@ -85,10 +151,6 @@ int main(int argc, char **argv)
}
}
- if(cmd->exists("help")) {
- return builtins::help(argv[0], cmd->description(), config->description(), pluginCommands, &translator);
- }
-
// argc, argv, allowSecondary
Browser app(argc, argv);
// set this, otherwise the webview becomes black when using a stylesheet
@@ -129,27 +191,25 @@ int main(int argc, char **argv)
#endif
#endif // CONFIG_USEBREAKPAD
- const bool isStandalone = cmd->exists("no-remote");
const auto profile = config->value<QString>("profile.default");
app.setConfiguration(config); // app takes ownership of config
app.setup(plugins);
QStringList urls;
- 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))();
- } else {
- urls.append(QString::fromStdString(u));
- }
+
+ for(const auto &u : args::get(cmd_args)) {
+ if(pluginCommands.contains(QString::fromStdString(u))) {
+ return pluginCommands.value(QString::fromStdString(u))();
+ } else {
+ urls.append(QString::fromStdString(u));
}
}
if(urls.isEmpty())
urls.append(QString());
// if app is primary, create new sessions from received messages
- if(app.isPrimary() && !isStandalone) {
+ if(app.isPrimary() && !cmd_noRemote) {
QObject::connect(&app, &Browser::receivedMessage, &app, [](quint32 instanceId, QByteArray message) {
Q_UNUSED(instanceId);
auto doc = QJsonDocument::fromJson(message);
@@ -160,14 +220,14 @@ int main(int argc, char **argv)
{
QJsonObject sessionData;
- if(cmd->exists("pick-session")) {
+ if(cmd_pickSession) {
auto *dlg = new SessionDialog();
if(const auto pick = dlg->pickSession())
sessionData = pick.value();
else
sessionData = Session::fromCommandLine(profile.value(), urls);
- } else if(const auto session = cmd->value<QString>("session")) {
- QFile sessionJson(session.value());
+ } else if(cmd_session) {
+ QFile sessionJson(QString::fromStdString(args::get(cmd_session)));
if(sessionJson.open(QIODevice::ReadOnly | QIODevice::Text)) {
sessionData = QJsonDocument::fromJson(sessionJson.readAll()).object();
sessionJson.close();
@@ -176,7 +236,7 @@ int main(int argc, char **argv)
sessionData = Session::fromCommandLine(profile.value(), urls);
}
- if(app.isPrimary() || isStandalone) {
+ if(app.isPrimary() || cmd_noRemote) {
Session::restoreSession(sessionData);
} else {
// app is secondary and not standalone
diff --git a/src/meson.build b/src/meson.build
index ea866b9..d2ff9ad 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -13,7 +13,7 @@ poi_moc = mod_qt5.preprocess(
poi = executable(get_option('poiName'), install: true,
cpp_args: ['-DQAPPLICATION_CLASS=QApplication'],
- dependencies: [dep_qt5, dep_boost, dep_spdlog, dep_SingleApplication, optional_deps,
+ dependencies: [dep_qt5, dep_boost, dep_spdlog, dep_SingleApplication, dep_args, optional_deps,
dep_about, dep_addressbar, dep_bookmarks, dep_configuration, dep_downloads, dep_pluginloader, dep_urlfilter, dep_webprofile],
include_directories: [include],
sources: ['main.cpp', 'builtins.cpp', 'crashhandler.cpp', poi_moc, version_h,