reinstalling GDUnit from assetlib
Some checks failed
Create tag and build when new code gets to main / Export (push) Failing after 6m41s

This commit is contained in:
2026-01-26 09:05:55 +01:00
parent 4095f818f6
commit bdce8b969c
438 changed files with 22833 additions and 17 deletions

View File

@@ -0,0 +1,62 @@
class_name CmdArgumentParser
extends RefCounted
var _options :CmdOptions
var _tool_name :String
var _parsed_commands :Dictionary = Dictionary()
func _init(p_options :CmdOptions, p_tool_name :String) -> void:
_options = p_options
_tool_name = p_tool_name
func parse(args :Array, ignore_unknown_cmd := false) -> GdUnitResult:
_parsed_commands.clear()
# parse until first program argument
while not args.is_empty():
var arg :String = args.pop_front()
if arg.find(_tool_name) != -1:
break
if args.is_empty():
return GdUnitResult.empty()
# now parse all arguments
while not args.is_empty():
var cmd :String = args.pop_front()
var option := _options.get_option(cmd)
if option:
if _parse_cmd_arguments(option, args) == -1:
return GdUnitResult.error("The '%s' command requires an argument!" % option.short_command())
elif not ignore_unknown_cmd:
return GdUnitResult.error("Unknown '%s' command!" % cmd)
return GdUnitResult.success(_parsed_commands.values())
func options() -> CmdOptions:
return _options
func _parse_cmd_arguments(option: CmdOption, args: Array) -> int:
var command_name := option.short_command()
var command: CmdCommand = _parsed_commands.get(command_name, CmdCommand.new(command_name))
if option.has_argument():
if not option.is_argument_optional() and args.is_empty():
return -1
if _is_next_value_argument(args):
var value: String = args.pop_front()
command.add_argument(value)
elif not option.is_argument_optional():
return -1
_parsed_commands[command_name] = command
return 0
func _is_next_value_argument(args: PackedStringArray) -> bool:
if args.is_empty():
return false
return _options.get_option(args[0]) == null

View File

@@ -0,0 +1 @@
uid://d4hd3vc50jltg

View File

@@ -0,0 +1,27 @@
class_name CmdCommand
extends RefCounted
var _name: String
var _arguments: PackedStringArray
func _init(p_name :String, p_arguments := []) -> void:
_name = p_name
_arguments = PackedStringArray(p_arguments)
func name() -> String:
return _name
func arguments() -> PackedStringArray:
return _arguments
func add_argument(arg :String) -> void:
@warning_ignore("return_value_discarded")
_arguments.append(arg)
func _to_string() -> String:
return "%s:%s" % [_name, ", ".join(_arguments)]

View File

@@ -0,0 +1 @@
uid://w4mr1j0k0l

View File

