| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | Main.gd | 10 | ||||
| -rw-r--r-- | Main.tscn | 6 | ||||
| -rw-r--r-- | README.md | 3 | ||||
| -rw-r--r-- | addons/gdcli/Arg.gd | 64 | ||||
| -rw-r--r-- | addons/gdcli/Parser.gd | 72 | ||||
| -rw-r--r-- | project.godot | 34 |
7 files changed, 191 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dabd852 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode/ +.import/ @@ -0,0 +1,10 @@ +extends Node + + +func _ready(): + var p = Parser.new() + p.add_argument(Arg.new({triggers = ["-fly", "--fley"], n_args = 2, help = "i eat donkeys"})) + p.add_argument(Arg.new({triggers = ["-bard", "--flgersog"], n_args = 2, help = "me 4"})) + p.add_argument(Arg.new({triggers = ["--radiation"], n_args = "*", help = "i am radiation"})) + print(p.parse_arguments()) + print(p.help()) diff --git a/Main.tscn b/Main.tscn new file mode 100644 index 0000000..cc043c2 --- /dev/null +++ b/Main.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://Main.gd" type="Script" id=1] + +[node name="Main" type="Node2D"] +script = ExtResource( 1 ) diff --git a/README.md b/README.md new file mode 100644 index 0000000..298332e --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# godot cli parser + +waiting on [godot-proposals/4815](https://github.com/godotengine/godot-proposals/issues/4815) for the full experience. diff --git a/addons/gdcli/Arg.gd b/addons/gdcli/Arg.gd new file mode 100644 index 0000000..828bbf1 --- /dev/null +++ b/addons/gdcli/Arg.gd @@ -0,0 +1,64 @@ +extends Reference +class_name Arg + +var n_args := 0 +var arg_type := "" # can be * +var triggers: PoolStringArray = [] +var help := "" +var arg_names := "" +var dest := "" +var default = "" + + +func find_trigger(to_find: String) -> String: + for t in triggers: + if t == to_find: + return t + return "" + + +func _init( + options := {triggers = [], n_args = 0, help = "", dest = "", default = "", arg_names = ""} +) -> void: + help = opt_get(options, "help", "") + triggers = opt_get(options, "triggers", []) + if typeof(opt_get(options, "n_args", 0)) == TYPE_STRING: + arg_type = opt_get(options, "n_args", "") + else: + n_args = opt_get(options, "n_args", 0) + dest = opt_get(options, "dest", dest_name()) + default = opt_get(options, "default", "") + arg_names = opt_get(options, "arg_namaes", get_arg_names()) + + +func opt_get(opt: Dictionary, key: String, df): + return opt[key] if key in opt else df + + +func add_trigger(t: String) -> void: + triggers.append(t) + + +func get_arg_names(): + var r_names := "[" + if not arg_type: + for i in n_args: + r_names += " arg%s " % i + else: + r_names += " ..." + return r_names + "]" + + +func small_arg() -> String: + var small := "" + for t in triggers: + small = t if len(t) < len(small) or !small else small + return small + + +func dest_name() -> String: + return small_arg().replace("-", "") + + +func format_triggers() -> String: + return triggers.join(", ") + " " + arg_names diff --git a/addons/gdcli/Parser.gd b/addons/gdcli/Parser.gd new file mode 100644 index 0000000..d618a0f --- /dev/null +++ b/addons/gdcli/Parser.gd @@ -0,0 +1,72 @@ +extends Reference +class_name Parser + +var target_args := [] + + +func add_argument(arg: Arg): + target_args.append(arg) + + +func parse_arguments(): + var cmdline_args = Array(OS.get_cmdline_args()) + var args := {unhandled = []} + var i := -1 + var star: String + while i < len(cmdline_args) - 1: + i += 1 + var res := __search_target_args(cmdline_args[i]) + if res: + if res.n_args: + args[res.dest] = cmdline_args.slice(i + 1, i + res.n_args) + i += res.n_args + star = "" + else: + match res.arg_type: + "*": + star = res.dest + args[res.dest] = cmdline_args.slice(i + 1, i) + else: + if star: + args[star].append(cmdline_args[i]) + breakpoint + else: + args.unhandled.append(cmdline_args[i]) + for r in target_args: + if not r.dest in args: + args[r.dest] = r.default + return args + + +func __search_target_args(to_find: String) -> Arg: + for arg in target_args: + if arg.find_trigger(to_find): + return arg + return null + + +func help() -> String: + var size = 1 + for arg in target_args: # find the longest arguments + size = len(arg.format_triggers()) if len(arg.format_triggers()) > size else size + + var options := "" + var usage := "godot " + for arg in target_args: + usage += "[%s] " % arg.small_arg() + options += arg.format_triggers() + " " + + for _i in range(size - len(arg.format_triggers())): + options += " " + options += arg.help + "\n" + var help = """ +usage: {usage} + +{description} + +options: +{options} +""".format( + {usage = usage, description = "", options = options.indent(" ")} + ) + return help diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..4f9b632 --- /dev/null +++ b/project.godot @@ -0,0 +1,34 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +_global_script_classes=[ { +"base": "Reference", +"class": "Arg", +"language": "GDScript", +"path": "res://addons/Arg.gd" +}, { +"base": "Reference", +"class": "Parser", +"language": "GDScript", +"path": "res://addons/Parser.gd" +} ] +_global_script_class_icons={ +"Arg": "", +"Parser": "" +} + +[application] + +config/name="gdcli" +run/main_scene="res://Main.tscn" + +[editor] + +main_run_args=" --radiation rad crad -bard rofl" |