diff --git a/src/apps/deskflow-core/deskflow-core.cpp b/src/apps/deskflow-core/deskflow-core.cpp index 8a5e1e24b..91acff740 100644 --- a/src/apps/deskflow-core/deskflow-core.cpp +++ b/src/apps/deskflow-core/deskflow-core.cpp @@ -6,12 +6,12 @@ * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ -#include "VersionInfo.h" #include "arch/Arch.h" #include "base/EventQueue.h" #include "base/Log.h" #include "common/ExitCodes.h" #include "deskflow/ClientApp.h" +#include "deskflow/CoreArgParser.h" #include "deskflow/ServerApp.h" #if SYSAPI_WIN32 @@ -20,17 +20,12 @@ #endif #include +#include #include -const static auto kHeader = QStringLiteral("%1-core: %2\n").arg(kAppId, kDisplayVersion); - -void showHelp() +void showHelp(const CoreArgParser &parser) { - std::cout << qPrintable(kHeader) << qPrintable(kAppDescription) << "\n\n"; - std::cout << "Usage: deskflow-core [...options]" << std::endl; - std::cout << "server - start as a server (deskflow-server)" << std::endl; - std::cout << "client - start as a client (deskflow-client)" << std::endl; - + QTextStream(stdout) << parser.helpText() << "\n"; ServerApp sApp(nullptr); sApp.help(); @@ -38,39 +33,6 @@ void showHelp() cApp.help(); } -bool isHelp(int argc, char **argv) -{ - for (int i = 0; i < argc; ++i) { - if (argv[i] == std::string("--help") || argv[i] == std::string("-h")) - return true; - } - return false; -} - -void showVersion() -{ - std::cout << qPrintable(kHeader) << qPrintable(kCopyright) << std::endl; -} - -bool isVersion(int argc, char **argv) -{ - for (int i = 0; i < argc; ++i) { - if (argv[i] == std::string("--version") || argv[i] == std::string("-v")) - return true; - } - return false; -} - -bool isServer(int argc, char **argv) -{ - return (argc > 1 && argv[1] == std::string("server")); -} - -bool isClient(int argc, char **argv) -{ - return (argc > 1 && argv[1] == std::string("client")); -} - int main(int argc, char **argv) { Arch arch; @@ -78,16 +40,29 @@ int main(int argc, char **argv) Log log; - if (isHelp(argc, argv)) { - showHelp(); + QStringList args; + for (int i = 0; i < argc; i++) + args.append(argv[i]); + + CoreArgParser parser(args); + + // Comment below until we are ready use only this parser + // if (!parser.errorText().isEmpty()) { + // QTextStream(stdout) << parser.errorText() << "\nUse --help for more information."; + // return s_exitFailed; + // } + + if (parser.help()) { + showHelp(parser); return s_exitSuccess; } - if (isVersion(argc, argv)) { - showVersion(); + if (parser.version()) { + QTextStream(stdout) << parser.versionText(); return s_exitSuccess; } + // Before we check any more args we need to check for a duplicate process. // Create a shared memory segment with a unique key // This is to prevent a new instance from running if one is already running QSharedMemory sharedMemory("deskflow-core"); @@ -102,6 +77,9 @@ int main(int argc, char **argv) LOG_WARN("an instance of deskflow core is already running"); return s_exitDuplicate; } + + parser.parse(); + #if SYSAPI_WIN32 // HACK to make sure settings gets the correct qApp path QCoreApplication m(argc, argv); @@ -112,14 +90,12 @@ int main(int argc, char **argv) EventQueue events; - if (isServer(argc, argv)) { + if (parser.serverMode()) { ServerApp app(&events); return app.run(argc, argv); - } else if (isClient(argc, argv)) { + } else if (parser.clientMode()) { ClientApp app(&events); return app.run(argc, argv); - } else { - showHelp(); } return s_exitSuccess; diff --git a/src/lib/deskflow/CMakeLists.txt b/src/lib/deskflow/CMakeLists.txt index 9edd316ae..68efb683c 100644 --- a/src/lib/deskflow/CMakeLists.txt +++ b/src/lib/deskflow/CMakeLists.txt @@ -83,6 +83,9 @@ add_library(${lib_name} STATIC ${PLATFORM_CODE} ClipboardChunk.h Config.cpp Config.h + CoreArgParser.cpp + CoreArgParser.h + CoreArgs.h DaemonApp.cpp DaemonApp.h DeskflowException.cpp diff --git a/src/lib/deskflow/CoreArgParser.cpp b/src/lib/deskflow/CoreArgParser.cpp new file mode 100644 index 000000000..b0dc4bba3 --- /dev/null +++ b/src/lib/deskflow/CoreArgParser.cpp @@ -0,0 +1,90 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#include "CoreArgParser.h" +#include "CoreArgs.h" +#include "VersionInfo.h" +#include "common/Constants.h" +#include "common/ExitCodes.h" +#include "common/Settings.h" + +const QString CoreArgParser::s_headerText = QStringLiteral("%1-core: %2\n").arg(kAppId, kDisplayVersion); + +CoreArgParser::CoreArgParser(const QStringList &args) +{ + m_parser.addPositionalArgument("coremode", "The mode to start in either: server or client", "coremode"); + + m_parser.addOptions(CoreArgs::options); + m_parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); + m_parser.parse(args); + m_parser.setApplicationDescription(kAppDescription); + + m_helpText = m_parser.helpText().replace("", QString("%1-core").arg(kAppId)); + m_helpText.replace("[options] coremode", "coremode [options]"); +} + +void CoreArgParser::parse() +{ + auto posArgs = m_parser.positionalArguments(); + if (posArgs.isEmpty()) { + showHelpText(); + exit(s_exitSuccess); + } + + const QString mode = posArgs.takeFirst(); + m_serverMode = (mode.compare("server", Qt::CaseInsensitive) == 0); + m_clientMode = (mode.compare("client", Qt::CaseInsensitive) == 0); + + if ((!m_clientMode && !m_serverMode) || mode.isEmpty()) { + showHelpText(); + exit(s_exitSuccess); + } + + if (m_parser.isSet(CoreArgs::configOption)) { + Settings::setSettingFile(m_parser.value(CoreArgs::configOption)); + } +} + +[[noreturn]] void CoreArgParser::showHelpText() const +{ + QTextStream(stdout) << helpText(); + exit(s_exitSuccess); +} + +QString CoreArgParser::helpText() const +{ + return QStringLiteral("%1%2").arg(s_headerText, m_helpText); +} + +QString CoreArgParser::versionText() const +{ + return QStringLiteral("%1%2\n").arg(s_headerText, kCopyright); +} + +QString CoreArgParser::errorText() const +{ + return m_parser.errorText(); +} + +bool CoreArgParser::help() const +{ + return m_parser.isSet(CoreArgs::helpOption); +} + +bool CoreArgParser::version() const +{ + return m_parser.isSet(CoreArgs::versionOption); +} + +bool CoreArgParser::serverMode() const +{ + return m_serverMode; +} + +bool CoreArgParser::clientMode() const +{ + return m_clientMode; +} diff --git a/src/lib/deskflow/CoreArgParser.h b/src/lib/deskflow/CoreArgParser.h new file mode 100644 index 000000000..45b7bc32c --- /dev/null +++ b/src/lib/deskflow/CoreArgParser.h @@ -0,0 +1,44 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#pragma once +#include + +/** + * @brief The CoreArgParser class + * This class processes the argments for the "core" app + */ +class CoreArgParser +{ +public: + /** + * @brief CoreArgParser calling this funciton will parse apps and set the setting and version options + * For any other settings to be set you must call parse(); + * @sa parse(); + * @param args List of args to parse + */ + explicit CoreArgParser(const QStringList &args = {}); + /** + * @brief parse + * This method will parse all options other then help and version + */ + void parse(); + QString helpText() const; + QString versionText() const; + QString errorText() const; + bool help() const; + bool version() const; + bool serverMode() const; + bool clientMode() const; + +private: + [[noreturn]] void showHelpText() const; + QCommandLineParser m_parser; + QString m_helpText; + bool m_clientMode = false; + bool m_serverMode = false; + static const QString s_headerText; +}; diff --git a/src/lib/deskflow/CoreArgs.h b/src/lib/deskflow/CoreArgs.h new file mode 100644 index 000000000..fe71cccf6 --- /dev/null +++ b/src/lib/deskflow/CoreArgs.h @@ -0,0 +1,22 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#pragma once + +#include +/** + * @brief The CoreArgs class + * This class contains args for the CoreArgParser + */ +struct CoreArgs +{ + inline static const auto helpOption = QCommandLineOption({"h", "help"}, "Display Help on the command line"); + inline static const auto versionOption = QCommandLineOption({"v", "version"}, "Display version information"); + inline static const auto configOption = QCommandLineOption( + {"s", "settings"}, "override configuration file to use", "configFile" + ); // use -c later, now avoid breaking the serverApp args. + inline static const auto options = {helpOption, versionOption, configOption}; +};