Skip to content

Commit

Permalink
Added Library/Cli
Browse files Browse the repository at this point in the history
  • Loading branch information
captainurist committed Oct 17, 2023
1 parent ad2b79c commit 8038505
Show file tree
Hide file tree
Showing 13 changed files with 90 additions and 100 deletions.
2 changes: 1 addition & 1 deletion src/Bin/CodeGen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ set(BIN_CODEGEN_HEADERS

if(NOT BUILD_PLATFORM STREQUAL "android")
add_executable(CodeGen ${BIN_CODEGEN_SOURCES} ${BIN_CODEGEN_HEADERS})
target_link_libraries(CodeGen PUBLIC platform_main application CLI11::CLI11)
target_link_libraries(CodeGen PUBLIC platform_main application library_cli)
target_check_style(CodeGen)
endif()
54 changes: 10 additions & 44 deletions src/Bin/CodeGen/CodeGenOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,28 @@

#include <memory>

#include <CLI/CLI.hpp>

#include "Utility/Format.h"
#include "Library/Cli/Cli.h"

CodeGenOptions CodeGenOptions::parse(int argc, char **argv) {
CodeGenOptions result;
result.useConfig = false; // CodeGen doesn't use external config.
result.logLevel = LOG_CRITICAL; // CodeGen doesn't need logging.

std::unique_ptr<CLI::App> app = std::make_unique<CLI::App>();
std::unique_ptr<CliApp> app = std::make_unique<CliApp>();

app->add_option("--data-path", result.dataPath,
"Path to game data dir")->check(CLI::ExistingDirectory)->option_text("PATH");
app->set_help_flag("-h,--help", "Print help and exit.");
app->require_subcommand();

CLI::App *items = app->add_subcommand("items", "Generate item ids enum.")->fallthrough();
items->callback([&] { result.subcommand = SUBCOMMAND_ITEM_ID; });

CLI::App *maps = app->add_subcommand("maps", "Generate map ids enum.")->fallthrough();
maps->callback([&] { result.subcommand = SUBCOMMAND_MAP_ID; });

CLI::App *beacons = app->add_subcommand("beacons", "Generate beacons mapping.")->fallthrough();
beacons->callback([&] { result.subcommand = SUBCOMMAND_BEACON_MAPPING; });

CLI::App *houses = app->add_subcommand("houses", "Generate house ids enum.")->fallthrough();
houses->callback([&] { result.subcommand = SUBCOMMAND_HOUSE_ID; });

CLI::App *monsters = app->add_subcommand("monsters", "Generate monster ids enum")->fallthrough();
monsters->callback([&] { result.subcommand = SUBCOMMAND_MONSTER_ID; });

CLI::App *monsterTypes = app->add_subcommand("monster_types", "Generate monster types enum")->fallthrough();
monsterTypes->callback([&] { result.subcommand = SUBCOMMAND_MONSTER_TYPE; });

CLI::App *bountyHunt = app->add_subcommand("bounty_hunt", "Generate monster type / town hall table for bounty hunts")->fallthrough();
bountyHunt->callback([&] { result.subcommand = SUBCOMMAND_BOUNTY_HUNT; });

try {
app->parse(argc, argv);
} catch (const CLI::ParseError &e) {
// TODO(captainurist): this is getting out of hand.
bool isHelp =
app->get_help_ptr()->as<bool>() ||
items->get_help_ptr()->as<bool>() ||
maps->get_help_ptr()->as<bool>() ||
beacons->get_help_ptr()->as<bool>() ||
monsters->get_help_ptr()->as<bool>() ||
monsterTypes->get_help_ptr()->as<bool>() ||
bountyHunt->get_help_ptr()->as<bool>();
if (isHelp) {
app->exit(e);
result.helpPrinted = true;
} else {
throw; // Genuine parse error => propagate.
}
}
app->add_subcommand("items", "Generate item ids enum.", result.subcommand, SUBCOMMAND_ITEM_ID)->fallthrough();
app->add_subcommand("maps", "Generate map ids enum.", result.subcommand, SUBCOMMAND_MAP_ID)->fallthrough();
app->add_subcommand("beacons", "Generate beacons mapping.", result.subcommand, SUBCOMMAND_BEACON_MAPPING)->fallthrough();
app->add_subcommand("houses", "Generate house ids enum.", result.subcommand, SUBCOMMAND_HOUSE_ID)->fallthrough();
app->add_subcommand("monsters", "Generate monster ids enum.", result.subcommand, SUBCOMMAND_MONSTER_ID)->fallthrough();
app->add_subcommand("monster_types", "Generate monster types enum.", result.subcommand, SUBCOMMAND_MONSTER_TYPE)->fallthrough();
app->add_subcommand("bounty_hunt", "Generate monster type / town hall table for bounty hunts.", result.subcommand, SUBCOMMAND_BOUNTY_HUNT)->fallthrough();

app->parse(argc, argv, &result.helpPrinted);
return result;
}
2 changes: 1 addition & 1 deletion src/Bin/LodTool/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ set(BIN_LODTOOL_HEADERS

if(NOT BUILD_PLATFORM STREQUAL "android")
add_executable(LodTool ${BIN_LODTOOL_SOURCES} ${BIN_LODTOOL_HEADERS})
target_link_libraries(LodTool PUBLIC library_lod library_lodformats CLI11::CLI11)
target_link_libraries(LodTool PUBLIC library_lod library_lodformats library_cli)
target_check_style(LodTool)
endif()
22 changes: 5 additions & 17 deletions src/Bin/LodTool/LodToolOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,18 @@

#include <memory>

#include <CLI/CLI.hpp>
#include "Library/Cli/Cli.h"

LodToolOptions LodToolOptions::parse(int argc, char **argv) {
LodToolOptions result;
std::unique_ptr<CLI::App> app = std::make_unique<CLI::App>();
std::unique_ptr<CliApp> app = std::make_unique<CliApp>();

app->set_help_flag("-h,--help", "Print help and exit.");
app->require_subcommand();

CLI::App *dump = app->add_subcommand("dump", "Dump a lod file.")->fallthrough();
CLI::App *dump = app->add_subcommand("dump", "Dump a lod file.", result.subcommand, SUBCOMMAND_DUMP)->fallthrough();
dump->add_option("LOD", result.lodPath, "Path to lod file.")->check(CLI::ExistingFile)->required()->option_text(" ");
dump->callback([&] {
result.subcommand = SUBCOMMAND_DUMP;
});

try {
app->parse(argc, argv);
} catch (const CLI::ParseError &e) {
if (app->get_help_ptr()->as<bool>() || dump->get_help_ptr()->as<bool>()) {
app->exit(e);
result.helpPrinted = true;
} else {
throw; // Genuine parse error => propagate.
}
}

app->parse(argc, argv, &result.helpPrinted);
return result;
}
4 changes: 2 additions & 2 deletions src/Bin/OpenEnroth/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ if(BUILD_PLATFORM STREQUAL "android")
add_library(main SHARED)
target_sources(main PUBLIC ${BIN_OPENENROTH_HEADERS} ${BIN_OPENENROTH_SOURCES})
target_check_style(main)
target_link_libraries(main PUBLIC platform_main application CLI11::CLI11)
target_link_libraries(main PUBLIC platform_main application library_cli)
target_link_options(main PRIVATE "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libmain.map")
else()
add_executable(OpenEnroth MACOSX_BUNDLE)
target_sources(OpenEnroth PUBLIC ${BIN_OPENENROTH_HEADERS} ${BIN_OPENENROTH_SOURCES})
target_check_style(OpenEnroth)
target_link_libraries(OpenEnroth PUBLIC platform_main application CLI11::CLI11)
target_link_libraries(OpenEnroth PUBLIC platform_main application library_cli)

set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT OpenEnroth)
endif()
30 changes: 10 additions & 20 deletions src/Bin/OpenEnroth/OpenEnrothOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

#include <memory>

#include <CLI/CLI.hpp>

#include "Utility/Format.h"

#include "Application/GamePathResolver.h"
#include "Application/GameConfig.h" // For PlatformLogLevel serialization.

#include "Library/Cli/Cli.h"

#include "Utility/Format.h"

OpenEnrothOptions OpenEnrothOptions::parse(int argc, char **argv) {
OpenEnrothOptions result;
std::unique_ptr<CLI::App> app = std::make_unique<CLI::App>();
std::unique_ptr<CliApp> app = std::make_unique<CliApp>();

app->add_option(
"--data-path", result.dataPath,
Expand All @@ -30,24 +30,14 @@ OpenEnrothOptions OpenEnrothOptions::parse(int argc, char **argv) {
"Set log level to 'verbose'.");
app->set_help_flag("-h,--help", "Print help and exit.");

CLI::App *retrace = app->add_subcommand("retrace", "Retrace traces and exit.")->fallthrough();
CLI::App *retrace = app->add_subcommand("retrace", "Retrace traces and exit.", result.subcommand, SUBCOMMAND_RETRACE)->fallthrough();
retrace->add_option("TRACE", result.retrace.traces,
"Path to trace file(s) to retrace.")->check(CLI::ExistingFile)->required()->option_text("...");
retrace->callback([&] {

app->parse(argc, argv, &result.helpPrinted);

if (result.subcommand == SUBCOMMAND_RETRACE)
result.useConfig = false; // Don't use external config if retracing.
result.subcommand = SUBCOMMAND_RETRACE;
});

try {
app->parse(argc, argv);
} catch (const CLI::ParseError &e) {
if (app->get_help_ptr()->as<bool>() || retrace->get_help_ptr()->as<bool>()) {
app->exit(e);
result.helpPrinted = true;
} else {
throw; // Genuine parse error => propagate.
}
}

return result;
}
1 change: 1 addition & 0 deletions src/Library/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.24 FATAL_ERROR)
add_subdirectory(Application)
add_subdirectory(Binary)
add_subdirectory(BuildInfo)
add_subdirectory(Cli)
add_subdirectory(Color)
add_subdirectory(Compression)
add_subdirectory(Config)
Expand Down
11 changes: 11 additions & 0 deletions src/Library/Cli/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.21.1)

