Skip to content

Commit 112e9c4

Browse files
committed
improvement: highlight symbols in lessons
fix: correct syntax highlighting on nested function calls close #675
1 parent af49979 commit 112e9c4

1 file changed

Lines changed: 45 additions & 21 deletions

File tree

utils/TextUtils.gd

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,66 @@ extends Reference
66
const _REGEX_CACHE := {}
77

88
# Regex pattern to find [code][/code] tags
9-
const REGEX_PATTERN_CODE = "\\[code\\].+?\\[\\/code\\]"
9+
const REGEX_PATTERN_CODE = "\\[code\\](.+?)\\[\\/code\\]"
1010
# Regex pattern to find the "func" literal
1111
const REGEX_PATTERN_FUNC = "(?<func>func)"
1212
# Regex pattern to find method calls (e.g. "draw(...)")
13-
const REGEX_PATTERN_METHOD_CALL = "(?<method_name>[^\\s\\[\\]]*)(?<method_args>\\(.*?\\))"
13+
const REGEX_PATTERN_METHOD_CALL = "(?<method_name>\\w[\\w\\d]*)(?<method_args>\\(.*?\\))"
1414
# Regex pattern for numbers (with no special characters on either side)
1515
const REGEX_PATTERN_NUMBER = "(?<number>[^#\\[\\]\\(\\)]?[0-9]++\\.?[0-9][^#\\[\\]\\(\\)]?)"
16+
const REGEX_SYMBOL = "(?<symbol>[a-zA-Z][a-zA-Z0-9_]+)"
1617

1718

1819
static func bbcode_add_code_color(bbcode_text := "") -> String:
1920
if not _REGEX_CACHE:
20-
_REGEX_CACHE["regex_bbcode_code"] = RegEx.new()
21-
_REGEX_CACHE["regex_bbcode_func"] = RegEx.new()
22-
_REGEX_CACHE["regex_bbcode_method_call"] = RegEx.new()
23-
_REGEX_CACHE["regex_bbcode_number"] = RegEx.new()
24-
_REGEX_CACHE["regex_bbcode_code"].compile(REGEX_PATTERN_CODE)
25-
_REGEX_CACHE["regex_bbcode_func"].compile(REGEX_PATTERN_FUNC)
26-
_REGEX_CACHE["regex_bbcode_method_call"].compile(REGEX_PATTERN_METHOD_CALL)
27-
_REGEX_CACHE["regex_bbcode_number"].compile(REGEX_PATTERN_NUMBER)
21+
_REGEX_CACHE["regex_code"] = RegEx.new()
22+
_REGEX_CACHE["regex_func"] = RegEx.new()
23+
_REGEX_CACHE["regex_method_call"] = RegEx.new()
24+
_REGEX_CACHE["regex_number"] = RegEx.new()
25+
_REGEX_CACHE["regex_symbol"] = RegEx.new()
2826

29-
var regex_matches : Array = _REGEX_CACHE["regex_bbcode_code"].search_all(bbcode_text)
27+
_REGEX_CACHE["regex_code"].compile(REGEX_PATTERN_CODE)
28+
_REGEX_CACHE["regex_func"].compile(REGEX_PATTERN_FUNC)
29+
_REGEX_CACHE["regex_method_call"].compile(REGEX_PATTERN_METHOD_CALL)
30+
_REGEX_CACHE["regex_number"].compile(REGEX_PATTERN_NUMBER)
31+
_REGEX_CACHE["regex_symbol"].compile(REGEX_SYMBOL)
32+
33+
var regex_matches: Array = _REGEX_CACHE["regex_code"].search_all(bbcode_text)
3034
var index_delta := 0
3135

36+
var REGEX_REPLACE_MAP := {
37+
"regex_func": "[color=#%s]$func[/color]" % CodeEditorEnhancer.COLOR_KEYWORD.to_html(false),
38+
"regex_method_call":
39+
"[color=#%s]$method_name[/color]$method_args" % CodeEditorEnhancer.COLOR_MEMBER.to_html(false),
40+
"regex_number": "[color=#%s]$number[/color]" % CodeEditorEnhancer.COLOR_NUMBERS.to_html(false),
41+
"regex_symbol": "[color=#%s]$symbol[/color]" % CodeEditorEnhancer.COLOR_MEMBER.to_html(false)
42+
}
43+
3244
for regex_match in regex_matches:
3345
var index_offset = regex_match.get_start() + index_delta
34-
var match_string : String = regex_match.strings[0]
35-
var initial_length := match_string.length()
36-
37-
match_string = _REGEX_CACHE["regex_bbcode_func"].sub(match_string, "[color=#%s]$func[/color]" % CodeEditorEnhancer.COLOR_KEYWORD.to_html(false))
38-
match_string = _REGEX_CACHE["regex_bbcode_method_call"].sub(match_string, "[color=#%s]$method_name[/color]$method_args" % CodeEditorEnhancer.COLOR_MEMBER.to_html(false))
39-
match_string = _REGEX_CACHE["regex_bbcode_number"].sub(match_string, "[color=#%s]$number[/color]" % CodeEditorEnhancer.COLOR_NUMBERS.to_html(false))
40-
46+
var initial_length: int = regex_match.strings[0].length()
47+
var match_string: String = regex_match.strings[1]
48+
49+
var current_index := 0
50+
var last_closing_bracket_index := 0
51+
var colored_string := ""
52+
for regex_type in [
53+
"regex_func",
54+
"regex_method_call",
55+
"regex_number",
56+
"regex_symbol",
57+
]:
58+
var before := match_string.substr(current_index)
59+
var replaced: String = _REGEX_CACHE[regex_type].sub(match_string, REGEX_REPLACE_MAP[regex_type], false, current_index)
60+
if replaced != before:
61+
last_closing_bracket_index = match_string.rfind("]")
62+
colored_string += replaced.substr(current_index, last_closing_bracket_index)
63+
current_index = last_closing_bracket_index
64+
65+
colored_string = "[code]" + colored_string + "[/code]"
4166
bbcode_text.erase(index_offset, initial_length)
42-
bbcode_text = bbcode_text.insert(index_offset, match_string)
43-
index_delta += (match_string.length() - initial_length)
67+
bbcode_text = bbcode_text.insert(index_offset, colored_string)
68+
index_delta += (colored_string.length() - initial_length)
4469

4570
return bbcode_text
4671

@@ -113,4 +138,3 @@ static func convert_type_index_to_text(type: int) -> String:
113138
_:
114139
printerr("Type value %s should be a member of the TYPE_* enum, but it is not.")
115140
return "[ERROR, nonexistent type value %s]" % type
116-

0 commit comments

Comments
 (0)