Open user menu
Files
testCLI.src
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*": "first name"}, {"second_name": "second name (optional)"}]
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 = {})
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"
Mycli.main_sig["args"] = [{"email": "your email why not"}, { ["commands*", Mycli.commands]: "Accepted commands: "}]
//required args should come first than optional ones
Mycli.main_sig["args"] = [{["commands*", Mycli.commands]: "Accepted commands: "}, {"email": "your email why not"} ]
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 = {})
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)
libs/thor.src
Thor = {}
Thor.init = function(class, root = true)
self.class = null
self.main = null
self.__commands = {}
self.commands = {}
self.root = root
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
//print(self.main)
//print(self.__commands)
//print(self.commands)
if self.root == true then self.eval_command(self.main, params)
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
command["func"] = self.class[name]
if self.class.hasIndex(name + "_sig") then
sig = self.class[name + "_sig"]
else
return command
end if
if sig.hasIndex("description") then command["description"] = sig["description"]
arg_to_map = function(obj)
param = {}
param["name"] = obj.indexes[0]
param["description"] = obj[obj.indexes[0]]
return param
end function
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
if sig.hasIndex("options") then
sig["options"] = Lst.map(sig["options"], @arg_to_map)
command["options"] = sig["options"]
end if
return command
end function
Thor.has_command = function(command_name)
return self.commands.hasIndex(command_name) != 0
end function
Thor.commands_list = function()
out = self.commands_doc_header
f = function(t)
return [t[0], t[1]["description"]]
end function
commands_descs = Lst.map(Lst.to_list(self.commands, true), @f)
for desc in commands_descs
out = out + "<b>" + desc[0] + "</b> : " + desc[1]
end for
return out
end function
Thor.command_help = function(command)
print(command["name"])
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)
args = {}
// 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
exit("option " + i + " is not defined, check the manual")
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
// check if value options 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_options
value = i[i.indexOf("=")+1:]
key = i[:i.indexOf("=")+1]
for j in c_options_by_key[key]
options[j[:-1]] = value
end for
end for
//print(c_options_by_key)
//print(c_all_options)
//print(params_options)
//print(params_value_options)
print(options)
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]
end function
Thor.eval_command = function(command, params)
self.parse_params(command, params)
return
if params.len != 0 and (params[0] == "--help" or params[0] == "-h") then
p = self.parse_params(command, params)
args = p[0]
options = p[1]
if options.hasIndex( "--help") or options.hasIndex( "-h") then
self.command_help(command)
return
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 param s.len < required_args_size then
if arg s.len < required_args_size then
self.command_help(command)
return
end if
end if
if command.hasIndex( "options") then
print(c ommand["op tions"].len)
end if
f = function(obj)
return obj[" commands"]
end function
cs = Lst.map(command["required_commands"] + command[ "optional_commands"], @f)
f = function(obj)
return obj.commands
end function
cs = Lst.map(cs, @f)
f = function(obj)
return obj.indexes[0]
end function
cs = Lst.map(cs, @f)
valid_c ommands = cs
print(valid_commands)
print(args)
f = func tion(obj)
if obj.hasIndex("commands") then
return [] // todo
else
return "*"
end if
end function
accepted_args = Lst.map(command["args"], @f)
print(accepted_args)
end function