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(name, second_name = "" , 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: "}]
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(email = "" )
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)
// self.exec
if self.root == true then self.eval_command(self.main, params)
end function
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]
if param.hasIndex("description") then param["description"] = obj[param.name ]
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["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])
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()
Thor.command_help = function(command)
print(command["name"] )
end function
Thor.exec_command = function(command, params)
if ( command["required_args"].len != 0 and params.len == 0) or params[0 ] == "-h" or params[0] == "--help" then
print("kek")
Thor.parse_params = function(command, params)
args = {}
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")
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)
end if
print(params)
end function
Thor.exec = function()
if params.len = = 0 or params[0] == "-h " or params[0] == "--help" or not self.has_command(params[0] ) then
print(Thor.cli_doc)
else
self.exec_ command(command, params[1:])
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
self.command_help (command)
return
end if
end function
if command.hasIndex("required_args") and command.hasIndex("required_commands") then
required_args_size = command["required_commands"].len + command["required_args"].len
if params.len < required_args_size then
self.command_help(command)
return
end if
end if
if command.hasIndex("options") then
print(command["options"].len)
end if
end function
libs/listLib.src
Lst = {}
Lst.to_list = function(map, shallow = false)
list = []
for i in map.indexes
if typeof(map[i]) == "map" then
if shallow == true then
list.push([i, map[i]])
else
list.push([i, Lst.to_list(map[i])])
end if
else
list.push([i, map[i]])
end if
end for
return list
end function
Lst.to_map = function(list)
l = list[0:]
map = {}
for i in indexes(l)
if typeof(l[i][1]) == "list" and l[i][1].len == 2 and typeof(l[i][1][0]) == "string" then
map[l[i][0]] = Lst.to_map(l[i][1])
else
map[l[i][0]] = l[i][1]
end if
end for
return map
end function
Lst.each = function(obj, func)
if typeof(obj) == "map" then
list = Lst.to_list(obj, true)
else
list = obj
end if
result = list[0:] //list copy.
for i in indexes(list)
if typeof(obj) == "map" then
func(result[i][0], result[i][1])
else
func(result[i])
end if
end for
end function
Lst.map = function(list, func)
result = list[0:] //list copy.
for i in indexes(list)
result[i] = func(result[i])
end for
return result
end function
Lst.reject = function(list, func)
result = list[0:] //list copy.
i = 0
while i < result.len
if func(result[i]) == true then
result.remove(i)
continue
end if
i = i + 1
end while
return result
end function
Lst.select = function(list, func)
result = list[0:] //list copy.
i = 0
while i < result.len
if func(result[i]) == false then
result.remove(i)
continue
end if
i = i + 1
end while
return result
end function
// do not rename funcc to to func it will infinite loop
Lst.lsort = function(list, funcc)
f = function(i)
return Lst.to_map([["sort_key", funcc(i)], ["obj", i]])
end function
result = Lst.map(list, @f)
result = result.sort("sort_key")
f = function(i)
return i["obj"]
end function
return Lst.map(result, @f)
end function
Lst.flat = function(list)
result = []
for i in list
if typeof(i) == "list" then
result = result + Lst.flat(i)
else
result.push(i)
end if
end for
return result
end function
Lst.uniq = function(list)
result = []
for i in list
if result.indexOf(i) == null then result.push(i)
end for
return result
end function
Lst.has_any = function(list, value)
for i in list
if i == value then return true
end for
return false
end function