@@ -0,0 +1,136 @@
class_name CmdCommandHandler
extends RefCounted
const CB_SINGLE_ARG = 0
const CB_MULTI_ARGS = 1
const NO_CB := Callable()
var _cmd_options :CmdOptions
# holds the command callbacks by key:<cmd_name>:String and value: [<cb single arg>, <cb multible args>]:Array
# Dictionary[String, Array[Callback]
var _command_cbs :Dictionary
func _init(cmd_options: CmdOptions) -> void:
_cmd_options = cmd_options
# register a callback function for given command
# cmd_name short name of the command
# fr_arg a funcref to a function with a single argument
func register_cb(cmd_name: String, cb: Callable) -> CmdCommandHandler:
var registered_cb: Array = _command_cbs.get(cmd_name, [NO_CB, NO_CB])
if registered_cb[CB_SINGLE_ARG]:
push_error("A function for command '%s' is already registered!" % cmd_name)
return self
if not _validate_cb_signature(cb, TYPE_STRING):
push_error(
("The callback '%s:%s' for command '%s' has invalid function signature. "
+"The callback signature must be 'func name(value: PackedStringArray)'")
% [cb.get_object().get_class(), cb.get_method(), cmd_name])
return null
registered_cb[CB_SINGLE_ARG] = cb
_command_cbs[cmd_name] = registered_cb
return self
# register a callback function for given command
# cb a funcref to a function with a variable number of arguments but expects all parameters to be passed via a single Array.
func register_cbv(cmd_name: String, cb: Callable) -> CmdCommandHandler:
var registered_cb: Array = _command_cbs.get(cmd_name, [NO_CB, NO_CB])
if registered_cb[CB_MULTI_ARGS]:
push_error("A function for command '%s' is already registered!" % cmd_name)
return self
if not _validate_cb_signature(cb, TYPE_PACKED_STRING_ARRAY):
push_error(
("The callback '%s:%s' for command '%s' has invalid function signature. "
+"The callback signature must be 'func name(value: PackedStringArray)'")
% [cb.get_object().get_class(), cb.get_method(), cmd_name])
return null
registered_cb[CB_MULTI_ARGS] = cb
_command_cbs[cmd_name] = registered_cb
return self
func _validate() -> GdUnitResult:
var errors := PackedStringArray()
# Dictionary[StringName, String]
var registered_cbs := Dictionary()
for cmd_name in _command_cbs.keys() as Array[String]:
var cb: Callable = (_command_cbs[cmd_name][CB_SINGLE_ARG]
if _command_cbs[cmd_name][CB_SINGLE_ARG]
else _command_cbs[cmd_name][CB_MULTI_ARGS])
if cb != NO_CB and not cb.is_valid():
@warning_ignore("return_value_discarded")
errors.append("Invalid function reference for command '%s', Check the function reference!" % cmd_name)
if _cmd_options.get_option(cmd_name) == null:
@warning_ignore("return_value_discarded")
errors.append("The command '%s' is unknown, verify your CmdOptions!" % cmd_name)
# verify for multiple registered command callbacks
if cb != NO_CB:
var cb_method := cb.get_method()
if registered_cbs.has(cb_method):
var already_registered_cmd :String = registered_cbs[cb_method]
@warning_ignore("return_value_discarded")
errors.append("The function reference '%s' already registerd for command '%s'!" % [cb_method, already_registered_cmd])
else:
registered_cbs[cb_method] = cmd_name
if errors.is_empty():
return GdUnitResult.success(true)
return GdUnitResult.error("\n".join(errors))
func execute(commands: Array[CmdCommand]) -> GdUnitResult:
var result := _validate()
if result.is_error():
return result
for cmd in commands:
var cmd_name := cmd.name()
if _command_cbs.has(cmd_name):
var cb_s: Callable = _command_cbs.get(cmd_name)[CB_SINGLE_ARG]
var arguments := cmd.arguments()
var cmd_option := _cmd_options.get_option(cmd_name)
if arguments.is_empty():
cb_s.call()
elif arguments.size() > 1:
var cb_m: Callable = _command_cbs.get(cmd_name)[CB_MULTI_ARGS]
cb_m.call(arguments)
else:
if cmd_option.type() == TYPE_BOOL:
cb_s.call(true if arguments[0] == "true" else false)
else:
cb_s.call(arguments[0])
return GdUnitResult.success(true)
func _validate_cb_signature(cb: Callable, arg_type: int) -> bool:
for m in cb.get_object().get_method_list():
if m["name"] == cb.get_method():
@warning_ignore("unsafe_cast")
return _validate_func_arguments(m["args"] as Array, arg_type)
return true
func _validate_func_arguments(arguments: Array, arg_type: int) -> bool:
# validate we have a single argument
if arguments.size() > 1:
return false
# a cb with no arguments is also valid
if arguments.size() == 0:
return true
# validate argument type
var arg: Dictionary = arguments[0]
@warning_ignore("unsafe_cast")
if arg["usage"] as int == PROPERTY_USAGE_NIL_IS_VARIANT:
return true
if arg["type"] != arg_type:
return false
return true

View File

@@ -0,0 +1 @@
uid://ccm3ivfiaf3i7

View File

@@ -0,0 +1,61 @@
class_name CmdOption
extends RefCounted
var _commands :PackedStringArray
var _help :String
var _description :String
var _type :int
var _arg_optional :bool = false
# constructs a command option by given arguments
# commands : a string with comma separated list of available commands begining with the short form
# help: a help text show howto use
# description: a full description of the command
# type: the argument type
# arg_optional: defines of the argument optional
func _init(p_commands :String, p_help :String, p_description :String, p_type :int = TYPE_NIL, p_arg_optional :bool = false) -> void:
_commands = p_commands.replace(" ", "").replace("\t", "").split(",")
_help = p_help
_description = p_description
_type = p_type
_arg_optional = p_arg_optional
func commands() -> PackedStringArray:
return _commands
func short_command() -> String:
return _commands[0]
func help() -> String:
return _help
func description() -> String:
return _description
func type() -> int:
return _type
func is_argument_optional() -> bool:
return _arg_optional
func has_argument() -> bool:
return _type != TYPE_NIL
func describe() -> String:
if help().is_empty():
return " %-32s %s \n" % [commands(), description()]
return " %-32s %s \n %-32s %s\n" % [commands(), description(), "", help()]
func _to_string() -> String:
return describe()

View File

@@ -0,0 +1 @@
uid://ccnb2ah35atho

View File

@@ -0,0 +1,31 @@
class_name CmdOptions
extends RefCounted
var _default_options :Array[CmdOption]
var _advanced_options :Array[CmdOption]
func _init(p_options :Array[CmdOption] = [], p_advanced_options :Array[CmdOption] = []) -> void:
# default help options
_default_options = p_options
_advanced_options = p_advanced_options
func default_options() -> Array[CmdOption]:
return _default_options
func advanced_options() -> Array[CmdOption]:
return _advanced_options
func options() -> Array[CmdOption]:
return default_options() + advanced_options()
func get_option(cmd :String) -> CmdOption:
for option in options():
if Array(option.commands()).has(cmd):
return option
return null

View File

@@ -0,0 +1 @@
uid://0p8udx4tdwol