From ae33b98a77e4133b6f375c8a54d1fff92434287d Mon Sep 17 00:00:00 2001 From: Austin Kelway Date: Fri, 5 Jul 2024 14:59:39 -0700 Subject: [PATCH] feat: Add recipes to CLI config and add builtin recipe shortcuts (#116) --- ecsact/cli/commands/build.cc | 39 ++++++++++++++++++++++++++++++++--- ecsact/cli/commands/config.cc | 39 +++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/ecsact/cli/commands/build.cc b/ecsact/cli/commands/build.cc index 1700773..347e21c 100644 --- a/ecsact/cli/commands/build.cc +++ b/ecsact/cli/commands/build.cc @@ -58,6 +58,31 @@ constexpr auto allowed_recipe_extensions = std::array{ ".json"sv, // json works since yaml is a superset }; +auto resolve_builtin_recipe( // + std::string recipe_str, + const char* argv[] +) -> std::optional { + using namespace std::string_literals; + + auto exec_path = ecsact::cli::detail::canon_argv0(argv[0]); + auto install_prefix = exec_path.parent_path().parent_path(); + auto recipes_dir = install_prefix / "share" / "ecsact" / "recipes"; + + for(auto& entry : fs::directory_iterator(recipes_dir)) { + auto filename = entry.path().filename().replace_extension("").string(); + const auto prefix = "ecsact_"s; + + auto stripped_filename = filename.substr(prefix.size(), filename.size()); + + if(recipe_str == stripped_filename) { + auto path = fs::path(filename); + path.replace_extension(".ecsact-recipe-bundle"); + return recipes_dir / path; + } + } + return std::nullopt; +} + auto ecsact::cli::detail::build_command( // int argc, const char* argv[] @@ -82,7 +107,15 @@ auto ecsact::cli::detail::build_command( // auto recipe_composite = std::optional{}; auto recipe_paths = args.at("--recipe").asStringList(); for(auto& recipe_path_str : recipe_paths) { - auto recipe_path = fs::path{recipe_path_str}; + auto builtin_path = resolve_builtin_recipe(recipe_path_str, argv); + + fs::path recipe_path; + if(builtin_path) { + recipe_path = *builtin_path; + } else { + recipe_path = fs::path{recipe_path_str}; + } + if(std::ranges::find(allowed_recipe_extensions, recipe_path.extension()) == allowed_recipe_extensions.end()) { ecsact::cli::report_error( @@ -168,8 +201,8 @@ auto ecsact::cli::detail::build_command( // } ecsact::cli::report_error( "Build recipes do not resolve all imports. Make sure all imported " - "functions in provided recipes are also exported by another recipe. If " - "you would like to allow unresolved imports you may provide the " + "functions in provided recipes are also exported by another recipe. " + "If you would like to allow unresolved imports you may provide the " "--allow-unresolved-imports flag to suppress this error." ); return 1; diff --git a/ecsact/cli/commands/config.cc b/ecsact/cli/commands/config.cc index a6d1fee..28e6f65 100644 --- a/ecsact/cli/commands/config.cc +++ b/ecsact/cli/commands/config.cc @@ -24,8 +24,9 @@ constexpr auto USAGE = R"(Ecsact Config Command Available config keys: install_dir directory Ecsact SDK was installed to include_dir directory containing Ecsact headers - plugin_dir directory containing built-in Ecsact codegen plugins - builtin_plugins list of built-in Ecsact codegen plugins available. + plugin_dir directory containing built-in Ecsact codegen plugins + builtin_plugins list of built-in Ecsact codegen plugins available + recipe_bundles directory containing runtime recipe bundles )"; @@ -44,6 +45,13 @@ constexpr auto CANNOT_FIND_PLUGIN_DIR = R"( https://github.com/ecsact-dev/ecsact_sdk/issues )"; +constexpr auto CANNOT_FIND_RECIPES_DIR = R"( +[ERROR] Cannot find Ecsact recipes directory. + Make sure you're using a standard Ecsact SDK installation. + If you believe this is a mistake please file an issue at + https://github.com/ecsact-dev/ecsact_sdk/issues +)"; + int ecsact::cli::detail::config_command(int argc, const char* argv[]) { using namespace std::string_literals; @@ -51,6 +59,7 @@ int ecsact::cli::detail::config_command(int argc, const char* argv[]) { auto exec_path = canon_argv0(argv[0]); auto install_prefix = exec_path.parent_path().parent_path(); auto plugin_dir = install_prefix / "share" / "ecsact" / "plugins"; + auto recipes_dir = install_prefix / "share" / "ecsact" / "recipes"; auto output = "{}"_json; std::unordered_map> key_handlers{ @@ -117,6 +126,32 @@ int ecsact::cli::detail::config_command(int argc, const char* argv[]) { return 0; }, }, + { + "recipe_bundles", + [&] { + if(fs::exists(recipes_dir)) { + std::vector recipe_bundles; + + for(auto& entry : fs::directory_iterator(recipes_dir)) { + auto filename = + entry.path().filename().replace_extension("").string(); + const auto prefix = "ecsact_"s; + + if(filename.starts_with(prefix)) { + recipe_bundles.emplace_back( + filename.substr(prefix.size(), filename.size()) + ); + } + } + output["recipes_dir"] = recipe_bundles; + } else { + std::cerr << CANNOT_FIND_RECIPES_DIR; + return 1; + } + return 0; + }, + }, + }; auto keys = args.at("").asStringList();