set(LIBRARY_CLI_SOURCES
Cli.cpp)

set(LIBRARY_CLI_HEADERS
Cli.h)

add_library(library_cli ${LIBRARY_CLI_SOURCES} ${LIBRARY_CLI_HEADERS})
target_link_libraries(library_cli CLI11::CLI11)
target_check_style(library_cli)
18 changes: 18 additions & 0 deletions src/Library/Cli/Cli.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "Cli.h"

void CliApp::parse(int argc, const char *const *argv, bool *helpPrinted) {
// Note: we don't call base_type::ensure_utf8 here, it's the caller's responsibility.
try {
base_type::parse(argc, argv);
} catch (const CLI::CallForHelp &e) {
base_type::exit(e);
*helpPrinted = true;
} catch (const CLI::CallForAllHelp &e) {
base_type::exit(e);
*helpPrinted = true;
} catch (const CLI::CallForVersion &e) {
base_type::exit(e);
*helpPrinted = true;
}
// Other exception are propagated.
}
25 changes: 25 additions & 0 deletions src/Library/Cli/Cli.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <utility>
#include <string>

#include <CLI/CLI.hpp>

/**
* A thin wrapper around `CLI:App` that simplifies the code for our use cases.
*/
class CliApp : public CLI::App {
using base_type = CLI::App;
public:
CliApp() = default;

template<class SubcommandEnum>
CliApp *add_subcommand(std::string name, std::string description, SubcommandEnum &target, SubcommandEnum targetValue) {
auto callback = [target = &target, targetValue] {
*target = targetValue;
};
return static_cast<CliApp *>(base_type::add_subcommand(std::move(name), std::move(description))->callback(std::move(callback)));
}

void parse(int argc, const char *const *argv, bool *helpPrinted);
};
2 changes: 1 addition & 1 deletion test/Bin/GameTest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ if(OE_BUILD_TESTS)
GameTestOptions.h)

