Open user menu
Files
libs/thor.src
Thor = {}
Thor.init = function(class, root = true)
self.class = null
self.main = null
self.__commands = {}
self.c ommands = {}
self.root = root
if class.hasIndex("name") then self.name = class.name
self.class = class
if self.class.hasIndex("main") then self.main = self.to_command("main")
for obj in self.class
if typeof(obj["value"]) == "function" then
if obj["key"][:2] == "__" then
self.__commands[obj["key"]] = self.to_command(obj["key"])
else if obj["key"] != "main" then
self.commands[obj["key"]] = self.to_command(obj["key"])
end if
end if
end for
ThorC ommand = {}
//print(self.main)
//print( self.__commands)
//print( self.commands)
ThorCommand.init = function(func, sig, name)
self.name = name
self.func = @func
if self.root == true then self.eval_command(self.main, params)
if sig.hasIndex("description") then s elf.description = sig["description"]
if sig.hasIndex("args") then
self.args = sig["args"]
end if
if sig.hasIndex("options") then
f = function(obj)
param = {}
param["name"] = obj.indexes[0]
param["description"] = obj[obj.indexes[0]]
return param
end function
self.options = Lst.map(sig["options"], @f)
end if
end function
ThorCommand.required_args = function()
f = function(obj)
return obj[-1:] == "*"
end function
// it takes a function name then returns an object with name, func key by default
// the description, options, [[required_args, optional args], [required_commands, optinal_commands]](if args is set) key is optional,
Thor.to_command = function(name)
command = {}
command["name"] = name
c ommand["func"] = self.class[name]
if self.class.hasIndex(name + "_sig") then
sig = self.class[name + "_sig"]
else
return command
end if
if sig.hasIndex("descrip tion") then command["description"] = sig["description"]
arg_to_map = function(obj)
param = {}
if typeof(obj) == "list" then param["name"] = obj[0]
param["name"] = obj
//param["name"] = obj .indexes[0]
//param["description"] = obj[obj.indexes[0]]
return param
return Lst.select(self. args, @f)
end function
ThorC ommand.optional_args = func tion()
f = function(obj)
return self.required_args .indexOf(obj) == null
end function
option_to_map = function(obj)
param = {}
param["name"] = obj.indexes[0]
param["descrip tion"] = obj[obj.indexes[0]]
return param
return Lst.select(self.args, @f)
end function
ThorCommand.options_list = func tion()
f = function(o)
return o.name
end function
return Lst.map(self.options, @f)
end function
// class divider ---------------------------------------
ThorManager = {}
ThorManager.init = function(thor)
self.thor = thor
end function
ThorManager.eval_command = function(command)
used_args = self.thor.global_args[:command.args.len]
self.thor.global_args = self.thor.global_args[command.args.len:]
if sig.hasIndex("args") then
sig["args"] = Lst.map(sig["args"], @arg_to_map)
required = function(obj)
return obj.name[-1:] == "*"
end function
command["args"] = sig["args"]
command["required_args"] = Lst.select(sig["args"], @required)
command[" optional_args"] = Lst.reject(sig["args"], @required)
f = function(obj)
return typeof(obj.name) == "list" and obj.name.len == 2 and typeof(obj.name[1]) == "map"
end function
commands = Lst.select(sig["args"], @f)
required = function(obj)
return obj.name[0][-1:] == "*"
end function
command["required_commands"] = Lst.select(commands, @required)
command[" optional_commands"] = Lst.reject(commands, @required)
f = function(obj)
sub_cli = new Thor
sub_cli.init(obj["name"][1], false)
obj["commands"] = sub_cli
obj["name"] = obj["name"][0]
return obj
end function
command["required_commands"] = Lst.map (command["required_commands"], @f)
command["optional_commands"] = Lst.map(command[" optional_commands"], @f)
end if
self.thor.used_ options = self.thor.used_ options + Lst.flat (command. options_list)
if sig.hasIndex("options") then
sig[" options"] = Lst.map(sig[" options"], @option_to_map)
command["options"] = sig["options"]
end if
command["passed_ options"] = self. options_by_key( command)
return command
end function
T hor.arg_allowed_commands = func tion(arg)
r = []
for i in arg["commands"]. commands
r.push(i["key"])
end for
return r
self.t hor.global_execu tion_queue.push( command)
end function
Thor.command_help = function(command)
out = char(10)
if self.root == true then
out = out + self.name
else
out = out + command["name"]
end if
out = out + " "
ThorManager.options_by_key = function(command)
r = {}
it_has_commands = false
get_value = function(o)
if o.indexOf("=") then
striped_options = self.thor.striped_global_options
if striped_options.indexOf(o) then
value = self.thor.global_options[striped_options.indexOf(o)]
return value[value.indexOf("=")+1:]
else
return null
end if
else
if self.thor.global_options.indexOf(i) != null then return true
return null
end if
end function
for arg in command["args"]
if arg.hasIndex("commands") then
out = out + "[" + arg["name"] + "] "
it_has_commands = true
for o in command.options_list
if typeof(o) == "list" then
v = null
for i in o
if get_value(i) != null then v = get_value(i)
end for
for i in o
r[i] = v
end for
else
out = out + "<" + arg["name"] + "> "
r[o] = get_value(o)
end if
end for
if command.hasIndex("options") then
out = out + char(10) + char(10)
out = out + "list of flags" + char(10)
for option in command.options
n = option.name
if typeof(option.name) == "list" then n = option.name.join(" ")
out = out + "<b>" + n + "</b> : " + option.description
if command.options.indexOf(option) < command.options.len - 1 then out = out + char(10)
end for
end if
return r
end function
if it_has_commands then
out = out + char(10)
for arg in command[" args"]
if arg.hasIndex("commands") then
ou t = out + char(10)
out = out + "list of valid commands for [" + arg["name"] + "]" + char(10)
for command in arg["c ommands"]. commands
out = out + "<b>" + command.value. name + "</b> : " + command.value.descri ption + char(10)
end for
end if
end for
end if
// class divider ---------------------------------------
Thor = {}
Thor.init = function(class, main_func_name)
self.class = null
self.global_ args = []
self.passed_args_coun t = 0
self.global_options = []
self.used_options = []
self.global_execution_queue = []
self.manager = new ThorManager
self.manager.init(self)
main_ command = new ThorC ommand
main_ command.init(class[main_func_name], class[main_func_ name+"_sig"], main_func_name)
self.params_to_args_o ptions(params)
self.manager.eval_command(main_command)
self.catch_errors
end function
print(out )
Thor.striped_global_options = function()
f = function(ob)
if ob.indexOf("=") then
return ob[:ob.indexOf("=")+1]
end if
end function
return Lst.map(self.global_options, @f )
end function
// returns a list with [args, options] with args beign a list and options a map
// if -h or --help is passed it will ignore all the -- and - options and return options with -h and --help set
// if a options is passed and it is not defined on the command options sig then it will exit
// if a value options is passed with no value like -f= then it will exit
Thor.parse_params = function(command, params)
Thor.params_to_args_ options = function(params)
// filter for args
f = function(p)
return p[0] == "-"
end function
args = Lst.reject(params, @f)
options = {}
if command.hasIndex("options") then
//command map
c_all_options = null
c_options = []
c_value_options = []
f = function(obj)
return obj["name"]
end function
c_all_options = Lst.map(command["options"], @f)
has_value = function(obj)
if typeof(obj) == "list" then
return obj[0].indexOf("=") != null
else
return obj.indexOf("=") != null
end if
end function
c_options = Lst.reject(c_all_options, @has_value)
c_value_options = Lst.select(c_all_options, @has_value)
// param map
f = function(param)
return param[:1] == "-" and param.indexOf("=") == null
end function
params_options = Lst.select(params, @f)
f = function(param)
if param[:2] != "--" and param.len > 2 then
r = []
for i in param[1:].values
r.push("-" + i)
end for
return r
else
return param
end if
end function
params_options = Lst.uniq(Lst.flat(Lst.map(params_options, @f)))
f = function(param)
return param[:1] == "-" and param.indexOf("=") ! = null
end function
params_value_ options = Lst.select(params, @f)
//print(c_all_options)
//print(c_options)
//print(c_value_options)
//print(params_options)
//print(params_value_options)
// check for errors
// check if undefined options was passed
f = function(p)
return p[:p.indexOf("=") + 1]
end function
vo_without_value = Lst.map(params_value_options, @f)
all_options = vo_without_value + params_options
for i in all_options
if Lst.flat(c_all_options).indexOf(i) == null then
if i == "-h" or i == "--help" then
return [args, {"-h": true, "--help": true}]
else
exit("option " + i + " is not defined, check the manual")
end if
end if
end for
f = function(param)
return param[:1] == "-" and param.indexOf("=") = = null
end function
params_options = Lst.select(params, @f)
// check if value op tions was passed without values
for i in params_value_options
if i[i.indexOf("=")+1:] == null then
exit("option " + i + " requires a value")
end if
end for
// set options to be passed for the command
c_options_by_key = {}
f = function(obj)
if typeof(obj) == "list" then
for i in obj
c_options_by_key[i] = obj
end for
else
c_options_by_key[obj] = [obj ]
end if
end function
Lst.each(c_all_options, @f)
for i in params_options
for j in c_options_by_key[i]
options[j] = true
end for
end for
for i in params_ value_option s
value = i[i.indexOf("=")+1:]
key = i[:i.indexOf("=")+1]
for j in c_options_by_key[key]
options[j[:-1]] = value
f = func tion(param)
if param[:2] != "--" and param.len > 2 then
r = []
for i in param[1:]. values
r.push("-" + i)
end for
end fo r
for i in Lst.flat(c_all _options)
if i .indexOf("=") then
key = i[:-1]
else
key = i
end if
if options.hasIndex(key) == false then
options[key] = null
end if
end for
end if
return [ args, options]
return r
else
return param
end if
end function
params_options = Lst.uniq(Lst. flat(Lst.map(params _options, @f)))
f = function(param)
return param[:1] == "-" and param .indexOf("=") != null
end function
params_value_ options = Lst.select(params, @f)
options = params_options + params_value_options
self.global_args = args
self.passed_args_count = args.len
self.global_options = options
end function
Thor.eval_command = function(command, params)
p = self.parse_params(command, params)
args = p[0]
op tions = p[1]
Thor.catch_errors = function()
f = function(c)
return c.required_args.len
end function
required_ args = Lst.map(self.global_execu tion_queue, @f)
if options.hasIndex("--help") or options.hasIndex("-h") then
self.command_help(command)
return
if self.passed_args_count < required_args.sum then
print("error: required params not passed"+char(10))
end if
if command.hasIndex("required_args") and command.hasIndex("required_commands") then
required_args_size = command["required_commands"].len + command["required_args"].len
if args.len < required_args_size then
self.command_help(command)
return
end if
end if
f = function(obj)
if obj.hasIndex("commands") then
return Thor.arg_allowed_commands(obj)
else
return "*"
end if
end function
accepted_args = Lst.map(command["args"], @f)
for i in args.indexes
if accepted_args.hasIndex(i) == false then break
if typeof(accepted_args[i]) == "list" and accepted_args[i].indexOf(args[i]) == null then
exit(args[i] + " is not a valid command, please check the docs.")
end if
end for
// push nulls to args until it is the same len ans the optional + required args len
i = 0
while i < accepted_args.len - args.len
args.push(null)
i = i + 1
end while
// TODO exec shit here
print(arg s)
// print(accepted_arg s)
print(self.striped_global_option s)
print(self.used_option s)
end function
Thor.exec_queue = function()
end function
testCLI.src
Mycli = {}
Mycli.name = "mycli"
Mycli.commands = {}
// args ending with * are required
// options ending with = require a value to be passed after the option
Mycli.commands.hello_sig = {}
Mycli.commands.hello_sig["description"] = "it says hello to you"
Mycli.commands.hello_sig["args"] = ["name*", "second_name"]
Mycli.commands.hello_sig["options"] = [{["-c", "--capitalize"]: "will capitalize your name"}, {["-f=", "--from="]: "name from the person saying hello"}]
// options that are not passed will be set to null, also if they are passed all the keys will be set to the options value
// if the functions is called with --help or -h then it wont be called and the documentation will be printed istead
Mycli.commands.hello = function(args = [], options = {})
if options["-c"] then
name = name.values[0]
name[0].upper
name = name.join("")
end if
print(["hello", name, second_name].join(" "))
end function
Mycli.main_sig = {}
Mycli.main_sig["description"] = "shit cli script"
//required args should come first than optional ones
Mycli.main_sig["args"] = ["email*", ["commands*", Mycli.commands]]
Mycli.main_sig["options"] = [{"-d": "dez"}, {["-c", "--capitalize"]: "will capitalize your name"}, {["-f=", "--from="]: "name from the person saying hello"}]
// the main fuction is the root function of the cli script
// this function will allways be called if the the required args are passed(and they are valid)
// so in this case bc we have another class as args this function will be called first
// then the matching command will be called after
Mycli.main = function(args = [], options = {})
globals["email"] = email
end function
// functions starting with __ wont trigger the main function
Mycli.__version = function()
print("0.0.1")
end function
import_code("/home/me/thor/libs/listLib.src") //requires on listlib
import_code("/home/me/thor/libs/thor.src") //requires on listlib
Thor.init(Mycli)
greetings.src
Greetings = {}
Greetings.greetings_sig = {}
Greetings.greetings_sig["description"] = "shit cli script"
//required args should come first than optional ones
Greetings.greetings_sig["args"] = ["name*", "second_name"]
Greetings.greetings_sig["options"] = [{["-c", "--capitalize"]: "the names"}, {["-f=", "--from="]: "from name"}]
Greetings.greetings = function(args = [], options = {})
print("hellow")
end function
import_code("/home/me/Thorr/libs/listLib.src") //requires on listlib
import_code("/home/me/Thorr/libs/thor.src") //requires on listlib
Thor.init(Greetings, "greetings")