Skip to content

Commit

Permalink
Added a q variant from all template methods. These use their first ar…
Browse files Browse the repository at this point in the history
…gument to decide whether to print anything or not.
  • Loading branch information
Relintai committed Feb 26, 2024
1 parent af2ef64 commit 6ea807b
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 14 deletions.
15 changes: 10 additions & 5 deletions modules/web/doc_classes/HTMLTemplate.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@
5. [code]pb(var)[/code] - print_newline_to_br, escaped, turns newlines into br tags, also includes a to string cast.
6. [code]prb(var)[/code] - print_raw_newline_to_br, not escaped, turns newlines into br tags, also includes a to string cast.
7. [code]vf("%d %d", var1, var2)[/code] - vformat or snprintf or String fromatting using % in gdscript.
8. [code]p(var_arr[0])[/code] - Array indexing.
9. [code]p(var_dict["x"]), p(var_dict[x]), p(var_dict['x'])[/code] - Dictionary indexing.
10. [code]p(var1, var2)[/code] - All methods supports multiple arguments.
11. Let's say [code]var1[/code] is a [Vector3], [code]var["x"][/code] and [code]var[0][/code] and [code]var[x][/code] will also work.
12. Indexing will also call [code]get()[/code] on [Object]s.
8. [code]qp(var1, var2)[/code] - Same as p, but only prints when it's first argument evaluates to true. (First arg is not printed!)
9. [code]qpr(var1, var2)[/code] - Same as pr, but only prints when it's first argument evaluates to true. (First arg is not printed!)
10. [code]qpb(var1, var2)[/code] - Same as pb, but only prints when it's first argument evaluates to true. (First arg is not printed!)
11. [code]qprb(var1, var2)[/code] - Same as prb, but only prints when it's first argument evaluates to true. (First arg is not printed!)
12. [code]qvf(var1, "%d %d", var1, var2)[/code] - Same as vf, but only prints when it's first argument evaluates to true. (First arg is not printed!)
13. [code]p(var_arr[0])[/code] - Array indexing.
14. [code]p(var_dict["x"]), p(var_dict[x]), p(var_dict['x'])[/code] - Dictionary indexing.
15. [code]p(var1, var2)[/code] - All methods supports multiple arguments.
16. Let's say [code]var1[/code] is a [Vector3], [code]var["x"][/code] and [code]var[0][/code] and [code]var[x][/code] will also work.
17. Indexing will also call [code]get()[/code] on [Object]s.
Not supported:
0. [code]p(var[var[var[2]]])[/code] Recursive indexing.
1. No actual method calls. Make everything available that your templates need in your controller class!
Expand Down
66 changes: 58 additions & 8 deletions modules/web/html/html_template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,31 @@ String HTMLTemplate::get_template_text(const StringName &p_name) {
return String();
}