add_executable(OpenEnroth_GameTest ${GAME_TEST_MAIN_SOURCES} ${GAME_TEST_MAIN_HEADERS})
target_link_libraries(OpenEnroth_GameTest PUBLIC platform_main application testing_game GTest::gtest CLI11::CLI11)
target_link_libraries(OpenEnroth_GameTest PUBLIC platform_main application testing_game library_cli GTest::gtest)

target_check_style(OpenEnroth_GameTest)

Expand Down
17 changes: 4 additions & 13 deletions test/Bin/GameTest/GameTestOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <memory>

#include <CLI/CLI.hpp>
#include "Library/Cli/Cli.h"

#include "Application/GamePathResolver.h"

Expand All @@ -12,7 +12,7 @@ GameTestOptions GameTestOptions::parse(int argc, char **argv) {
result.useConfig = false; // Tests don't need an external config.
std::optional<std::string> testPath;

std::unique_ptr<CLI::App> app = std::make_unique<CLI::App>();
std::unique_ptr<CliApp> app = std::make_unique<CliApp>();

std::string requiredOptions = "Required Options";
std::string otherOptions = "Other Options";
Expand All @@ -28,20 +28,11 @@ GameTestOptions GameTestOptions::parse(int argc, char **argv) {
app->set_help_flag("-h,--help", "Print help and exit.")->group(otherOptions);
app->allow_extras();

try {
app->parse(argc, argv);
} catch (const CLI::ParseError &e) {
if (app->get_help_ptr()->as<bool>()) {
app->exit(e);
result.helpPrinted = true;
} else {
throw; // Genuine parse error => propagate.
}
}
app->parse(argc, argv, &result.helpPrinted);

if (!result.listRequested && !result.helpPrinted && !testPath)
throw CLI::RequiredError(testPathOption->get_name());

result.testPath = testPath.value_or("");

return result;
}
2 changes: 1 addition & 1 deletion test/Bin/UnitTest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ if(OE_BUILD_TESTS)
UnitTestMain.cpp)

add_executable(OpenEnroth_UnitTest ${UNIT_TEST_MAIN_SOURCES})
target_link_libraries(OpenEnroth_UnitTest PUBLIC testing_unit CLI11::CLI11)
target_link_libraries(OpenEnroth_UnitTest PUBLIC testing_unit)

add_custom_target(UnitTest OpenEnroth_UnitTest
DEPENDS OpenEnroth_UnitTest
Expand Down

0 comments on commit 8038505

Please sign in to comment.