Reform command-line handling to use Clara, which is bundled with Catch

This commit is contained in:
2024-08-10 15:47:26 -04:00
committed by Celtic Minstrel
parent 8801d17ed5
commit d74b11aa31
14 changed files with 124 additions and 39 deletions

View File

@@ -2,6 +2,7 @@
#include "boe.global.hpp"
#include "tools/replay.hpp"
#include "universe/universe.hpp"
#include "cli.hpp"
#include <boost/filesystem/operations.hpp>
#include <boost/lexical_cast.hpp>
@@ -227,19 +228,26 @@ static void init_ui() {
}
static void process_args(int argc, char* argv[]) {
// Command line usage:
// "Blades of Exile" # basic launch
// "Blades of Exile" <save file> # launch and load save file
// "Blades of Exile" record <optional file> # record this session in a time-stamped xml file
// "Blades of Exile" replay <file> # replay a session from an xml file
if(argc > 1) {
std::string file = "";
if(argc > 2) {
file = argv[2];
}
if(init_action_log(argv[1], file))
return;
preprocess_args(argc, argv);
clara::Args args(argc, argv);
clara::Parser cli;
std::string record_to, replay, saved_game;
cli |= clara::Opt(record_to, "record")["--record"]("Records a replay of your session to the specified XML file.");
cli |= clara::Opt(replay, "replay-file")["--replay"]("Replays a previously-recorded session from the specified XML file.");
cli |= clara::Arg(saved_game, "save-file")("Launch and load a saved game file.");
bool show_help = false;
cli |= clara::Help(show_help);
if(auto result = cli.parse(args)); else {
std::cerr << "Error in command line: " << result.errorMessage() << std::endl;
exit(1);
}
if(show_help) {
cli.writeToStream(std::cout);
exit(0);
}
if(!record_to.empty() && init_action_log("record", record_to)) return;
if(!replay.empty() && init_action_log("replay", replay)) return;
if(!saved_game.empty()) {
if(!load_party(argv[1], univ)) {
std::cout << "Failed to load save file: " << argv[1] << std::endl;
return;

View File

@@ -25,6 +25,7 @@
#include "fileio/resmgr/res_image.hpp"
#include "tools/prefs.hpp"
#include "tools/framerate_limiter.hpp"
#include "cli.hpp"
#ifdef __APPLE__
short menuChoiceId=-1;
@@ -81,15 +82,30 @@ short specials_res_id;
char start_name[256];
static void process_args(int argc, char* argv[]) {
if(argc > 1) {
if(load_party(argv[1], univ)) {
file_in_mem = argv[1];
preprocess_args(argc, argv);
clara::Args args(argc, argv);
clara::Parser cli;
std::string file;
cli |= clara::Arg(file, "file")("The scenario file to open");
bool show_help = false;
cli |= clara::Help(show_help);
if(auto result = cli.parse(args)); else {
std::cerr << "Error in command line: " << result.errorMessage() << std::endl;
exit(1);
}
if(show_help) {
cli.writeToStream(std::cout);
exit(0);
}
if(!file.empty()) {
if(load_party(file, univ)) {
file_in_mem = file;
party_in_scen = !univ.party.scen_name.empty();
if(!party_in_scen) load_base_item_defs();
scen_items_loaded = true;
menu_activate();
} else {
std::cout << "Failed to load save file: " << argv[1] << std::endl;
std::cout << "Failed to load save file: " << file << std::endl;
return;
}
}

View File

@@ -3,6 +3,7 @@
#include <string>
#include <memory>
#include <boost/filesystem/operations.hpp>
#include "cli.hpp"
#include "scen.global.hpp"
#include "scenario/scenario.hpp"
@@ -188,8 +189,23 @@ void adjust_windows (sf::RenderWindow & mainPtr, sf::View & mainView) {
}
static void process_args(int argc, char* argv[]) {
if(argc > 1) {
if(load_scenario(argv[1], scenario)) {
preprocess_args(argc, argv);
clara::Args args(argc, argv);
clara::Parser cli;
std::string file;
cli |= clara::Arg(file, "file")("The scenario file to open");
bool show_help = false;
cli |= clara::Help(show_help);
if(auto result = cli.parse(args)); else {
std::cerr << "Error in command line: " << result.errorMessage() << std::endl;
exit(1);
}
if(show_help) {
cli.writeToStream(std::cout);
exit(0);
}
if(!file.empty()) {
if(load_scenario(file, scenario)) {
set_current_town(scenario.last_town_edited);
cur_out = scenario.last_out_edited;
current_terrain = scenario.outdoors[cur_out.x][cur_out.y];
@@ -197,7 +213,7 @@ static void process_args(int argc, char* argv[]) {
ae_loading = true;
set_up_main_screen();
} else {
std::cout << "Failed to load scenario: " << argv[1] << std::endl;
std::cout << "Failed to load scenario: " << file << std::endl;
}
}
}

5
src/tools/cli.hpp Normal file
View File

@@ -0,0 +1,5 @@
#include <boost/optional/optional_fwd.hpp>
#define CLARA_CONFIG_OPTIONAL_TYPE boost::optional
#include "clara.hpp" // part of Catch
namespace clara = Catch::clara;

View File

@@ -22,6 +22,10 @@ void setWindowFloating(sf::Window& win, bool floating);
void init_fileio();
void launchURL(std::string url);
// Optionally do some platform-specific preprocessing on the command-line arguments before parsing them.
// If preprocessing is needed, the expectation is that they will be modified in-place.
void preprocess_args(int& argc, char* argv[]);
std::string get_os_version();
fs::path nav_get_party();

View File

@@ -210,6 +210,9 @@ void launchURL(std::string url) {
system((std::string { "xdg-open " } + url).c_str());
}
void preprocess_args(int& argc, char* argv[]) {
}
// TODO: Implement modal session.
// It seems that Windows doesn't have anything similar to the Mac modal session, so I might have to somehow simulate it myself.
void ModalSession::pumpEvents() {
@@ -229,4 +232,4 @@ int getMenubarHeight() {
}
void adjust_window_for_menubar(int mode, unsigned int width, unsigned int height) {
}
}

View File

@@ -177,6 +177,28 @@ void launchURL(std::string url) {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithUTF8String:url.c_str()]]];
}
void preprocess_args(int& argc, char* argv[]) {
// Remove parameters that Xcode or the Finder throw onto the end of the command-line.
int skip_args = 0;
for(int i = 1; i < argc; i++) {
if(strcmp(argv[i], "-ApplePersistenceIgnoreState") == 0) {
skip_args = 2;
} else if(strcmp(argv[i], "-NSDocumentRevisionsDebugMode") == 0) {
skip_args = 2;
} else if(strcmp(argv[i], "-psn") == 0) {
skip_args = 1;
}
if(skip_args > 0) {
for(int j = i + 1; j <= argc; j++) {
argv[j - 1] = argv[j];
}
i--;
skip_args--;
argc--;
}
}
}
int getMenubarHeight() {
// Mac menubar isn't in the window, so we return 0 here.
return 0;

View File

@@ -426,6 +426,9 @@ void launchURL(std::string url) {
ShellExecuteA(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
}
void preprocess_args(int& argc, char* argv[]) {
}
// TODO: Implement modal session.
// It seems that Windows doesn't have anything similar to the Mac modal session, so I might have to somehow simulate it myself.
void ModalSession::pumpEvents() {
@@ -471,4 +474,4 @@ void adjust_window_for_menubar(int mode, unsigned int width, unsigned int height
height += getMenubarHeight();
mainPtr.setSize({ width, height });
}
}