String HTMLTemplate::call_template_method(const TemplateExpressionMethods p_method, const Array &p_data) {
String HTMLTemplate::call_template_method(const TemplateExpressionMethods p_method, const Array &p_data, const bool p_first_var_decides_print) {
int s = p_data.size();

if (s == 0) {
return String();
}

if (p_first_var_decides_print) {
Variant v = p_data[0];

if (!v) {
return String();
}
}

if (p_method != TEMPLATE_EXPRESSION_METHOD_VFORMAT) {
int arg_start = 0;

if (p_first_var_decides_print) {
++arg_start;
}

String ret;

for (int i = 0; i < s; ++i) {
for (int i = arg_start; i < s; ++i) {
switch (p_method) {
case TEMPLATE_EXPRESSION_METHOD_PRINT: {
ret += String(p_data[i]).xml_escape();
Expand All @@ -254,17 +272,23 @@ String HTMLTemplate::call_template_method(const TemplateExpressionMethods p_meth

return ret;
} else {
int arg_start = 1;

if (p_first_var_decides_print) {
++arg_start;
}

//VFormat

ERR_FAIL_COND_V_MSG(s < 1, String(), "vformat requires at least one positional argument!");
ERR_FAIL_COND_V_MSG(s < arg_start, String(), "vformat requires at least one positional argument!");

Array args;

for (int i = 1; i < s; ++i) {
for (int i = arg_start; i < s; ++i) {
args.push_back(p_data[i]);
}
String fstring = String(p_data[0]);

String fstring = String(p_data[arg_start - 1]);

bool error = false;
String fmt = fstring.sprintf(args, &error);
Expand Down Expand Up @@ -363,6 +387,11 @@ String HTMLTemplate::process_template_expression(const String &p_expression, con
// pb(var) // print_newline_to_br, escaped, turns newlines into <br>, also includes to string cast
// prb(var) // print_raw_newline_to_br, not escaped, turns newlines into <br>, also includes to string cast
// vf("%d %d", var1, var2) // vformat
// qp(var1, var2) // Same as p, but only prints when it's first argument evaluates to true
// qpr(var1, var2) // Same as pr, but only prints when it's first argument evaluates to true
// qpb(var1, var2) // Same as pb, but only prints when it's first argument evaluates to true
// qprb(var1, var2) // Same as prb, but only prints when it's first argument evaluates to true
// qvf(var1, "%d %d", var1, var2) // Same as vf, but only prints when it's first argument evaluates to true
// p(var[1]) // Array indexing
// p(var["x"]) // Dictionary indexing
// p(var1, var2) All methods can do multiple arguments
Expand Down Expand Up @@ -410,6 +439,7 @@ String HTMLTemplate::process_template_expression(const String &p_expression, con
method_name_search_done:

TemplateExpressionMethods call_method = TEMPLATE_EXPRESSION_METHOD_PRINT;
bool first_var_decides_print = false;

// This will be zero even if (var)
if (method_name_end_index != 0) {
Expand All @@ -426,6 +456,21 @@ String HTMLTemplate::process_template_expression(const String &p_expression, con
call_method = TEMPLATE_EXPRESSION_METHOD_PRINT_RAW_BR;
} else if (method_name == "vf") {
call_method = TEMPLATE_EXPRESSION_METHOD_VFORMAT;
} else if (method_name == "qp") {
//default, needs to be checked so no error
first_var_decides_print = true;
} else if (method_name == "qpr") {
call_method = TEMPLATE_EXPRESSION_METHOD_PRINT_RAW;
first_var_decides_print = true;
} else if (method_name == "qpb") {
call_method = TEMPLATE_EXPRESSION_METHOD_PRINT_BR;
first_var_decides_print = true;
} else if (method_name == "qprb") {
call_method = TEMPLATE_EXPRESSION_METHOD_PRINT_RAW_BR;
first_var_decides_print = true;
} else if (method_name == "qvf") {
call_method = TEMPLATE_EXPRESSION_METHOD_VFORMAT;
first_var_decides_print = true;
} else {
ERR_FAIL_V_MSG(String(), "There is an error in the syntax of an expression! Not a valid method!. Method: " + method_name + " Expression: " + p_expression);
}
Expand Down Expand Up @@ -536,7 +581,7 @@ String HTMLTemplate::process_template_expression(const String &p_expression, con
final_values.set(vi, process_template_expression_variable(variable, p_data));
}

return call_template_method(call_method, final_values);
return call_template_method(call_method, final_values, first_var_decides_print);
}

String HTMLTemplate::render_template(const String &p_text, const Dictionary &p_data) {
Expand All @@ -547,6 +592,11 @@ String HTMLTemplate::render_template(const String &p_text, const Dictionary &p_d
// {{ pb(var) }} // print_newline_to_br, escaped, turns newlines into <br>, also includes to string cast
// {{ prb(var) }} // print_raw_newline_to_br, not escaped, turns newlines into <br>, also includes to string cast
// {{ vf("%d %d", var1, var2) }} // vformat
// {{ qp(var) }} // Same as p, but only prints when it's first argument evaluates to true
// {{ qpr(var) }} // Same as pr, but only prints when it's first argument evaluates to true
// {{ qpb(var) }} // Same as pb, but only prints when it's first argument evaluates to true
// {{ qprb(var) }} // Same as prb, but only prints when it's first argument evaluates to true
// {{ qvf("%d %d", var1, var2) }} // Same as vf, but only prints when it's first argument evaluates to true

String result;

Expand Down Expand Up @@ -1040,7 +1090,7 @@ void HTMLTemplate::_bind_methods() {

ClassDB::bind_method(D_METHOD("get_template_text", "name"), &HTMLTemplate::get_template_text);

ClassDB::bind_method(D_METHOD("call_template_method", "method", "data"), &HTMLTemplate::call_template_method);
ClassDB::bind_method(D_METHOD("call_template_method", "method", "data", "first_var_decides_print"), &HTMLTemplate::call_template_method);
ClassDB::bind_method(D_METHOD("process_template_expression_variable", "variable", "data"), &HTMLTemplate::process_template_expression_variable);
ClassDB::bind_method(D_METHOD("process_template_expression", "expression", "data"), &HTMLTemplate::process_template_expression);
ClassDB::bind_method(D_METHOD("render_template", "text", "data"), &HTMLTemplate::render_template);
Expand Down
2 changes: 1 addition & 1 deletion modules/web/html/html_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class HTMLTemplate : public Resource {

String get_template_text(const StringName &p_name);

String call_template_method(const TemplateExpressionMethods p_method, const Array &p_data);
String call_template_method(const TemplateExpressionMethods p_method, const Array &p_data, const bool p_first_var_decides_print);
Variant process_template_expression_variable(const String &p_variable, const Dictionary &p_data);
String process_template_expression(const String &p_expression, const Dictionary &p_data);
String render_template(const String &p_text, const Dictionary &p_data);
Expand Down

0 comments on commit 6ea807b

Please sign in to comment.