120 lines
3.7 KiB
GDScript
120 lines
3.7 KiB
GDScript
extends Object
|
|
## Utility functions
|
|
|
|
|
|
static func bbcode_escape(p_text: String) -> String:
|
|
return p_text \
|
|
.replace("[", "~LB~") \
|
|
.replace("]", "~RB~") \
|
|
.replace("~LB~", "[lb]") \
|
|
.replace("~RB~", "[rb]")
|
|
|
|
|
|
static func bbcode_strip(p_text: String) -> String:
|
|
var stripped := ""
|
|
var in_brackets: bool = false
|
|
for c: String in p_text:
|
|
if c == '[':
|
|
in_brackets = true
|
|
elif c == ']':
|
|
in_brackets = false
|
|
elif not in_brackets:
|
|
stripped += c
|
|
return stripped
|
|
|
|
|
|
static func get_method_info(p_callable: Callable) -> Dictionary:
|
|
var method_info: Dictionary
|
|
var method_list: Array[Dictionary]
|
|
if p_callable.get_object() is GDScript:
|
|
method_list = p_callable.get_object().get_script_method_list()
|
|
else:
|
|
method_list = p_callable.get_object().get_method_list()
|
|
for m in method_list:
|
|
if m.name == p_callable.get_method():
|
|
method_info = m
|
|
break
|
|
if !method_info and p_callable.is_custom():
|
|
var args: Array
|
|
var default_args: Array
|
|
for i in p_callable.get_argument_count():
|
|
var argument: Dictionary
|
|
argument["name"] = "arg%d" % i
|
|
argument["type"] = TYPE_NIL
|
|
args.push_back(argument)
|
|
method_info["name"] = "<anonymous lambda>"
|
|
method_info["args"] = args
|
|
method_info["default_args"] = default_args
|
|
return method_info
|
|
|
|
|
|
## Finds the most similar string in an array.
|
|
static func fuzzy_match_string(p_string: String, p_max_edit_distance: int, p_array) -> String:
|
|
if typeof(p_array) < TYPE_ARRAY:
|
|
push_error("LimboConsole: Internal error: p_array is not an array")
|
|
return ""
|
|
if p_array.size() == 0:
|
|
return ""
|
|
var best_distance: int = 9223372036854775807
|
|
var best_match: String = ""
|
|
for i in p_array.size():
|
|
var elem := str(p_array[i])
|
|
var dist: float = _calculate_osa_distance(p_string, elem)
|
|
if dist < best_distance:
|
|
best_distance = dist
|
|
best_match = elem
|
|
return best_match if best_distance <= p_max_edit_distance else ""
|
|
|
|
|
|
## Calculates optimal string alignment distance [br]
|
|
## See: https://en.wikipedia.org/wiki/Levenshtein_distance
|
|
static func _calculate_osa_distance(s1: String, s2: String) -> int:
|
|
var s1_len: int = s1.length()
|
|
var s2_len: int = s2.length()
|
|
|
|
# Iterative approach with 3 matrix rows.
|
|
# Most of the work is done on row1 and row2 - row0 is only needed to calculate transposition cost.
|
|
var row0: PackedInt32Array # previous-previous
|
|
var row1: PackedInt32Array # previous
|
|
var row2: PackedInt32Array # current aka the one we need to calculate
|
|
row0.resize(s2_len + 1)
|
|
row1.resize(s2_len + 1)
|
|
row2.resize(s2_len + 1)
|
|
|
|
# edit distance is the number of characters to insert to get from empty string to s2
|
|
for i in range(s2_len + 1):
|
|
row1[i] = i
|
|
|
|
for i in range(s1_len):
|
|
# edit distance is the number of characters to delete from s1 to match empty s2
|
|
row2[0] = i + 1
|
|
|
|
for j in range(s2_len):
|
|
var deletion_cost: int = row1[j + 1] + 1
|
|
var insertion_cost: int = row2[j] + 1
|
|
var substitution_cost: int = row1[j] if s1[i] == s2[j] else row1[j] + 1
|
|
|
|
row2[j + 1] = min(deletion_cost, insertion_cost, substitution_cost)
|
|
|
|
if i > 1 and j > 1 and s1[i - 1] == s2[j] and s1[i - 1] == s2[j]:
|
|
var transposition_cost: int = row0[j - 1] + 1
|
|
row2[j + 1] = mini(transposition_cost, row2[j + 1])
|
|
|
|
# Swap rows.
|
|
var tmp: PackedInt32Array = row0
|
|
row0 = row1
|
|
row1 = row2
|
|
row2 = tmp
|
|
return row1[s2_len]
|
|
|
|
|
|
## Returns true, if a string is constructed of one or more space-separated valid
|
|
## command identifiers ("command" or "command sub1 sub2").
|
|
## A valid command identifier may contain only letters, digits, and underscores (_),
|
|
## and the first character may not be a digit.
|
|
static func is_valid_command_sequence(p_string: String) -> bool:
|
|
for part in p_string.split(' '):
|
|
if not part.is_valid_ascii_identifier():
|
|
return false
|
|
return true
|