Implement BiDi override mode for GDScript source.

This commit is contained in:
bruvzg
2023-01-18 09:33:35 +02:00
parent b5f3ac522e
commit 5361ec9f43
21 changed files with 178 additions and 55 deletions

View File

@@ -483,6 +483,7 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR);
BIND_ENUM_CONSTANT(DIRECTION_RTL);
BIND_ENUM_CONSTANT(DIRECTION_INHERITED);
/* Orientation */
BIND_ENUM_CONSTANT(ORIENTATION_HORIZONTAL);
@@ -599,7 +600,7 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_FILE);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_EMAIL);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_LIST);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_NONE);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_GDSCRIPT);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_CUSTOM);
}
@@ -1692,22 +1693,22 @@ String TextServer::strip_diacritics(const String &p_string) const {
return result;
}
TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
TypedArray<Vector2i> ret;
TypedArray<Vector3i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
TypedArray<Vector3i> ret;
switch (p_parser_type) {
case STRUCTURED_TEXT_URI: {
int prev = 0;
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == '.') || (p_text[i] == ':') || (p_text[i] == '&') || (p_text[i] == '=') || (p_text[i] == '@') || (p_text[i] == '?') || (p_text[i] == '#')) {
if (prev != i) {
ret.push_back(Vector2i(prev, i));
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
ret.push_back(Vector2i(i, i + 1));
ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
}
}
if (prev != p_text.length()) {
ret.push_back(Vector2i(prev, p_text.length()));
ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
}
} break;
case STRUCTURED_TEXT_FILE: {
@@ -1715,14 +1716,14 @@ TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_pa
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == ':')) {
if (prev != i) {
ret.push_back(Vector2i(prev, i));
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
ret.push_back(Vector2i(i, i + 1));
ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
}
}
if (prev != p_text.length()) {
ret.push_back(Vector2i(prev, p_text.length()));
ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
}
} break;
case STRUCTURED_TEXT_EMAIL: {
@@ -1731,19 +1732,19 @@ TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_pa
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '@') && local) { // Add full "local" as single context.
local = false;
ret.push_back(Vector2i(prev, i));
ret.push_back(Vector2i(i, i + 1));
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
} else if (!local && (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
if (prev != i) {
ret.push_back(Vector2i(prev, i));
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
ret.push_back(Vector2i(i, i + 1));
ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
}
}
if (prev != p_text.length()) {
ret.push_back(Vector2i(prev, p_text.length()));
ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
}
} break;
case STRUCTURED_TEXT_LIST: {
@@ -1752,18 +1753,97 @@ TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_pa
int prev = 0;
for (int i = 0; i < tags.size(); i++) {
if (prev != i) {
ret.push_back(Vector2i(prev, prev + tags[i].length()));
ret.push_back(Vector3i(prev, prev + tags[i].length(), TextServer::DIRECTION_INHERITED));
}
ret.push_back(Vector2i(prev + tags[i].length(), prev + tags[i].length() + 1));
ret.push_back(Vector3i(prev + tags[i].length(), prev + tags[i].length() + 1, TextServer::DIRECTION_INHERITED));
prev = prev + tags[i].length() + 1;
}
}
} break;
case STRUCTURED_TEXT_GDSCRIPT: {
bool in_string_literal = false;
bool in_string_literal_single = false;
bool in_id = false;
int prev = 0;
for (int i = 0; i < p_text.length(); i++) {
char32_t c = p_text[i];
if (in_string_literal) {
if (c == '\\') {
i++;
continue; // Skip escaped chars.
} else if (c == '\"') {
// String literal end, push string and ".
if (prev != i) {
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
prev = i + 1;
ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
in_string_literal = false;
}
} else if (in_string_literal_single) {
if (c == '\\') {
i++;
continue; // Skip escaped chars.
} else if (c == '\'') {
// String literal end, push string and '.
if (prev != i) {
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
prev = i + 1;
ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
in_string_literal_single = false;
}
} else if (in_id) {
if (!is_unicode_identifier_continue(c)) {
// End of id, push id.
if (prev != i) {
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
prev = i;
in_id = false;
}
} else if (is_unicode_identifier_start(c)) {
// Start of new id, push prev element.
if (prev != i) {
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
prev = i;
in_id = true;
} else if (c == '\"') {
// String literal start, push prev element and ".
if (prev != i) {
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
prev = i + 1;
ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
in_string_literal = true;
} else if (c == '\'') {
// String literal start, push prev element and '.
if (prev != i) {
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
prev = i + 1;
ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
in_string_literal_single = true;
} else if (c == '#') {
// Start of comment, push prev element and #, skip the rest of the text.
if (prev != i) {
ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
prev = i + 1;
ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
break;
}
}
if (prev < p_text.length()) {
ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
}
} break;
case STRUCTURED_TEXT_CUSTOM:
case STRUCTURED_TEXT_NONE:
case STRUCTURED_TEXT_DEFAULT:
default: {
ret.push_back(Vector2i(0, p_text.length()));
ret.push_back(Vector3i(0, p_text.length(), TextServer::DIRECTION_INHERITED));
}
}
return ret;