diff --git a/hypercommand.py b/hypercommand.py new file mode 100644 index 0000000..0d747d0 --- /dev/null +++ b/hypercommand.py @@ -0,0 +1,96 @@ +from helpers import * + +######################################################### +# # +# I may or may have not trademarked the name -Nemes # +# # +######################################################### + +debug_perm = "utils.hypercommand.debug" + +# cmd = the actual command +# tree = the subcommand/argument/permission/function tree +# helpnoargs = print help if no args given, else run the command function below decorator +# console = can be ran by console +def hypercommand(cmd, tree = [], helpnoargs = False, console = False): + def help_msg_get(tree): + holder = "" + for data in tree: + if len(data["cont"]) > 0: + holder += ("(" + help_msg_get(data["cont"]) + ")") + else: + holder += (data["name"] if data["type"] == "cmd" else ("<" + data["name"] + ">")) + return holder + + def help_msg(sender, tree): + for data in tree: + if len(data["cont"]) > 0: + msg(sender, "&e-&a " + (data["name"] if data["type"] == "cmd" else ("<" + data["name"] + ">")) + " " + help_msg_get(data["cont"]) + else: + msg(sender, "&e-&a " + (data["name"] if data["type"] == "cmd" else ("<" + data["name"] + ">")) + return None + + has_help = False + for data in tree: + if data["name"] == "help" and data["type"] == "cmd": + has_help = True + break + cmd = cmd.lower() + if not has_help: + tree.append({"name": "help", "perm": "utils." + cmd + ".help", "func": help_msg, "type": "cmd", "cont": []}) # type = "cmd" for subcommands or "arg" for arguments + + def decorator(function): + def get_next(sender, tree, args, all_args): + if len(args) == 0: # ran out of arguments but command is supposed to continue, print usage + data = [] + for comm in tree: + if comm["type"] == "cmd": + data.append(comm["name"]) + else: + data.append("<" + comm["name"] + ">") + return "&c" + " ".join(all_args) + " " + "/".join(data) + "..." + for comm in tree: + if comm["type"] == "cmd": + if comm["name"] == args[0]: # argument exists as a subcommand + if sender.hasPermission(comm["perm"]): + if len(comm["cont"]) > 0: # command continues + return get_next(sender, comm["cont"], args[1:], all_args) # continue in the recursive stack + else: + return comm["func"](sender, args[1:]) # run function with sender and all trailing arguments incase they are relevant + else: + return "&cNo permission" + for comm in tree: + if comm["type"] == "arg": + if len(comm["cont"]) > 0: # command continues, but this is an argument + # run the function its pointing at and substitute itself with the returned subcommand to chose + # continue in stack as if the arg was a subcommand returned by its pointer function + return get_next(sender, comm["cont"], args[0:(len(args) - 1)].insert(0, comm["func"](sender, args[0])), all_args) + else: + return comm["func"](sender, args) # run the function arg is pointing at with current arguments including this one as args[0] + return get_next(sender, tree, [], all_args[0:(len(all_args) - 1)]) + + @hook.command(cmd) + def call(sender, command, label, args): + message = run(sender, command, label, args) + if message: + msg(sender, message) + return True + + def run(sender, command, label, args): + if not is_player(sender) and not console: + return "This command can only be executed by players" + if len(args) == 0: + if helpnoargs: + help_msg(sender, tree) + return None + else: + try: + return function(sender, command, label, args) + except: + print trace() + return "&cAn internal error occured while attempting to perform this command" + return get_next(sender, tree, args, args) + + return call + return decorator +