From 6ca1ebc349528d5f6fc9194c590a17ecbe9fa444 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 6 Nov 2020 17:28:01 -0500 Subject: comments interpret a first argument starting with -- as an error instead of an exe name/binary --- src/commandline.h | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) (limited to 'src/commandline.h') diff --git a/src/commandline.h b/src/commandline.h index 72018ba3..478ee8ea 100644 --- a/src/commandline.h +++ b/src/commandline.h @@ -9,44 +9,96 @@ namespace cl namespace po = boost::program_options; - +// base class for all commands +// class Command { public: virtual ~Command() = default; + // command name, used on the command line to invoke it; this is meta().name + // std::string name() const; + + // command short description, shown in general help; this is + // meta().description + // std::string description() const; + + // usage line, puts together the name and whatever getUsageLine() returns + // std::string usageLine() const; + + // returns all options for this command, including hidden ones; used to parse + // the command line + // po::options_description allOptions() const; + + // returns visible options, used to display usage + // po::options_description visibleOptions() const; + + // returns positional arguments + // po::positional_options_description positional() const; - std::string usage() const; + // whether the command allows for unregistered options; this is only used for + // the old `launch` command and shouldn't be used anywhere else + // virtual bool allow_unregistered() const; + // runs this command, eventually calls doRun() + // std::optional run( const std::wstring& originalLine, po::variables_map vm, std::vector untouched); protected: + // meta information about this command, returned by derived classes + // struct Meta { std::string name, description; }; + // returns the usage line for this command, not including the name + // virtual std::string getUsageLine() const; + + // returns visible options specific to this command + // virtual po::options_description getVisibleOptions() const; + + // returns hidden options specific to this command + // virtual po::options_description getInternalOptions() const; + + // returns positional arguments specific to this command + // virtual po::positional_options_description getPositional() const; + + // meta + // virtual Meta meta() const = 0; + + // runs the command + // virtual std::optional doRun() = 0; + + // returns the original command line + // const std::wstring& originalCmd() const; + + // variables + // const po::variables_map& vm() const; + + // returns unparsed options, only used by launch + // const std::vector& untouched() const; private: @@ -56,6 +108,8 @@ private: }; +// generates a crash dump for another MO process +// class CrashDumpCommand : public Command { protected: @@ -93,6 +147,8 @@ protected: }; +// runs a configured executable +// class ExeCommand : public Command { protected: @@ -105,6 +161,8 @@ protected: }; +// runs an arbitrary executable +// class RunCommand : public Command { protected: @@ -114,24 +172,76 @@ protected: }; +// parses the command line and runs any given command +// +// the command line used to support a few commands but with no real conventions; +// those are mostly preserved for backwards compatibility, but deprecated: +// +// - moshortcut:// for desktop/taskbar shortcuts, may contain an instance name +// and a configured executable or arbitrary binary (still used in MO for +// shortcuts) +// +// - nxm:// links +// +// - the name of a configured executable or path to binary, followed by +// arbitrary parameters, forwarded to the program +// +// any command added CommandLine will unfortunately break any executable with +// the same name: `ModOrganizer.exe run` used to launch a program named "run" +// but will now execute the command "run" +// +// if moshortcut:// is detected and has an instance, it will override -i if both +// are given +// class CommandLine { public: CommandLine(); + // parses the given command line and executes the appropriate command, if + // any + // + // returns an empty optional if execution should continue, or a return code + // if MO must quit + // std::optional run(const std::wstring& line); + + // clears parsed options, used when MO is "restarted" so the options aren't + // processed again + // void clear(); + // global usage string plus usage for the given command, if any + // std::string usage(const Command* c=nullptr) const; + + // whether --multiple was given + // bool multiple() const; + + // profile override (-p) + // std::optional profile() const; + + // instance override (-i) + // std::optional instance() const; + // returns the data parsed from an moshortcut:// option, if any + // const MOShortcut& shortcut() const; + + // returns the nxm:// link, if any + // std::optional nxmLink() const; + + // returns the executable/binary, if any std::optional executable() const; + // returns the list of arguments, excluding moshortcut or executable name; + // deprecated, only use with executable() + // const QStringList& untouched() const; private: -- cgit v1.3.1 From ba7d24faef49858b9721c2ade0f3ea4a7ba4d96d Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 7 Nov 2020 17:21:13 -0500 Subject: moved handleCommandLine() to CommandLine::setupCore() --- src/commandline.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/commandline.h | 22 ++++++++++++++++++++++ src/main.cpp | 51 +-------------------------------------------------- 3 files changed, 76 insertions(+), 50 deletions(-) (limited to 'src/commandline.h') diff --git a/src/commandline.cpp b/src/commandline.cpp index dc8cf53f..3d0e901d 100644 --- a/src/commandline.cpp +++ b/src/commandline.cpp @@ -1,10 +1,15 @@ #include "commandline.h" #include "env.h" +#include "organizercore.h" #include "shared/util.h" +#include +#include namespace cl { +using namespace MOBase; + std::string pad_right(std::string s, std::size_t n, char c=' ') { if (s.size() < n) @@ -195,6 +200,54 @@ std::optional CommandLine::run(const std::wstring& line) } } +std::optional CommandLine::setupCore(OrganizerCore& organizer) const +{ + // if we have a command line parameter, it is either a nxm link or + // a binary to start + if (m_shortcut.isValid()) { + if (m_shortcut.hasExecutable()) { + try { + organizer.processRunner() + .setFromShortcut(m_shortcut) + .setWaitForCompletion() + .run(); + + return 0; + } + catch (const std::exception &e) { + reportError( + QObject::tr("failed to start shortcut: %1").arg(e.what())); + return 1; + } + } + } else if (m_nxmLink) { + log::debug("starting download from command line: {}", *m_nxmLink); + organizer.externalMessage(*m_nxmLink); + } else if (m_executable) { + const QString exeName = *m_executable; + log::debug("starting {} from command line", exeName); + + try + { + // pass the remaining parameters to the binary + organizer.processRunner() + .setFromFileOrExecutable(exeName, m_untouched) + .setWaitForCompletion() + .run(); + + return 0; + } + catch (const std::exception &e) + { + reportError( + QObject::tr("failed to start application: %1").arg(e.what())); + return 1; + } + } + + return {}; +} + void CommandLine::clear() { m_vm.clear(); diff --git a/src/commandline.h b/src/commandline.h index 478ee8ea..baa0bfb9 100644 --- a/src/commandline.h +++ b/src/commandline.h @@ -4,6 +4,8 @@ #include #include +class OrganizerCore; + namespace cl { @@ -193,6 +195,18 @@ protected: // if moshortcut:// is detected and has an instance, it will override -i if both // are given // +// +// the command is used in two phases: +// +// 1) run() is called in main() shortly after startup; it parses the command +// line and runs the given command, if any +// +// 2) if the command did not request to exit, the instance is loaded +// in main() et al. and setupCore() is called; it handles moshortcut, +// nxm links and starting executables/binaries +// +// either can return an exit code, which will make MO exit immediately +// class CommandLine { public: @@ -206,6 +220,14 @@ public: // std::optional run(const std::wstring& line); + // handles moshortcut, nxm links and starting processes + // + // returns an empty optional if execution should continue, or a return code + // if MO must quit + // + std::optional setupCore(OrganizerCore& organizer) const; + + // clears parsed options, used when MO is "restarted" so the options aren't // processed again // diff --git a/src/main.cpp b/src/main.cpp index e0326b27..55fedc7a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,55 +115,6 @@ void setExceptionHandlers() g_prevTerminateHandler = std::set_terminate(onTerminate); } -std::optional handleCommandLine( - const cl::CommandLine& cl, OrganizerCore& organizer) -{ - // if we have a command line parameter, it is either a nxm link or - // a binary to start - if (cl.shortcut().isValid()) { - if (cl.shortcut().hasExecutable()) { - try { - organizer.processRunner() - .setFromShortcut(cl.shortcut()) - .setWaitForCompletion() - .run(); - - return 0; - } - catch (const std::exception &e) { - reportError( - QObject::tr("failed to start shortcut: %1").arg(e.what())); - return 1; - } - } - } else if (cl.nxmLink()) { - log::debug("starting download from command line: {}", *cl.nxmLink()); - organizer.externalMessage(*cl.nxmLink()); - } else if (cl.executable()) { - const QString exeName = *cl.executable(); - log::debug("starting {} from command line", exeName); - - try - { - // pass the remaining parameters to the binary - organizer.processRunner() - .setFromFileOrExecutable(exeName, cl.untouched()) - .setWaitForCompletion() - .run(); - - return 0; - } - catch (const std::exception &e) - { - reportError( - QObject::tr("failed to start application: %1").arg(e.what())); - return 1; - } - } - - return {}; -} - int runApplication( MOApplication &application, const cl::CommandLine& cl, SingleInstance &instance, const QString &dataPath, @@ -274,7 +225,7 @@ int runApplication( organizer.setCurrentProfile(currentInstance.profileName()); - if (auto r=handleCommandLine(cl, organizer)) { + if (auto r=cl.setupCore(organizer)) { return *r; } -- cgit v1.3.1