# preprocessor.gd # CORE Text Preprocessor # # This file is part of StarOpenSource CORE (SOSCORE) # Made by the StarOpenSource Project and Contributers # Licensed under GNU GPLv3 # # list/table: # Tag | Description # | Newline (DO NOT USE '\n'!) # | Text is lowercase until closing tag # | Text is UPPERCASE until closing tag # | Text is camelCase until closing tag # | Text is PascalCase until closing tag # | Text is snake_case until closing tag # | Closing tag for # | Closing tag for # | Closing tag for # | Closing tag for # | Closing tag for extends Control var logger = null @export_category("Configuration") # Enables/disables Preprocessor. @export var enabled = true # Enables/disables verbose preprocessing. DO NOT ENABLE. VERBOSE PREPROCESSING ADDS 20 LINES FOR EACH LOGGER CALL WITH PREPROCESSING ENABLED AND MAKES THE LOG UNREADABLE. ONLY ENABLE IF YOU KNOW WHAT YOU ARE DOING. # Requires Logger.enable -> true @export var verbose_logging = false # Enables/disables Preprocessor tests. Please do not disable as testing the preprocessor can help catch bugs early. # Requires enabled -> true @export var tests_enabled = true # Controls how test results are displayed # 0 = Never show results # 1 = Only display on failure # 2 = Always display @export var tests_level = 1 var tests_executed = false var tests_log = "" var tests_success = 0 func _ready() -> void: print("preprocessor -> Initializing Preprocessor") print("preprocessor -> Delaying initialization by 0.75s") await get_tree().create_timer(0.75).timeout logger = get_node(NodePath("/root/Logger")) await get_tree().create_timer(0.05).timeout do_tests(false) if enabled: logger.diag("Preprocessor","Preprocessor ready.",false) else: logger.diag("Preprocessor","Preprocessor disabled.",false) # Performs tests on all Preprocessor features to help catch bugs while debugging. # Recommended to leave enabled because log output might look weird if the a faulty commit is installed. # Use tests_executed to check if the tests have been executed, use tests_log for the test log and # read tests_success if you want the number of successful tests. func do_tests(ignore_flag:bool = false) -> void: logger.diag("Preprocessor","Testing preprocessor...",false) # If tests are disaled and ignore_flag is false return if !tests_enabled and !ignore_flag: logger.diag("Preprocessor","Testing failed: Tests are disabled.",false) return # If the Preprocessor is not enabled return if !enabled: logger.diag("Preprocessor","Testing failed: Preprocessor is disabled.",false) return # Expected test resulsts var tests_newlines = "test_prefix_Line 1.\n _Line 2.\n _Line 3." var tests_uppercase = "a THIS TEXT SHOULD BE UPPPERCASED b" var tests_lowercase = "a this text should be lowercased b" var tests_camelcase = "a thisShouldBeCamelCasEd b" var tests_pascalcase = "a ThisShouldBePascalCasEd b" var tests_snakecase = "a this_should_be_snake_cas_ed b" var tests_escapes_newlines = "" var tests_escapes_uppercase = "" var tests_escapes_lowercase = "" var tests_escapes_camelcase = "" var tests_escapes_pascalcase = "" var tests_escapes_snakecase = "" # Actual tests performed using pre() var tests_newlines_result = process("Line 1Line 2Line 3","test_prefix","_",".") var tests_uppercase_result = process("a ThIs tExT sHoUlD bE uPpPeRcAsEd b") var tests_lowercase_result = process("a ThIs tExT sHoUlD bE lOwErCaSeD b") var tests_camelcase_result = process("a thisShould_be_camel_CASEd b") var tests_pascalcase_result = process("a thisShould_be_pascal_CASEd b") var tests_snakecase_result = process("a thisShould_be_snake_CASEd b") var tests_escapes_newlines_result = process("") var tests_escapes_uppercase_result = process("") var tests_escapes_lowercase_result = process("") var tests_escapes_camelcase_result = process("") var tests_escapes_pascalcase_result = process("") var tests_escapes_snakecase_result = process("") # Test success and log tests_success = 0 tests_log = "" # Checks if all tests are equal to their expected results and logs the result. if tests_newlines_result == tests_newlines: tests_success = tests_success+1 tests_log = "Y Test NEWLINES returned:\n" + tests_newlines_result + "\n" else: tests_log = "N Test NEWLINES returned:\n" + tests_newlines_result + "\n... instead of:\n" + tests_newlines + "\n" if tests_uppercase_result == tests_uppercase: tests_success = tests_success+1 tests_log = tests_log + "Y Test UPPERCASE returned \"" + tests_uppercase_result + "\".\n" else: tests_log = tests_log + "N Test UPPERCASE returned \"" + tests_uppercase_result + "\" instead of \"" + tests_uppercase + "\".\n" if tests_lowercase_result == tests_lowercase: tests_success = tests_success+1 tests_log = tests_log + "Y Test LOWERCASE returned \"" + tests_lowercase_result + "\".\n" else: tests_log = tests_log + "N Test LOWERCASE returned \"" + tests_lowercase_result + "\" instead of \"" + tests_lowercase + "\".\n" if tests_camelcase_result == tests_camelcase: tests_success = tests_success+1 tests_log = tests_log + "Y Test CAMELCASE returned \"" + tests_camelcase_result + "\".\n" else: tests_log = tests_log + "N Test CAMELCASE returned \"" + tests_camelcase_result + "\" instead of \"" + tests_camelcase + "\".\n" if tests_pascalcase_result == tests_pascalcase: tests_success = tests_success+1 tests_log = tests_log + "Y Test PASCALCASE returned \"" + tests_pascalcase_result + "\".\n" else: tests_log = tests_log + "N Test PASCALCASE returned \"" + tests_pascalcase_result + "\" instead of \"" + tests_pascalcase + "\".\n" if tests_snakecase_result == tests_snakecase: tests_success = tests_success+1 tests_log = tests_log + "Y Test SNAKECASE returned \"" + tests_snakecase_result + "\".\n" else: tests_log = tests_log + "N Test SNAKECASE returned \"" + tests_snakecase_result + "\" instead of \"" + tests_snakecase + "\".\n" if tests_escapes_newlines_result == tests_escapes_newlines: tests_success = tests_success+1 tests_log = tests_log + "Y Test ESCAPES_NEWLINES returned \"" + tests_escapes_newlines_result + "\".\n" else: tests_log = tests_log + "N Test ESCAPES_NEWLINES returned \"" + tests_escapes_newlines_result + "\" instead of \"" + tests_escapes_newlines + "\".\n" if tests_escapes_uppercase_result == tests_escapes_uppercase: tests_success = tests_success+1 tests_log = tests_log + "Y Test ESCAPES_UPPERCASE returned \"" + tests_escapes_uppercase_result + "\".\n" else: tests_log = tests_log + "N Test ESCAPES_UPPERCASE returned \"" + tests_escapes_uppercase_result + "\" instead of \"" + tests_escapes_uppercase + "\".\n" if tests_escapes_lowercase_result == tests_escapes_lowercase: tests_success = tests_success+1 tests_log = tests_log + "Y Test ESCAPES_LOWERCASE returned \"" + tests_escapes_lowercase_result + "\".\n" else: tests_log = tests_log + "N Test ESCAPES_LOWERCASE returned \"" + tests_escapes_lowercase_result + "\" instead of \"" + tests_escapes_lowercase + "\".\n" if tests_escapes_camelcase_result == tests_escapes_camelcase: tests_success = tests_success+1 tests_log = tests_log + "Y Test ESCAPES_CAMELCASE returned \"" + tests_escapes_camelcase_result + "\".\n" else: tests_log = tests_log + "N Test ESCAPES_CAMELCASE returned \"" + tests_escapes_camelcase_result + "\" instead of \"" + tests_escapes_camelcase + "\".\n" if tests_escapes_pascalcase_result == tests_escapes_pascalcase: tests_success = tests_success+1 tests_log = tests_log + "Y Test ESCAPES_PASCALCASE returned \"" + tests_escapes_pascalcase_result + "\".\n" else: tests_log = tests_log + "N Test ESCAPES_PASCALCASE returned \"" + tests_escapes_pascalcase_result + "\" instead of \"" + tests_escapes_pascalcase + "\".\n" if tests_escapes_snakecase_result == tests_escapes_snakecase: tests_success = tests_success+1 tests_log = tests_log + "Y Test ESCAPES_SNAKECASE returned \"" + tests_escapes_snakecase_result + "\".\n" else: tests_log = tests_log + "N Test ESCAPES_SNAKECASE returned \"" + tests_escapes_snakecase_result + "\" instead of \"." + tests_escapes_snakecase + "\".\n" tests_log = tests_log.left(tests_log.length()-1) # Removes unnecessary line. tests_executed = true # Checks if all tests were successful. If not disable the Preprocessor and print log. if tests_success == 12: enabled = true logger.diag("Preprocessor","Testing complete: All preprocessor features are working as intended.",false) if tests_level == 2: logger.diag("Preprocessor","Log:\n" + tests_log) else: enabled = false logger.error("Preprocessor","Testing failed: Preprocessor is malfunctioning and is now disabled.",false) if tests_level >= 1: logger.error("Preprocessor","Log:\n" + tests_log) # Processes tags func _newline(msg:String,prefix:String,pre_msg:String,post_msg:String,exclusion_filter:Array) -> String: if verbose_logging: logger.diag("Preprocessor","Preprocessing newlines") var prefix_space = prefix for exclusion in exclusion_filter: prefix_space = prefix_space.replace(exclusion,"") prefix_space = " ".repeat(prefix_space.length()) var msg_proc = prefix + pre_msg + msg.replace("",post_msg + "\n" + prefix_space + pre_msg) + post_msg if verbose_logging: logger.diag("Preprocessor","Preprocessed newlines") return msg_proc # Processes and tags # Warning: Please do NOT modify the while true loop. It was a pain to debug, believe me. func _case_lower(msg:String) -> String: if verbose_logging: logger.diag("Preprocessor","Preprocessing lowercasing") var msg_proc = msg while true: var index_one = msg_proc.find("") var index_two = msg_proc.find("") if index_one != -1: if index_two != -1: index_two = index_two + 5 - index_one var index_proc = msg_proc.substr(index_one,index_two) msg_proc = msg_proc.replace(index_proc,index_proc.replace("","").replace("","").to_lower()) else: logger.error("Preprocessor","Failed preprocessing message \"" + msg + "\" (stage LOWERCASE).",false) msg_proc = msg break else: break if verbose_logging: logger.diag("Preprocessor","Preprocessed lowercasing") return msg_proc # Processes and tags # Warning: Please do NOT modify the while true loop. It was a pain to debug, believe me. func _case_upper(msg:String) -> String: if verbose_logging: logger.diag("Preprocessor","Preprocessing uppercasing") var msg_proc = msg while true: var index_one = msg_proc.find("") var index_two = msg_proc.find("") if index_one != -1: if index_two != -1: index_two = index_two + 5 - index_one var index_proc = msg_proc.substr(index_one,index_two) msg_proc = msg_proc.replace(index_proc,index_proc.replace("","").replace("","").to_upper()) else: logger.error("Preprocessor","Failed preprocessing message \"" + msg + "\". (stage UPPERCASE).",false) msg_proc = msg break else: break if verbose_logging: logger.diag("Preprocessor","Preprocessed uppercasing") return msg_proc # Processes and tags # Warning: Please do NOT modify the while true loop. It was a pain to debug, believe me. func _case_camelcase(msg:String) -> String: if verbose_logging: logger.diag("Preprocessor","Preprocessing camelcasing") var msg_proc = msg while true: var index_one = msg_proc.find("") var index_two = msg_proc.find("") if index_one != -1: if index_two != -1: index_two = index_two + 5 - index_one var index_proc = msg_proc.substr(index_one,index_two) msg_proc = msg_proc.replace(index_proc,index_proc.replace("","").replace("","").to_camel_case()) else: logger.error("Preprocessor","Failed preprocessing message \"" + msg + "\". (stage CAMELCASE).",false) msg_proc = msg break else: break if verbose_logging: logger.diag("Preprocessor","Preprocessed camelcasing") return msg_proc # Processes and tags # Warning: Please do NOT modify the while true loop. It was a pain to debug, believe me. func _case_pascalcase(msg:String) -> String: if verbose_logging: logger.diag("Preprocessor","Preprocessing pascalcasing") var msg_proc = msg while true: var index_one = msg_proc.find("") var index_two = msg_proc.find("") if index_one != -1: if index_two != -1: index_two = index_two + 5 - index_one var index_proc = msg_proc.substr(index_one,index_two) msg_proc = msg_proc.replace(index_proc,index_proc.replace("","").replace("","").to_pascal_case()) else: logger.error("Preprocessor","Failed preprocessing message \"" + msg + "\". (stage PASCALCASE).",false) msg_proc = msg break else: break if verbose_logging: logger.diag("Preprocessor","Preprocessed pascalcasing") return msg_proc # Processes and tags # Warning: Please do NOT modify the while true loop. It was a pain to debug, believe me. func _case_snakecase(msg:String) -> String: if verbose_logging: logger.diag("Preprocessor","Preprocessing snakecasing") var msg_proc = msg while true: var index_one = msg_proc.find("") var index_two = msg_proc.find("") if index_one != -1: if index_two != -1: index_two = index_two + 5 - index_one var index_proc = msg_proc.substr(index_one,index_two) msg_proc = msg_proc.replace(index_proc,index_proc.replace("","").replace("","").to_snake_case()) else: logger.error("Preprocessor","Failed preprocessing message \"" + msg + "\". (stage SNAKECASE).",false) msg_proc = msg break else: break if verbose_logging: logger.diag("Preprocessor","Preprocessed snakecasing") return msg_proc # Functions to call all other functions related to *case func _case(msg:String) -> String: if verbose_logging: logger.diag("Preprocessor","Preprocessing casing") var msg_proc = _case_lower(msg) msg_proc = _case_upper(msg_proc) msg_proc = _case_camelcase(msg_proc) msg_proc = _case_pascalcase(msg_proc) msg_proc = _case_snakecase(msg_proc) if verbose_logging: logger.diag("Preprocessor","Preprocessed casing") return msg_proc # Replaces all escapes func _escapes(msg:String) -> String: if verbose_logging: logger.diag("Preprocessor","Preprocessing escapes") var msg_proc = msg.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") if verbose_logging: logger.diag("Preprocessor","Preprocessed escapes") return msg_proc # Checks for and if found stops preprocessing func _noprocess(msg:String) -> String: if verbose_logging: logger.diag("Preprocessor","Preprocessing noprocess") if msg.find("") != -1: logger.diag("Preprocessor","Preprocessed noprocess") return msg.replace("","") if verbose_logging: logger.diag("Preprocessor","Preprocessed noprocess") return msg # Executes all preprocessing functions and returns their combined work func process(msg:String,prefix:String = "",pre_msg:String = "",post_msg:String = "",exclusion_filter:Array = []) -> String: if verbose_logging: logger.diag("Preprocessor","Preprocessing a message") if !enabled: if verbose_logging: logger.diag("Preprocessor","Preprocessing failed: Preprocessor is disabled") return msg # _noprocess() returns a modified msg variable with removed. That's returned and then checked against the "real" msg variable. var msg_proc = _noprocess(msg) if msg_proc != msg: if verbose_logging: logger.diag("Preprocessor","Preprocessing cancelled: tag detected") return msg_proc msg_proc = _case(msg) msg_proc = _newline(msg_proc,prefix,pre_msg,post_msg,exclusion_filter) msg_proc = _escapes(msg_proc) if verbose_logging: logger.diag("Preprocessor","Preprocessing complete") return msg_proc