Skip to content

Commit cdda706

Browse files
authored
feat: Add recipes to CLI config and add builtin recipe shortcuts (#116)
1 parent 7a71935 commit cdda706

File tree

2 files changed

+75
-7
lines changed

2 files changed

+75
-7
lines changed

ecsact/cli/commands/build.cc

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include "ecsact/cli/commands/build.hh"
22

33
#include <memory>
4-
#include <iostream>
54
#include <format>
65
#include <filesystem>
76
#include <array>
@@ -58,6 +57,33 @@ constexpr auto allowed_recipe_extensions = std::array{
5857
".json"sv, // json works since yaml is a superset
5958
};
6059

60+
auto resolve_builtin_recipe( //
61+
std::string recipe_str,
62+
const char* argv[]
63+
) -> std::optional<fs::path> {
64+
using namespace std::string_literals;
65+
66+
auto exec_path = ecsact::cli::detail::canon_argv0(argv[0]);
67+
auto install_prefix = exec_path.parent_path().parent_path();
68+
auto recipes_dir = install_prefix / "share" / "ecsact" / "recipes";
69+
70+
if(fs::exists(recipes_dir)) {
71+
for(auto& entry : fs::directory_iterator(recipes_dir)) {
72+
auto filename = entry.path().filename().replace_extension("").string();
73+
const auto prefix = "ecsact_"s;
74+
75+
auto stripped_filename = filename.substr(prefix.size(), filename.size());
76+
77+
if(recipe_str == stripped_filename) {
78+
auto path = fs::path(filename);
79+
path.replace_extension(".ecsact-recipe-bundle");
80+
return recipes_dir / path;
81+
}
82+
}
83+
}
84+
return std::nullopt;
85+
}
86+
6187
auto ecsact::cli::detail::build_command( //
6288
int argc,
6389
const char* argv[]
@@ -82,7 +108,15 @@ auto ecsact::cli::detail::build_command( //
82108
auto recipe_composite = std::optional<build_recipe>{};
83109
auto recipe_paths = args.at("--recipe").asStringList();
84110
for(auto& recipe_path_str : recipe_paths) {
85-
auto recipe_path = fs::path{recipe_path_str};
111+
auto builtin_path = resolve_builtin_recipe(recipe_path_str, argv);
112+
113+
fs::path recipe_path;
114+
if(builtin_path) {
115+
recipe_path = *builtin_path;
116+
} else {
117+
recipe_path = fs::path{recipe_path_str};
118+
}
119+
86120
if(std::ranges::find(allowed_recipe_extensions, recipe_path.extension()) ==
87121
allowed_recipe_extensions.end()) {
88122
ecsact::cli::report_error(
@@ -168,8 +202,8 @@ auto ecsact::cli::detail::build_command( //
168202
}
169203
ecsact::cli::report_error(
170204
"Build recipes do not resolve all imports. Make sure all imported "
171-
"functions in provided recipes are also exported by another recipe. If "
172-
"you would like to allow unresolved imports you may provide the "
205+
"functions in provided recipes are also exported by another recipe. "
206+
"If you would like to allow unresolved imports you may provide the "
173207
"--allow-unresolved-imports flag to suppress this error."
174208
);
175209
return 1;

ecsact/cli/commands/config.cc

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include "./config.hh"
2-
32
#include <iostream>
43
#include <filesystem>
54
#include <map>
@@ -24,8 +23,9 @@ constexpr auto USAGE = R"(Ecsact Config Command
2423
Available config keys:
2524
install_dir directory Ecsact SDK was installed to
2625
include_dir directory containing Ecsact headers
27-
plugin_dir directory containing built-in Ecsact codegen plugins
28-
builtin_plugins list of built-in Ecsact codegen plugins available.
26+
plugin_dir directory containing built-in Ecsact codegen plugins
27+
builtin_plugins list of built-in Ecsact codegen plugins available
28+
recipe_bundles directory containing runtime recipe bundles
2929
3030
)";
3131

@@ -44,13 +44,21 @@ constexpr auto CANNOT_FIND_PLUGIN_DIR = R"(
4444
https://github.com/ecsact-dev/ecsact_sdk/issues
4545
)";
4646

47+
constexpr auto CANNOT_FIND_RECIPES_DIR = R"(
48+
[ERROR] Cannot find Ecsact recipes directory.
49+
Make sure you're using a standard Ecsact SDK installation.
50+
If you believe this is a mistake please file an issue at
51+
https://github.com/ecsact-dev/ecsact_sdk/issues
52+
)";
53+
4754
int ecsact::cli::detail::config_command(int argc, const char* argv[]) {
4855
using namespace std::string_literals;
4956

5057
auto args = docopt::docopt(USAGE, {argv + 1, argv + argc});
5158
auto exec_path = canon_argv0(argv[0]);
5259
auto install_prefix = exec_path.parent_path().parent_path();
5360
auto plugin_dir = install_prefix / "share" / "ecsact" / "plugins";
61+
auto recipes_dir = install_prefix / "share" / "ecsact" / "recipes";
5462
auto output = "{}"_json;
5563

5664
std::unordered_map<std::string, std::function<int()>> key_handlers{
@@ -117,6 +125,32 @@ int ecsact::cli::detail::config_command(int argc, const char* argv[]) {
117125
return 0;
118126
},
119127
},
128+
{
129+
"recipe_bundles",
130+
[&] {
131+
if(fs::exists(recipes_dir)) {
132+
std::vector<std::string> recipe_bundles;
133+
134+
for(auto& entry : fs::directory_iterator(recipes_dir)) {
135+
auto filename =
136+
entry.path().filename().replace_extension("").string();
137+
const auto prefix = "ecsact_"s;
138+
139+
if(filename.starts_with(prefix)) {
140+
recipe_bundles.emplace_back(
141+
filename.substr(prefix.size(), filename.size())
142+
);
143+
}
144+
}
145+
output["recipes_dir"] = recipe_bundles;
146+
} else {
147+
std::cerr << CANNOT_FIND_RECIPES_DIR;
148+
return 1;
149+
}
150+
return 0;
151+
},
152+
},
153+
120154
};
121155

122156
auto keys = args.at("<keys>").asStringList();

0 commit comments

Comments
 (0)