Posted 20 June 2016 - 03:39 PM
Argser
pastebin get 3jkDVune argser
This is an API I wrote to help with parsing program arguments. It's made to process such things like switches (myprogram -a -b valueforb anothervalueforb) and named arguments (myprogram –named1=valuefor1 –named2), as well as simple "normal" arguments (myprogram arg1 arg2 arg3). It can also automatically convert the passed arguments to certain Lua types and preprocess them using custom functions.
Loading the API
To load the API you can use dofile() function (os.loadAPI() will not work):
local argser = dofile("argser")
Documentation
The API returns a single function to which you pass the program's arguments, setup all the switches, named arguments, value types, defaults and aliases, and parse the arguments. The parsed arguments are then returned in a table which you can then use to get the arguments.
Example
You can see an example of all the features and usage of the API:
local args = dofile("argser")(...)
:num(1, "arg1")
:num(2, "arg2", "number"):default(1)
:switch("files", true):alias("f"):func(shell.resolve):default({})
:named("argser", true):func(shell.resolve)
:named("print", true, "boolean"):alias("p"):default(false)
:alias("argser", "a")
:parse().args
for i, arg in ipairs(args) do
print(i .. ". " .. arg)
end
if args.print then
print()
for name, arg in pairs(args) do
print(name .. ": " .. textutils.serialize(arg))
end
end
If this program was saved in the root directory of the computer as "test", running it like so:
test a --argser=/argser -f argser rom --print=t 2
…would print this onto the screen:
1. a
2. 2
1: "a"
2: 2
files: {
"argser",
"rom",
}
print: true
argser: "argser"
arg1: "a"
arg2: 2
Parser methods and variables
After loading the API you can call the function, passing all the program arguments to it. It then returns a parser with which you setup all the options. The parser exposes a few functions and variables. All the functions must be called using the colon notation (eg.: parser:num(…)) and they return the parser itself for method chaining.I will be appending all example code to this:
local argser = dofile("argser")
local parser = argser(...)
:num(argumentNumber:number, [name:string], [valueType:string])
This function is meant for the "normal" numbered arguments. You can give them a name or a default value that way.
- argumentNumber - the number of the argument (1 for the first argument, 2 for the second, etc..).
- name - the name for the argument.
- valueType - the type of the argument's value. Valid types are: string, number, boolean and table.
parser:num(1, "arg1") --# the first argument
parser:num(3, "arg3", "boolean") --# the third argument
:switch(name:string, [values:boolean|number], [valueType:string])
This function is used to define a switch: give it a name and whether it accepts values or how many values it accepts.
- name - the name for the switch.
- values - if passed a boolean: true for infinite amount of values, false for no values. If passed a number then that number specifies the maximum amount of values that the switch can accept.
- valueType - the type of the argument's value. Valid types are: string, number, boolean and table.
parser:switch("switch1") --# creates a switch which doesn't accept any value
parser:switch("switch2", true, "number") --# creates a switch which accepts any amount of numbers
parser:switch("switch3", 3) --# creates a switch which accepts maximum of 3 values
:named(name:string, [hasValue:boolean], [valueType:string])
This function is used to define a named argument, which can accept a single value.
- name - the name for the named argument.
- hasValue - specifies whether the named argument accepts a value.
- valueType - the type of the argument's value. Valid types are: string, number, boolean and table.
parser:named("named1") --# creates a named argument which doesn't accept any value
parser:named("named2", true, "boolean") --# creates a named argument which accepts a boolean
:alias([name:string ,] alias:string)
This function is used to give an alias for any argument type: numbered (normal), switch or named.
- name - the name of the argument.
- alias - the alias for the argument.
parser:alias("named1", "n1") --# specifies an alias for the named argument "named1"
parser:switch("switch2"):alias("s2") --# specifies an alias for the switch "switch2"
:default([name:string ,] default:any)
This function is used to give an argument a default value.
- name - the name of the argument.
- default - the default value of the argument.
parser:default("arg1", "argument") --# gives a default value for the argument "arg1"
parser:named("named1"):default(1) --# specifies a default value for the named argument "named1"
:func([name:string ,] fn:function)
This function attaches a "processing" function which is used to process the argument. It is passed a single argument and it's return value is used as the value for the argument.
- name - the name of the argument.
- fn - the "processing" function.
parser:func("arg1", function (arg)
return "!" .. arg .. "!"
end) --# modifies the values of argument "arg1"
parser:switch("files", true):func(shell.resolve) --# shell.resolve's every argument of the switch "files"
:parse()
Parses the arguments. The parsed arguments are stored in the parser.arg table. You can access the numbered (normal) arguments by using the table as an array (eg.: parser.arg[1] for first argument) or if the argument was specified using :num() and given a name, you can access it using it's name (eg.: parser.arg.arg1 for a numbered argument named "arg1"). You can access the switche's arguments using it's name (eg.: parser.arg.switch1 for the values of "switch1"). All of the switches arguments are put into an array. If the switch doesn't accept any values and it was specified as an argument it will be set to true. You can access all named arguments using their name (eg.: parser.arg.named1 for the value of "named1"). If the named argument doesn't accept any values and it was passed as an argument it's value will be set to true.
Example:
parser:num(1, "arg1")
parser:switch("switch1", true)
parser:named("named1", true, "number"):default(1)
parser:parse()
local args = parser.args
Changelog
- 2016-06-21(2) - the API now contains a single function which you can copy-paste into your own programs.
- 2016-06-21(1) - fixed a bug with undefined named argument parsing.
- 2016-06-20 - initial public release.
Licensing
You can use and edit this API as much as you want. I only ask that you don't start redistributing it as if it was your own API.
Edited on 21 June 2016 - 06:57 PM