mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-24 19:32:18 +00:00
feat: add regex_replace() string transform to placeholder templates (#14650)
feat: add regex_replace() string transform to filename templates
The filename template language could test strings (=~, !~, one_of) but
never rewrite one, so there was no supported way to reshape a placeholder
value, such as dropping a file extension from {first_object_name}.
Add regex_replace(subject, /pattern/, replacement), reusing the existing
regex-literal syntax and boost::regex engine. Every placeholder keeps
returning its exact value and the template does the transform explicitly:
{regex_replace(first_object_name, /\.[^.]*$/, "")} strip any extension
The replacement may reference capture groups ($1, $2, ...). It is one
grammar function mirroring digits(), with the name registered as a keyword
so it is not parsed as a variable.
This commit is contained in:
@@ -712,6 +712,26 @@ namespace client
|
||||
static void regex_matches (expr &lhs, IteratorRange &rhs) { return regex_op(lhs, rhs, '=', lhs); }
|
||||
static void regex_doesnt_match(expr &lhs, IteratorRange &rhs) { return regex_op(lhs, rhs, '!', lhs); }
|
||||
|
||||
// Replace every match of the regular expression 'pattern' in the string 'subject' with 'replacement'.
|
||||
// The replacement may reference capture groups ($1, $2, ...). Store the result into subject.
|
||||
static void regex_replace(expr &subject, IteratorRange &pattern, expr &replacement)
|
||||
{
|
||||
if (subject.type() == TYPE_EMPTY)
|
||||
// Inside an if / else block to be skipped
|
||||
return;
|
||||
if (subject.type() != TYPE_STRING)
|
||||
subject.throw_exception("regex_replace() first parameter must be a string.");
|
||||
try {
|
||||
std::string re(++ pattern.begin(), -- pattern.end());
|
||||
std::string result = SLIC3R_REGEX_NAMESPACE::regex_replace(subject.s(), SLIC3R_REGEX_NAMESPACE::regex(re), replacement.to_string());
|
||||
subject.set_s(std::move(result));
|
||||
} catch (SLIC3R_REGEX_NAMESPACE::regex_error &ex) {
|
||||
// Syntax error in the regular expression
|
||||
boost::throw_exception(qi::expectation_failure<Iterator>(
|
||||
pattern.begin(), pattern.end(), spirit::info(std::string("*Regular expression compilation failed: ") + ex.what())));
|
||||
}
|
||||
}
|
||||
|
||||
static void one_of_test_init(expr &out) {
|
||||
out.set_b(false);
|
||||
}
|
||||
@@ -2323,6 +2343,8 @@ namespace client
|
||||
[ px::bind(&expr::digits<false>, _val, _2, _3) ]
|
||||
| (kw["zdigits"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > optional_parameter(_r1))
|
||||
[ px::bind(&expr::digits<true>, _val, _2, _3) ]
|
||||
| (kw["regex_replace"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > regular_expression > ',' > conditional_expression(_r1) > ')')
|
||||
[ px::bind(&expr::regex_replace, _val, _2, _3) ]
|
||||
| (kw["int"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::to_int, _1, _val) ]
|
||||
| (kw["round"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::round, _1, _val) ]
|
||||
| (kw["ceil"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::ceil, _1, _val) ]
|
||||
@@ -2404,6 +2426,7 @@ namespace client
|
||||
("min")
|
||||
("max")
|
||||
("random")
|
||||
("regex_replace")
|
||||
("filament_change")
|
||||
("repeat")
|
||||
("round")
|
||||
|
||||
Reference in New Issue
Block a user