Changing up variable interpolation in preparation of supporting interpolation for environments
This commit is contained in:
@@ -17,48 +17,77 @@ namespace daggy {
|
||||
return string;
|
||||
}
|
||||
|
||||
std::vector<std::unordered_map<std::string, std::string>>
|
||||
generateCartesianValues(const ConfigValues &values)
|
||||
{
|
||||
using ResultType =
|
||||
std::vector<std::unordered_map<std::string, std::string>>;
|
||||
ResultType result{{}};
|
||||
|
||||
for (const auto &[k, v] : values) {
|
||||
if (std::holds_alternative<std::string>(v)) {
|
||||
for (auto &valset : result) {
|
||||
valset.emplace(k, std::get<std::string>(v));
|
||||
}
|
||||
}
|
||||
else {
|
||||
ResultType new_result;
|
||||
for (const auto &val : std::get<std::vector<std::string>>(v)) {
|
||||
for (auto valset : result) {
|
||||
valset.emplace(k, val);
|
||||
new_result.emplace_back(valset);
|
||||
}
|
||||
}
|
||||
result.swap(new_result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> matchingParameters(
|
||||
const std::vector<std::string> &input, const ConfigValues &values)
|
||||
{
|
||||
std::unordered_set<std::string> matchParams;
|
||||
for (const auto &[k, v] : values) {
|
||||
std::string pattern = "{{" + k + "}}";
|
||||
bool anyMatched =
|
||||
std::any_of(input.begin(), input.end(), [&](const auto &part) {
|
||||
return part.find(pattern) != std::string::npos;
|
||||
});
|
||||
if (anyMatched)
|
||||
matchParams.insert(k);
|
||||
}
|
||||
return matchParams;
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::string>> interpolateValues(
|
||||
const std::vector<std::string> &raw, const ConfigValues &values)
|
||||
{
|
||||
std::vector<std::vector<std::string>> cooked{{}};
|
||||
std::vector<std::vector<std::string>> cooked;
|
||||
|
||||
for (const auto &part : raw) {
|
||||
std::vector<std::string> expandedPart{part};
|
||||
auto matchParams = matchingParameters(raw, values);
|
||||
if (matchParams.empty()) {
|
||||
cooked.emplace_back(raw);
|
||||
return cooked;
|
||||
}
|
||||
|
||||
// Find all values of parameters, and expand them
|
||||
for (const auto &[paramRaw, paramValue] : values) {
|
||||
std::string param = "{{" + paramRaw + "}}";
|
||||
auto pos = part.find(param);
|
||||
if (pos == std::string::npos)
|
||||
continue;
|
||||
std::vector<std::string> newExpandedPart;
|
||||
ConfigValues paramSubset;
|
||||
for (const auto &[k, v] : values) {
|
||||
if (matchParams.count(k) == 0)
|
||||
continue;
|
||||
paramSubset.emplace(k, v);
|
||||
}
|
||||
|
||||
if (std::holds_alternative<std::string>(paramValue)) {
|
||||
for (auto &cmd : expandedPart) {
|
||||
newExpandedPart.push_back(
|
||||
globalSub(cmd, param, std::get<std::string>(paramValue)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const auto &val :
|
||||
std::get<std::vector<std::string>>(paramValue)) {
|
||||
for (const auto &cmd : expandedPart) {
|
||||
newExpandedPart.push_back(globalSub(cmd, param, val));
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto valueSets = generateCartesianValues(paramSubset);
|
||||
|
||||
expandedPart.swap(newExpandedPart);
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::string>> newCommands;
|
||||
for (const auto &newPart : expandedPart) {
|
||||
for (auto cmd : cooked) {
|
||||
cmd.push_back(newPart);
|
||||
newCommands.emplace_back(cmd);
|
||||
for (const auto &valueSet : valueSets) {
|
||||
std::vector<std::string> item(raw);
|
||||
for (auto &part : item) {
|
||||
for (const auto &[k, v] : valueSet) {
|
||||
part = globalSub(part, "{{" + k + "}}", v);
|
||||
}
|
||||
}
|
||||
cooked.swap(newCommands);
|
||||
cooked.emplace_back(item);
|
||||
}
|
||||
return cooked;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user