summaryrefslogtreecommitdiff
path: root/src/commandline.cpp
diff options
context:
space:
mode:
authorMikaƫl Capelle <capelle.mikael@gmail.com>2023-07-09 17:36:03 +0200
committerGitHub <noreply@github.com>2023-07-09 17:36:03 +0200
commitef94aee28464039672b277243a0181ae93550d6c (patch)
tree0575a68af5f154e9d6d0738edbaefb16a11d6f5c /src/commandline.cpp
parent7d6cb8528d20e36a4cee822263865ee2f7f32481 (diff)
parent3de050e9c03e553f7ae3f780f6bd080a30ae123e (diff)
Merge pull request #1839 from Holt59/ci/initial-gh-action-for-build
Clang-Format + Github Workflow
Diffstat (limited to 'src/commandline.cpp')
-rw-r--r--src/commandline.cpp343
1 files changed, 132 insertions, 211 deletions
diff --git a/src/commandline.cpp b/src/commandline.cpp
index f64ff7cb..9082d710 100644
--- a/src/commandline.cpp
+++ b/src/commandline.cpp
@@ -1,11 +1,11 @@
#include "commandline.h"
#include "env.h"
-#include "organizercore.h"
#include "instancemanager.h"
-#include "multiprocess.h"
#include "loglist.h"
-#include "shared/util.h"
+#include "multiprocess.h"
+#include "organizercore.h"
#include "shared/appconfig.h"
+#include "shared/util.h"
#include <log.h>
#include <report.h>
@@ -14,19 +14,18 @@ namespace cl
using namespace MOBase;
-std::string pad_right(std::string s, std::size_t n, char c=' ')
+std::string pad_right(std::string s, std::size_t n, char c = ' ')
{
if (s.size() < n)
- s.append(n - s.size() , c);
+ s.append(n - s.size(), c);
return s;
}
// formats the list of pairs in two columns
//
-std::string table(
- const std::vector<std::pair<std::string, std::string>>& v,
- std::size_t indent, std::size_t spacing)
+std::string table(const std::vector<std::pair<std::string, std::string>>& v,
+ std::size_t indent, std::size_t spacing)
{
std::size_t longest = 0;
@@ -35,40 +34,28 @@ std::string table(
std::string s;
- for (auto&& p : v)
- {
+ for (auto&& p : v) {
if (!s.empty())
s += "\n";
- s +=
- std::string(indent, ' ') +
- pad_right(p.first, longest) + " " +
- std::string(spacing, ' ') +
- p.second;
+ s += std::string(indent, ' ') + pad_right(p.first, longest) + " " +
+ std::string(spacing, ' ') + p.second;
}
return s;
-
}
-
-CommandLine::CommandLine()
- : m_command(nullptr)
+CommandLine::CommandLine() : m_command(nullptr)
{
createOptions();
- add<
- RunCommand,
- ReloadPluginCommand,
- RefreshCommand,
- CrashDumpCommand,
- LaunchCommand>();
+ add<RunCommand, ReloadPluginCommand, RefreshCommand, CrashDumpCommand,
+ LaunchCommand>();
}
std::optional<int> CommandLine::process(const std::wstring& line)
{
- try
- {
+ try {
auto args = po::split_winmain(line);
if (!args.empty()) {
// remove program name
@@ -79,18 +66,16 @@ std::optional<int> CommandLine::process(const std::wstring& line)
// command name, but not the rest, which will be collected below
auto parsed = po::wcommand_line_parser(args)
- .options(m_allOptions)
- .positional(m_positional)
- .allow_unregistered()
- .run();
+ .options(m_allOptions)
+ .positional(m_positional)
+ .allow_unregistered()
+ .run();
po::store(parsed, m_vm);
po::notify(m_vm);
// collect options past the command name
- auto opts = po::collect_unrecognized(
- parsed.options, po::include_positional);
-
+ auto opts = po::collect_unrecognized(parsed.options, po::include_positional);
if (m_vm.count("command")) {
// there's a word as the first argument; this may be a command name or
@@ -106,8 +91,7 @@ std::optional<int> CommandLine::process(const std::wstring& line)
// remove the command name itself
opts.erase(opts.begin());
- try
- {
+ try {
// legacy commands handle their own parsing, such as 'launch'; don't
// attempt to parse anything here
if (!c->legacy()) {
@@ -140,14 +124,10 @@ std::optional<int> CommandLine::process(const std::wstring& line)
m_command = c.get();
return runEarly();
- }
- catch(po::error& e)
- {
+ } catch (po::error& e) {
env::Console console;
- std::cerr
- << e.what() << "\n"
- << usage(c.get()) << "\n";
+ std::cerr << e.what() << "\n" << usage(c.get()) << "\n";
return 1;
}
@@ -155,7 +135,6 @@ std::optional<int> CommandLine::process(const std::wstring& line)
}
}
-
// the first word on the command line is not a valid command, try the other
// stuff; this is used in setupCore() below when called from
// MOApplication::doOneRun()
@@ -167,7 +146,6 @@ std::optional<int> CommandLine::process(const std::wstring& line)
return 0;
}
-
if (!opts.empty()) {
const auto qs = QString::fromStdWString(opts[0]);
@@ -202,14 +180,10 @@ std::optional<int> CommandLine::process(const std::wstring& line)
}
return {};
- }
- catch(po::error& e)
- {
+ } catch (po::error& e) {
env::Console console;
- std::cerr
- << e.what() << "\n"
- << usage() << "\n";
+ std::cerr << e.what() << "\n" << usage() << "\n";
return 1;
}
@@ -250,7 +224,7 @@ std::optional<int> CommandLine::runPostApplication(MOApplication& a)
if (m_vm.count("instance") && m_vm["instance"].as<std::string>() == "") {
env::Console c;
- if (auto i=InstanceManager::singleton().currentInstance()) {
+ if (auto i = InstanceManager::singleton().currentInstance()) {
std::cout << i->displayName().toStdString() << "\n";
} else {
std::cout << "no instance configured\n";
@@ -283,13 +257,12 @@ std::optional<int> CommandLine::runPostOrganizer(OrganizerCore& core)
// make sure MO doesn't exit even if locking is disabled, ForceWait and
// PreventExit will do that
core.processRunner()
- .setFromShortcut(m_shortcut)
- .setWaitForCompletion(ProcessRunner::ForCommandLine, UILocker::PreventExit)
- .run();
+ .setFromShortcut(m_shortcut)
+ .setWaitForCompletion(ProcessRunner::ForCommandLine, UILocker::PreventExit)
+ .run();
return 0;
- }
- catch (std::exception&) {
+ } catch (std::exception&) {
// user was already warned
return 1;
}
@@ -301,23 +274,19 @@ std::optional<int> CommandLine::runPostOrganizer(OrganizerCore& core)
const QString exeName = *m_executable;
log::debug("starting {} from command line", exeName);
- try
- {
+ try {
// pass the remaining parameters to the binary
//
// make sure MO doesn't exit even if locking is disabled, ForceWait and
// PreventExit will do that
core.processRunner()
- .setFromFileOrExecutable(exeName, m_untouched)
- .setWaitForCompletion(ProcessRunner::ForCommandLine, UILocker::PreventExit)
- .run();
+ .setFromFileOrExecutable(exeName, m_untouched)
+ .setWaitForCompletion(ProcessRunner::ForCommandLine, UILocker::PreventExit)
+ .run();
return 0;
- }
- catch (const std::exception &e)
- {
- reportError(
- QObject::tr("failed to start application: %1").arg(e.what()));
+ } catch (const std::exception& e) {
+ reportError(QObject::tr("failed to start application: %1").arg(e.what()));
return 1;
}
} else if (m_command) {
@@ -331,42 +300,31 @@ void CommandLine::clear()
{
m_vm.clear();
m_shortcut = {};
- m_nxmLink = {};
+ m_nxmLink = {};
}
void CommandLine::createOptions()
{
- m_visibleOptions.add_options()
- ("help",
- "show this message")
-
- ("multiple",
- "allow multiple MO processes to run; see below")
+ m_visibleOptions.add_options()("help", "show this message")
- ("pick",
- "show the select instance dialog on startup")
+ ("multiple", "allow multiple MO processes to run; see below")
- ("logs",
- "duplicates the logs to stdout")
+ ("pick", "show the select instance dialog on startup")
- ("instance,i",
- po::value<std::string>()->implicit_value(""),
- "use the given instance (defaults to last used)")
+ ("logs", "duplicates the logs to stdout")
- ("profile,p",
- po::value<std::string>(),
- "use the given profile (defaults to last used)");
+ ("instance,i", po::value<std::string>()->implicit_value(""),
+ "use the given instance (defaults to last used)")
+ ("profile,p", po::value<std::string>(),
+ "use the given profile (defaults to last used)");
po::options_description options;
- options.add_options()
- ("command", po::value<std::string>(), "command")
- ("subargs", po::value<std::vector<std::string> >(), "args");
+ options.add_options()("command", po::value<std::string>(), "command")(
+ "subargs", po::value<std::vector<std::string>>(), "args");
// one command name, followed by any arguments for that command
- m_positional
- .add("command", 1)
- .add("subargs", -1);
+ m_positional.add("command", 1).add("subargs", -1);
m_allOptions.add(m_visibleOptions);
m_allOptions.add(options);
@@ -376,27 +334,22 @@ std::string CommandLine::usage(const Command* c) const
{
std::ostringstream oss;
- oss
- << "\n"
- << "Usage:\n";
+ oss << "\n"
+ << "Usage:\n";
if (c) {
- oss
- << " ModOrganizer.exe [global-options] " << c->usageLine() << "\n\n";
+ oss << " ModOrganizer.exe [global-options] " << c->usageLine() << "\n\n";
const std::string more = c->moreInfo();
if (!more.empty()) {
oss << more << "\n\n";
}
- oss
- << "Command options:\n"
- << c->visibleOptions() << "\n";
+ oss << "Command options:\n" << c->visibleOptions() << "\n";
} else {
- oss
- << " ModOrganizer.exe [options] [[command] [command-options]]\n"
- << "\n"
- << "Commands:\n";
+ oss << " ModOrganizer.exe [options] [[command] [command-options]]\n"
+ << "\n"
+ << "Commands:\n";
// name and description for all commands
std::vector<std::pair<std::string, std::string>> v;
@@ -409,14 +362,11 @@ std::string CommandLine::usage(const Command* c) const
v.push_back({c->name(), c->description()});
}
- oss
- << table(v, 2, 4) << "\n"
- << "\n";
+ oss << table(v, 2, 4) << "\n"
+ << "\n";
}
- oss
- << "Global options:\n"
- << m_visibleOptions << "\n";
+ oss << "Global options:\n" << m_visibleOptions << "\n";
// show the more text unless this is usage for a specific command
if (!c) {
@@ -480,32 +430,29 @@ const QStringList& CommandLine::untouched() const
std::string CommandLine::more() const
{
- return
- "Multiple processes\n"
- " A note on terminology: 'instance' can either mean an MO process\n"
- " that's running on the system, or a set of mods and profiles managed\n"
- " by MO. To avoid confusion, the term 'process' is used below for the\n"
- " former.\n"
- " \n"
- " --multiple can be used to allow multiple MO processes to run\n"
- " simultaneously. This is unsupported and can create all sorts of weird\n"
- " problems. To minimize these:\n"
- " \n"
- " 1) Never have multiple MO processes running that manage the same\n"
- " game instance.\n"
- " 2) If an executable is launched from an MO process, only this\n"
- " process may launch executables until all processes are \n"
- " terminated.\n"
- " \n"
- " It is recommended to close _all_ MO processes as soon as multiple\n"
- " processes become unnecessary.";
+ return "Multiple processes\n"
+ " A note on terminology: 'instance' can either mean an MO process\n"
+ " that's running on the system, or a set of mods and profiles managed\n"
+ " by MO. To avoid confusion, the term 'process' is used below for the\n"
+ " former.\n"
+ " \n"
+ " --multiple can be used to allow multiple MO processes to run\n"
+ " simultaneously. This is unsupported and can create all sorts of weird\n"
+ " problems. To minimize these:\n"
+ " \n"
+ " 1) Never have multiple MO processes running that manage the same\n"
+ " game instance.\n"
+ " 2) If an executable is launched from an MO process, only this\n"
+ " process may launch executables until all processes are \n"
+ " terminated.\n"
+ " \n"
+ " It is recommended to close _all_ MO processes as soon as multiple\n"
+ " processes become unnecessary.";
}
-
Command::Meta::Meta(std::string n, std::string d, std::string u, std::string m)
- : name(n), description(d), usage(u), more(m)
-{
-}
+ : name(n), description(d), usage(u), more(m)
+{}
std::string Command::name() const
{
@@ -541,8 +488,7 @@ po::options_description Command::visibleOptions() const
{
po::options_description d(getVisibleOptions());
- d.add_options()
- ("help", "shows this message");
+ d.add_options()("help", "shows this message");
return d;
}
@@ -575,13 +521,11 @@ po::positional_options_description Command::getPositional() const
return {};
}
-void Command::set(
- const std::wstring& originalLine,
- po::variables_map vm,
- std::vector<std::wstring> untouched)
+void Command::set(const std::wstring& originalLine, po::variables_map vm,
+ std::vector<std::wstring> untouched)
{
- m_original = originalLine;
- m_vm = vm;
+ m_original = originalLine;
+ m_vm = vm;
m_untouched = untouched;
}
@@ -625,25 +569,20 @@ const std::vector<std::wstring>& Command::untouched() const
return m_untouched;
}
-
po::options_description CrashDumpCommand::getVisibleOptions() const
{
po::options_description d;
- d.add_options()
- ("type", po::value<std::string>()->default_value("mini"), "mini|data|full");
+ d.add_options()("type", po::value<std::string>()->default_value("mini"),
+ "mini|data|full");
return d;
}
Command::Meta CrashDumpCommand::meta() const
{
- return {
- "crashdump",
- "writes a crashdump for a running process of MO",
- "[options]",
- ""
- };
+ return {"crashdump", "writes a crashdump for a running process of MO", "[options]",
+ ""};
}
std::optional<int> CrashDumpCommand::runEarly()
@@ -651,7 +590,7 @@ std::optional<int> CrashDumpCommand::runEarly()
env::Console console;
const auto typeString = vm()["type"].as<std::string>();
- const auto type = env::coreDumpTypeFromString(typeString);
+ const auto type = env::coreDumpTypeFromString(typeString);
// dump
const auto b = env::coredumpOther(type);
@@ -665,7 +604,6 @@ std::optional<int> CrashDumpCommand::runEarly()
return (b ? 0 : 1);
}
-
Command::Meta LaunchCommand::meta() const
{
return {"launch", "(internal, do not use)", "", ""};
@@ -691,14 +629,15 @@ std::optional<int> LaunchCommand::runEarly()
int LaunchCommand::SpawnWaitProcess(LPCWSTR workingDirectory, LPCWSTR commandLine)
{
- PROCESS_INFORMATION pi{ 0 };
- STARTUPINFO si{ 0 };
- si.cb = sizeof(si);
+ PROCESS_INFORMATION pi{0};
+ STARTUPINFO si{0};
+ si.cb = sizeof(si);
std::wstring commandLineCopy = commandLine;
- if (!CreateProcessW(NULL, &commandLineCopy[0], NULL, NULL, FALSE, 0, NULL, workingDirectory, &si, &pi)) {
- // A bit of a problem where to log the error message here, at least this way you can get the message
- // using a either DebugView or a live debugger:
+ if (!CreateProcessW(NULL, &commandLineCopy[0], NULL, NULL, FALSE, 0, NULL,
+ workingDirectory, &si, &pi)) {
+ // A bit of a problem where to log the error message here, at least this way you can
+ // get the message using a either DebugView or a live debugger:
std::wostringstream ost;
ost << L"CreateProcess failed: " << commandLine << ", " << GetLastError();
OutputDebugStringW(ost.str().c_str());
@@ -714,15 +653,15 @@ int LaunchCommand::SpawnWaitProcess(LPCWSTR workingDirectory, LPCWSTR commandLin
return static_cast<int>(exitCode);
}
-// Parses the first parseArgCount arguments of the current process command line and returns
-// them in parsedArgs, the rest of the command line is returned untouched.
-LPCWSTR LaunchCommand::UntouchedCommandLineArguments(
- int parseArgCount, std::vector<std::wstring>& parsedArgs)
+// Parses the first parseArgCount arguments of the current process command line and
+// returns them in parsedArgs, the rest of the command line is returned untouched.
+LPCWSTR
+LaunchCommand::UntouchedCommandLineArguments(int parseArgCount,
+ std::vector<std::wstring>& parsedArgs)
{
LPCWSTR cmd = GetCommandLineW();
- LPCWSTR arg = nullptr; // to skip executable name
- for (; parseArgCount >= 0 && *cmd; ++cmd)
- {
+ LPCWSTR arg = nullptr; // to skip executable name
+ for (; parseArgCount >= 0 && *cmd; ++cmd) {
if (*cmd == '"') {
int escaped = 0;
for (++cmd; *cmd && (*cmd != '"' || escaped % 2 != 0); ++cmd)
@@ -730,8 +669,8 @@ LPCWSTR LaunchCommand::UntouchedCommandLineArguments(
}
if (*cmd == ' ') {
if (arg)
- if (cmd-1 > arg && *arg == '"' && *(cmd-1) == '"')
- parsedArgs.push_back(std::wstring(arg+1, cmd-1));
+ if (cmd - 1 > arg && *arg == '"' && *(cmd - 1) == '"')
+ parsedArgs.push_back(std::wstring(arg + 1, cmd - 1));
else
parsedArgs.push_back(std::wstring(arg, cmd));
arg = cmd + 1;
@@ -741,29 +680,25 @@ LPCWSTR LaunchCommand::UntouchedCommandLineArguments(
return cmd;
}
-
Command::Meta RunCommand::meta() const
{
- return {
- "run",
- "runs a program, file or a configured executable",
- "[options] NAME",
+ return {"run", "runs a program, file or a configured executable", "[options] NAME",
- "Runs a program or a file with the virtual filesystem. If NAME is a path\n"
- "to a non-executable file, the program that is associated with the file\n"
- "extension is run instead. With -e, NAME must refer to the name of an\n"
- "executable in the instance (for example, \"SKSE\")."
- };
+ "Runs a program or a file with the virtual filesystem. If NAME is a path\n"
+ "to a non-executable file, the program that is associated with the file\n"
+ "extension is run instead. With -e, NAME must refer to the name of an\n"
+ "executable in the instance (for example, \"SKSE\")."};
}
po::options_description RunCommand::getVisibleOptions() const
{
po::options_description d;
- d.add_options()
- ("executable,e", po::value<bool>()->default_value(false)->zero_tokens(), "the name is a configured executable name")
- ("arguments,a", po::value<std::string>(), "override arguments")
- ("cwd,c", po::value<std::string>(), "override working directory");
+ d.add_options()("executable,e",
+ po::value<bool>()->default_value(false)->zero_tokens(),
+ "the name is a configured executable name")(
+ "arguments,a", po::value<std::string>(), "override arguments")(
+ "cwd,c", po::value<std::string>(), "override working directory");
return d;
}
@@ -772,8 +707,8 @@ po::options_description RunCommand::getInternalOptions() const
{
po::options_description d;
- d.add_options()
- ("NAME", po::value<std::string>()->required(), "program or executable name");
+ d.add_options()("NAME", po::value<std::string>()->required(),
+ "program or executable name");
return d;
}
@@ -796,8 +731,7 @@ std::optional<int> RunCommand::runPostOrganizer(OrganizerCore& core)
{
const auto program = QString::fromStdString(vm()["NAME"].as<std::string>());
- try
- {
+ try {
// make sure MO doesn't exit even if locking is disabled, ForceWait and
// PreventExit will do that
auto p = core.processRunner();
@@ -814,9 +748,9 @@ std::optional<int> RunCommand::runPostOrganizer(OrganizerCore& core)
if (itor == exes.end()) {
// not found
reportError(
- QObject::tr("Executable '%1' not found in instance '%2'.")
- .arg(program)
- .arg(InstanceManager::singleton().currentInstance()->displayName()));
+ QObject::tr("Executable '%1' not found in instance '%2'.")
+ .arg(program)
+ .arg(InstanceManager::singleton().currentInstance()->displayName()));
return 1;
}
@@ -840,40 +774,33 @@ std::optional<int> RunCommand::runPostOrganizer(OrganizerCore& core)
const auto r = p.run();
if (r == ProcessRunner::Error) {
reportError(
- QObject::tr("Failed to run '%1'. The logs might have more information.").arg(program));
+ QObject::tr("Failed to run '%1'. The logs might have more information.")
+ .arg(program));
return 1;
}
return 0;
- }
- catch (const std::exception &e) {
+ } catch (const std::exception& e) {
reportError(
- QObject::tr("Failed to run '%1'. The logs might have more information. %2")
- .arg(program).arg(e.what()));
+ QObject::tr("Failed to run '%1'. The logs might have more information. %2")
+ .arg(program)
+ .arg(e.what()));
return 1;
}
}
-
-
Command::Meta ReloadPluginCommand::meta() const
{
- return {
- "reload-plugin",
- "reloads the given plugin",
- "PLUGIN",
- ""
- };
+ return {"reload-plugin", "reloads the given plugin", "PLUGIN", ""};
}
po::options_description ReloadPluginCommand::getInternalOptions() const
{
po::options_description d;
- d.add_options()
- ("PLUGIN", po::value<std::string>()->required(), "plugin name");
+ d.add_options()("PLUGIN", po::value<std::string>()->required(), "plugin name");
return d;
}
@@ -896,10 +823,9 @@ std::optional<int> ReloadPluginCommand::runPostOrganizer(OrganizerCore& core)
{
const QString name = QString::fromStdString(vm()["PLUGIN"].as<std::string>());
- QString filepath = QDir(
- qApp->applicationDirPath() + "/" +
- ToQString(AppConfig::pluginPath()))
- .absoluteFilePath(name);
+ QString filepath =
+ QDir(qApp->applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()))
+ .absoluteFilePath(name);
log::debug("reloading plugin from {}", filepath);
core.pluginContainer().reloadPlugin(filepath);
@@ -907,14 +833,9 @@ std::optional<int> ReloadPluginCommand::runPostOrganizer(OrganizerCore& core)
return {};
}
-
Command::Meta RefreshCommand::meta() const
{
- return {
- "refresh",
- "refreshes MO (same as F5)",
- "", ""
- };
+ return {"refresh", "refreshes MO (same as F5)", "", ""};
}
bool RefreshCommand::canForwardToPrimary() const
@@ -928,4 +849,4 @@ std::optional<int> RefreshCommand::runPostOrganizer(OrganizerCore& core)
return {};
}
-} // namespace
+} // namespace cl