pax_global_header 0000666 0000000 0000000 00000000064 12606142114 0014507 g ustar 00root root 0000000 0000000 52 comment=b8c14144c20ddc29ea04684b34d2c659d8780f38
lua_cliargs-2.5-4/ 0000775 0000000 0000000 00000000000 12606142114 0014003 5 ustar 00root root 0000000 0000000 lua_cliargs-2.5-4/.env 0000664 0000000 0000000 00000000074 12606142114 0014575 0 ustar 00root root 0000000 0000000 GITHUB_USER="amireh"
GITHUB_REPO="lua_cliargs"
GITHUB_TOKEN= lua_cliargs-2.5-4/.gitignore 0000664 0000000 0000000 00000000103 12606142114 0015765 0 ustar 00root root 0000000 0000000 /luacov.report.out
/luacov.stats.out
/.env.local
/*.rock
**/.*.swp
lua_cliargs-2.5-4/.travis.yml 0000664 0000000 0000000 00000000360 12606142114 0016113 0 ustar 00root root 0000000 0000000 language: erlang
otp_release:
- R15B02
env:
- LUA=""
- LUA="luajit"
branches:
only:
- master
install:
- sudo apt-get install luajit
- sudo apt-get install luarocks
- sudo luarocks install busted
script: "busted spec"
lua_cliargs-2.5-4/LICENSE 0000664 0000000 0000000 00000002040 12606142114 0015004 0 ustar 00root root 0000000 0000000 Copyright (c) 2012 Ahmad Amireh
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
lua_cliargs-2.5-4/README.md 0000664 0000000 0000000 00000017604 12606142114 0015272 0 ustar 00root root 0000000 0000000 # cliargs
[](http://travis-ci.org/#!/amireh/lua_cliargs/builds)
cliargs is a command-line argument parser for Lua. It supports several types of arguments:
1. required arguments
1. optional arguments with different notations: `-short-key VALUE` and/or `--expanded-key=VALUE`
2. optional arguments with multiple-values that get appended to a list
1. optional "flag" arguments (on/off options) with notations: `-short-key` and/or `--expanded-key`
1. a single optional "splat" argument which can be repeated (must be the last argument)
Optional arguments can have default values (strings), flags always default to 'true'.
## Usage Example
See `example.lua` for an example on how to use the parser.
Try it with the following sample command lines;
```
example.lua --help
example.lua -o myfile -d --compress=gzip inputfile
example.lua --__DUMP__ -o myfile -d --compress=gzip inputfile
```
**Accessing arguments**
All types of arguments must specify a *key*. In the case of required arguments, the keys are only used in the help listings. However, for optional arguments, they are mandatory (either *--key* or *--extended-key* must be specified, the other is optional).
The `parse()` method will parse the command line and return a table with results. Accessing argument or option values in this table can be done using the key with the leading dashes omitted (`-` or `--`). When defining an option (or a flag) , you can access it using either key or expanded-key; they'll both be defined.
## Help listings `--help`
A help listing will be automatically generated and accessed using the `--help` argument. You can also force its display in the code using `cli:print_help()`.
This is the result for our example (see examples/00_general.lua):
```
Usage: cli_example.lua [OPTIONS] INPUT [OUTPUT-1 [OUTPUT-2 [...]]]
ARGUMENTS:
INPUT path to the input file (required)
OUTPUT multiple output paths (optional, default:
/dev/stdout)
OPTIONS:
-c, --compress=FILTER the filter to use for compressing output: gzip,
lzma, bzip2, or none (default: gzip)
-o FILE path to output file (default: /dev/stdout)
-d script will run in DEBUG mode
-v, --version prints the program's version and exits
--verbose the script output will be very verbose
```
## Validations
### Runtime argument validation
From a parsing point of view, there are 3 cases that need to be handled which are outlined below. If I missed something, please open a ticket!
**Missing a required argument**
```
$ lua examples/00_general.lua
cli_example.lua: error: bad number of arguments; 1-4 argument(s) must be specified, not 0; re-run with --help for usage.
```
**Missing value for an optional argument**
```
$ lua examples/00_general.lua --compress inputfile
cli_example.lua: error: option --compress requires a value to be set; re-run with --help for usage.
```
**Unknown arguments**
```
$ lua examples/00_general.lua -f inputfile
cli_example.lua: error: unknown/bad flag; -f; re-run with --help for usage.
```
### Some sanity guards
In the following cases, `cliargs` will report an error to you and terminate the running script:
1. flag options can not accept a value. For example: `cli:add_flag('-v VERSION')` will return an error
2. duplicate keys are not allowed: defining two options with the key `--input` will be rejected
## Tests
Running test specs is done using [busted](http://olivinelabs.com/busted/). You can install it using [LuaRocks](http://www.luarocks.org/), and then just call it with the `spec` folder:
```
luarocks install busted
cd /path/to/lua_cliargs/
busted spec
```
## Contributions
If you come across a bug and you'd like to patch it, please fork the repository, commit your patch, and request a pull.
## Thanks to
Many thanks to everyone who reported bugs, provided fixes, and added entirely new features:
1. [Thijs Schreijer](https://github.com/Tieske)
1. [Jack Lawson](https://github.com/ajacksified)
1. [Robert Andrew Ditthardt](https://github.com/DorianGray)
1. [Oscar Lim](https://github.com/o-lim)
*If I missed you, don't hesitate to update this file or just email me.*
## Reference
A function reference was generated using [LunaDoc](http://jgm.github.com/lunamark/lunadoc.1.html) which can be found [here](http://lua-cliargs.docs.mxvt.net).
## Changelog
Changes from 2.5.1 to 2.5.2
- No longer tracking the (legacy) tarballs in git or the luarocks package. Instead, we use the GitHub release tarballs for each version.
Changes in 2.4.0 from 2.3-4
1. All arguments now accept a callback that will be invoked when parsing of those arguments was successful
2. (**POSSIBLY BREAKING**) Default value for flags is now `nil` instead of `false`. This will only affect existing behavior if you were explicitly testing unset flags to equal `false` (i.e. `if flag == false then`) as opposed to `if flag then` (or `if not flag then`).
3. Minor bugfixes
Changes in 2.3.0
1. the parser will now understand `--` to denote the end of optional arguments and will map whatever comes after it to required/splat args
2. `-short VALUE` is now properly supported, so is `-short=VALUE`
3. short-key options can now officially be composed of more than 1 character
4. the parser now accepts callbacks that will be invoked as soon as options are parsed so that you can bail out of parsing preemptively (like for `--version` or `--help` options)
5. options can now accept multiple values via multiple invocations if a table was provided as a default value (passed-in values will be appended to that list)
Changes in 2.2-0 from 2.1-2
1. the `=` that separates keys from values in the `--expanded-key` notation is no longer mandatory; using either a space or a `=` will map the value to the key (e.g., `--compress lzma` is equal to `--compress=lzma`)
Changes in 2.0.0 from 1.x.x
1. added the 'splat' argument, an optional repetitive argument for which a maximum number of occurrences can be set
1. removed the reference, arguments are now solely returned by their key/expanded-key (BREAKING!)
1. removed object overhead and the `new()` method as the library will only be used once on program start-up (BREAKING!)
1. after parsing completed successfully, the library will effectively delete itself to free resources (BREAKING!)
1. option/flag is now allowed with only an expanded-key defined
1. Debug aid implemented; adding a first option `--__DUMP__`, will dump the results of parsing the command line. Especially for testing how to use the commandline with arguments containing spaces either quoted or not.
1. the `print_usage()` and `print_help()` now have a 'noprint' parameter that will not print the message, but return it as an error string (`nil + errmsg`)
## License
The code is released under the MIT terms. Feel free to use it in both open and closed software as you please.
Copyright (c) 2011-2012 Ahmad Amireh
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
lua_cliargs-2.5-4/bin/ 0000775 0000000 0000000 00000000000 12606142114 0014553 5 ustar 00root root 0000000 0000000 lua_cliargs-2.5-4/bin/coverage 0000775 0000000 0000000 00000000447 12606142114 0016301 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# Run busted and collect spec coverage using LuaCov.
# Output will be found at /luacov.report.out.
#
# Usage:
#
# $ ./bin/coverage
# $ cat luacov.report.out
busted -c
luacov src/cliargs.lua
rm luacov.stats.out
grep -zPo "(?s)={10,}\nSummary\n={10,}.+" luacov.report.out lua_cliargs-2.5-4/bin/release 0000775 0000000 0000000 00000004572 12606142114 0016131 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
[ -f ".env" ] && source ".env"
[ -f ".env.local" ] && source ".env.local"
function abort {
echo -e "\e[00;31m[ FAILED ]\e[00m ${1}"
exit 1
}
function confirm {
echo "${1} [y/N]"
read confirmation
if [ "${confirmation}" != "y" ]; then
exit 0
fi
}
[ -z "${GITHUB_TOKEN}" ] && abort "Missing GITHUB_TOKEN env variable."
[ -z "${GITHUB_USER}" ] && abort "Missing GITHUB_USER env variable."
[ -z "${GITHUB_REPO}" ] && abort "Missing GITHUB_REPO env variable."
[ -z "${LUAROCKS_API_KEY}" ] && abort "Missing LUAROCKS_API_KEY env variable."
VERSION=$1
SRC_FILE="src/cliargs.lua"
# VERSION=$(grep "version" lua_cliargs-*.rockspec | cut -d' ' -f3 | sed 's/"//g')
SRC_VERSION=$(grep "_VERSION" src/cliargs.lua | sed -e 's/.*=//' -e 's/.* //' -e 's/"//g')
NEW_ROCKSPEC="lua_cliargs-${VERSION}.rockspec"
OLD_ROCKSPEC="lua_cliargs-${SRC_VERSION}.rockspec"
if [ "${VERSION}" == "${SRC_VERSION}" ]; then
abort "Version specified is the same as the current one in rockspec"
fi
# Publish to GitHub
JSON_PAYLOAD=$(
printf '{
"tag_name": "v%s",
"target_commitish": "master",
"name": "v%s",
"body": "Release of version %s",
"draft": false,
"prerelease": false
}' $VERSION $VERSION $VERSION
)
echo $JSON_PAYLOAD
echo "Releasing version ${VERSION}..."
if [ ! -f $OLD_ROCKSPEC ]; then
abort "Version in ${SRC_FILE} does not match the rockspec file!"
fi
# rename rockspec file
mv $OLD_ROCKSPEC $NEW_ROCKSPEC
# bump version in rockspec
perl -p -i -e "s/${SRC_VERSION}/${VERSION}/g" $NEW_ROCKSPEC
# bump version in src
perl -p -i -e "s/${SRC_VERSION}/${VERSION}/" $SRC_FILE
confirm "rockspec and source file have been modified, please confirm the changes. Proceed?"
echo "Creating git release v${VERSION}..."
git add $NEW_ROCKSPEC
git rm $OLD_ROCKSPEC
git add $SRC_FILE
git commit -m "Release v${VERSION}"
git push origin master
echo "Done."
confirm "Create a new GitHub release?"
# the API will automatically create the tag for us, no need to do it manually!
curl \
--data "$JSON_PAYLOAD" \
-X POST \
-H "Content-Type: application/json; charset=utf-8" \
-H "Accept: application/json" \
"https://api.github.com/repos/${GITHUB_USER}/${GITHUB_REPO}/releases?access_token=${GITHUB_TOKEN}"
echo "Done."
confirm "Publish to luarocks?"
luarocks --api-key=$LUAROCKS_API_KEY upload $NEW_ROCKSPEC
echo -e "\e[00;32m[ SUCCESS ]\e[00m"
lua_cliargs-2.5-4/doc/ 0000775 0000000 0000000 00000000000 12606142114 0014550 5 ustar 00root root 0000000 0000000 lua_cliargs-2.5-4/doc/cliargs.html 0000664 0000000 0000000 00000014507 12606142114 0017071 0 ustar 00root root 0000000 0000000
cliargs
cliargs
cli:set_name(name)
Assigns the name of the program which will be used for logging.
cli:add_arg(key, desc)
Defines a required argument. Required arguments have no special notation and are order-sensitive. Note: the value will be stored in args[@key]. Aliases: add_argument
Parameters
key: the argument’s “name” that will be displayed to the user
desc: a description of the argument
Usage example
The following will parse the argument (if specified) and set its value in args["root"]: cli:add_arg("root", "path to where root scripts can be found")
cli:optarg(key, desc, default, maxcount)
Defines an optional argument (or more than one). There can be only 1 optional argument, and is has to be the last one on the argumentlist. Note: the value will be stored in args[@key]. The value will be a ‘string’ if ‘maxcount == 1’, or a table if ‘maxcount > 1’
Parameters
key: the argument’s “name” that will be displayed to the user
desc: a description of the argument
default: optional; specify a default value (the default is "")
maxcount: optional; specify the maximum number of occurences allowed (default is 1)
Usage example
The following will parse the argument (if specified) and set its value in args["root"]: cli:add_arg("root", "path to where root scripts can be found", "", 2) The value returned will be a table with at least 1 entry and a maximum of 2 entries
cli:add_opt(key, desc, default)
Defines an option. Optional arguments can use 3 different notations, and can accept a value. Aliases: add_option
Parameters
key: the argument identifier, can be either -key, or -key, --expanded-key: if the first notation is used then a value can be defined after a space ('-key VALUE'), if the 2nd notation is used then a value can be defined after an = ('-key, --expanded-key=VALUE'). As a final option it is possible to only use the expanded key (eg. '--expanded-key') both with and without a value specified.
desc: a description for the argument to be shown in –help
default: optional; specify a default value (the default is "")
Usage example
The following option will be stored in args["i"] and args["input"] with a default value of my_file.txt: cli:add_option("-i, --input=FILE", "path to the input file", "my_file.txt")
cli:add_flag(key, desc)
Define a flag argument (on/off). This is a convenience helper for cli.addopt(). See cli.addopt() for more information.
Parameters
key: the argument’s key
desc: a description of the argument to be displayed in the help listing
cli:parse(noprint, dump)
Parses the arguments found in #arg and returns a table with the populated values. (NOTE: after succesful parsing, the module will delete itself to free resources) Aliases: parse_args
Parameters
noprint: set this flag to prevent any information (error or help info) from being printed
dump: set this flag to dump the parsed variables for debugging purposes, alternatively set the first option to –DEBUG (option with 2 trailing and leading underscores) to dump at runtime.
Returns
a table containing the keys specified when the arguments were defined along with the parsed values, or nil + error message (–help option is considered an error and returns nil + help message)
cli:print_usage(noprint)
Prints the USAGE heading.
Parameters
noprint: set this flag to prevent the line from being printed
Returns
a string with the USAGE message.
cli:print_help(noprint)
Prints the HELP information.
Parameters
noprint: set this flag to prevent the information from being printed
Returns
a string with the HELP message.
cli:set_colsz(key_cols, desc_cols)
Sets the amount of space allocated to the argument keys and descriptions in the help listing. The sizes are used for wrapping long argument keys and descriptions.
Parameters
key_cols: the number of columns assigned to the argument keys, set to 0 to auto detect (default: 0)
desc_cols: the number of columns assigned to the argument descriptions, set to 0 to auto set the total width to 72 (default: 0)
Assigns the name of the program which will be used for logging.
cli:add_arg(key, desc)
Defines a required argument. Required arguments have no special notation and are order-sensitive. Note: the value will be stored in args[@key]. Aliases: add_argument
Parameters
key: the argument’s “name” that will be displayed to the user
desc: a description of the argument
Usage example
The following will parse the argument (if specified) and set its value in args["root"]: cli:add_arg("root", "path to where root scripts can be found")
cli:optarg(key, desc, default, maxcount)
Defines an optional argument (or more than one). There can be only 1 optional argument, and is has to be the last one on the argumentlist. Note: the value will be stored in args[@key]. The value will be a ‘string’ if ‘maxcount == 1’, or a table if ‘maxcount > 1’
Parameters
key: the argument’s “name” that will be displayed to the user
desc: a description of the argument
default: optional; specify a default value (the default is "")
maxcount: optional; specify the maximum number of occurences allowed (default is 1)
Usage example
The following will parse the argument (if specified) and set its value in args["root"]: cli:add_arg("root", "path to where root scripts can be found", "", 2) The value returned will be a table with at least 1 entry and a maximum of 2 entries
cli:add_opt(key, desc, default)
Defines an option. Optional arguments can use 3 different notations, and can accept a value. Aliases: add_option
Parameters
key: the argument identifier, can be either -key, or -key, --expanded-key: if the first notation is used then a value can be defined after a space ('-key VALUE'), if the 2nd notation is used then a value can be defined after an = ('-key, --expanded-key=VALUE'). As a final option it is possible to only use the expanded key (eg. '--expanded-key') both with and without a value specified.
desc: a description for the argument to be shown in –help
default: optional; specify a default value (the default is "")
Usage example
The following option will be stored in args["i"] and args["input"] with a default value of my_file.txt: cli:add_option("-i, --input=FILE", "path to the input file", "my_file.txt")
cli:add_flag(key, desc)
Define a flag argument (on/off). This is a convenience helper for cli.addopt(). See cli.addopt() for more information.
Parameters
key: the argument’s key
desc: a description of the argument to be displayed in the help listing
cli:parse(noprint, dump)
Parses the arguments found in #arg and returns a table with the populated values. (NOTE: after succesful parsing, the module will delete itself to free resources) Aliases: parse_args
Parameters
noprint: set this flag to prevent any information (error or help info) from being printed
dump: set this flag to dump the parsed variables for debugging purposes, alternatively set the first option to –DEBUG (option with 2 trailing and leading underscores) to dump at runtime.
Returns
a table containing the keys specified when the arguments were defined along with the parsed values, or nil + error message (–help option is considered an error and returns nil + help message)
cli:print_usage(noprint)
Prints the USAGE heading.
Parameters
noprint: set this flag to prevent the line from being printed
Returns
a string with the USAGE message.
cli:print_help(noprint)
Prints the HELP information.
Parameters
noprint: set this flag to prevent the information from being printed
Returns
a string with the HELP message.
cli:set_colsz(key_cols, desc_cols)
Sets the amount of space allocated to the argument keys and descriptions in the help listing. The sizes are used for wrapping long argument keys and descriptions.
Parameters
key_cols: the number of columns assigned to the argument keys, set to 0 to auto detect (default: 0)
desc_cols: the number of columns assigned to the argument descriptions, set to 0 to auto set the total width to 72 (default: 0)
lua_cliargs-2.5-4/doc/lunadoc.css 0000664 0000000 0000000 00000000633 12606142114 0016711 0 ustar 00root root 0000000 0000000 body { font-family: Georgia, serif; }
h3.declaration { margin-bottom: 0.5em; }
div.section { clear: both; border-top: 2px solid #eee; }
code,pre { font-family: Courier, monospace; font-size: 90%; }
div#index { position: absolute; left: 1em; top: 1em; width:14em; }
div#content { position: absolute; left: 15em; top: 0.5em; padding-left: 2em; max-width: 40em; padding-bottom: 1em; border-left: 1px solid #555; }
lua_cliargs-2.5-4/examples/ 0000775 0000000 0000000 00000000000 12606142114 0015621 5 ustar 00root root 0000000 0000000 lua_cliargs-2.5-4/examples/00_general.lua 0000775 0000000 0000000 00000005130 12606142114 0020242 0 ustar 00root root 0000000 0000000 --[[
Try this file with the following commands lines;
example.lua --help
example.lua -o myfile -d --compress=gzip inputfile
example.lua --__DUMP__ -o myfile -d --compress=gzip inputfile
--]]
local cli = require "../src/cliargs"
local function print_version(key, value, altkey)
-- this is called when the flag -v or --version is set
if key == 'version' then
print("cli_example.lua: version 1.2.1")
os.exit(0)
end
end
cli:set_name("cli_example.lua")
-- Required arguments:
cli:add_argument("INPUT", "path to the input file")
-- cli:add_argument("OUTPUT", "path to the output file") -- Using an alias for add_argument
-- Optional (repetitive) arguments
-- only the last argument can be optional. Being set to maximum 3 optionals.
cli:optarg("OUTPUT", "multiple output paths", "/dev/stdout", 3)
-- Optional parameters:
cli:add_option("-c, --compress=FILTER", "the filter to use for compressing output: gzip, lzma, bzip2, or none", "gzip")
cli:add_option("-o FILE", "path to output file", "/dev/stdout")
-- Flags: a flag is a boolean option. Defaults to false
-- A flag with short-key notation only
cli:add_flag("-d", "script will run in DEBUG mode")
-- A flag with both the short-key and --expanded-key notations, and callback function
cli:add_flag("-v, --version", "prints the program's version and exits", print_version)
-- A flag with --expanded-key notation only
cli:add_flag("--verbose", "the script output will be very verbose")
-- A flag that can be negated using --no- as a prefix, but you'll still have
-- to access its value without that prefix. See below for an example.
cli:add_flag('--[no-]ice-cream', 'ice cream, or not', true)
-- Parses from _G['arg']
local args = cli:parse(arg)
if not args then
-- something wrong happened and an error was printed
os.exit(1)
elseif not args['ice-cream'] then
print('kernel panic: NO ICE CREAM?!11')
os.exit(1000)
end
-- argument parsing was successful, arguments can be found in `args`
-- upon successful parsing cliargs will delete itslef to free resources
-- for k,item in pairs(args) do print(k .. " => " .. tostring(item)) end
print("Input file: " .. args["INPUT"])
print("Output file: " .. args["o"])
if #args.OUTPUT > 0 then
print("Additional outputs:")
if type(args.OUTPUT) == "string" then
args.OUTPUT = { args.OUTPUT }
end
for i, out in ipairs(args.OUTPUT) do
print(" " .. i .. ". " .. out)
end
end
if #args['c'] == 0 or args['c'] == 'none' then
print("Won't be compressing")
else
print("Compressing using " .. args['c'])
end
if args['ice-cream'] then
print('And, one ice cream for you.')
end lua_cliargs-2.5-4/examples/01_multiple_options.lua 0000664 0000000 0000000 00000002207 12606142114 0022233 0 ustar 00root root 0000000 0000000 --[[
This example shows how to use multiple-value options that get appended into a
list.
Try this file with the following invocations;
multiple_options.lua --help
multiple_options.lua \
-i http://www.google.com \
-i http://www.yahoo.com \
-j 2 \
combined.html
--]]
local cli = require "cliargs"
cli:set_name("example.lua")
cli:optarg("OUTPUT", "Path to where the combined HTML output should be saved.", "./a.html")
cli:add_option("-i URLs...", "A url to download. You can pass in as many as needed", {} --[[ this is the important bit! ]])
cli:add_option("-j THREADS", "Concurrency threshold; the higher the number, the more files will be downloaded in parallel.", "2")
-- Parses from _G['arg']
local args = cli:parse_args()
if not args then
os.exit(1) -- something wrong happened and an error was printed
end
if #args.i > 0 then
print("Source URLs:")
for i, url in ipairs(args.i) do
print(" " .. i .. ". " .. url)
end
print("Downloading ".. #args.i .. " files in " .. tonumber(args.j) .. " threads.")
print("Output will be found at " .. args.OUTPUT)
else
print("No source URLs provided, nothing to do!")
end
lua_cliargs-2.5-4/examples/02_parse_callbacks.lua 0000664 0000000 0000000 00000001642 12606142114 0021741 0 ustar 00root root 0000000 0000000 --[[
Shows how to define a callback to be invoked as soon as an option is parsed.
Callbacks are useful for abruptive options like "--help" or "--version" where
you might want to stop the execution of the parser/program if passed.
Try this file with the following commands lines;
example.lua --version
example.lua -v
example.lua
--]]
local cli = require "cliargs"
local function print_version(key, value, altkey, opt)
-- this is called when the flag -v or --version is set
if key == 'version' then
print("example.lua: version 1.2.1")
os.exit(0)
end
end
cli:set_name("try_my_version.lua")
cli:add_flag("-v, --version", "prints the program's version and exits", print_version)
-- Parses from _G['arg']
local args = cli:parse()
if not args then
-- something wrong happened and an error was printed
os.exit(1)
end
-- if we got to this point, it means -v (or --version) were not passed:
print "Why, hi!"
lua_cliargs-2.5-4/lua_cliargs-2.5-4.rockspec 0000664 0000000 0000000 00000001240 12606142114 0020463 0 ustar 00root root 0000000 0000000 package = "lua_cliargs"
version = "2.5-4"
source = {
url = "https://github.com/amireh/lua_cliargs/archive/v2.5-4.tar.gz",
dir = "lua_cliargs-2.5-4"
}
description = {
summary = "A command-line argument parser.",
detailed = [[
This module adds support for accepting CLI
arguments easily using multiple notations and argument types.
cliargs allows you to define required, optional, and flag arguments.
]],
homepage = "https://github.com/amireh/lua_cliargs",
license = "MIT "
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
cliargs = "src/cliargs.lua"
}
}
lua_cliargs-2.5-4/spec/ 0000775 0000000 0000000 00000000000 12606142114 0014735 5 ustar 00root root 0000000 0000000 lua_cliargs-2.5-4/spec/cliargs_methods_spec.lua 0000664 0000000 0000000 00000026632 12606142114 0021632 0 ustar 00root root 0000000 0000000
-- some helper stuff for debugging
local quoted = function(s)
return "'" .. tostring(s) .. "'"
end
local dump = function(t)
print(" ============= Dump " .. tostring(t) .. " =============")
if type(t) ~= "table" then
if type(t) == "string" then
print(quoted(tostring(t)))
else
print(tostring(t))
end
else
for k,v in pairs(t) do
if type(v) == "string" then
print(quoted(k),quoted(v))
else
print(quoted(k),tostring(v))
end
end
end
print(" ============= Dump " .. tostring(t) .. " =============")
end
local cli
-- start tests
describe("Testing cliargs library methods/functions", function()
describe("testing private functions", function()
setup(function()
_G._TEST = true
package.loaded.cliargs = nil -- Busted uses it, but must force to reload to test it with _TEST
cli = require("cliargs")
end)
teardown(function()
_G._TEST = nil
end)
it("tests the private split() function", function()
-- takes: str, split-char
local expected, result
result = cli.split("hello,world",",")
expected = {"hello", "world"}
assert.is.same(result, expected)
result = cli.split("hello,world,",",")
expected = {"hello", "world"}
assert.is.same(result, expected)
result = cli.split("hello",",")
expected = {"hello"}
assert.is.same(result, expected)
result = cli.split("",",")
expected = {}
assert.is.same(result, expected)
end)
it("tests the private wordwrap() function", function()
-- takes: text, size, padding
local text = "123456789 123456789 123456789!"
local expected, result
result = cli.wordwrap(text, 10)
expected = "123456789\n123456789\n123456789!"
assert.is.same(result, expected)
-- exact length + 1 overflow
result = cli.wordwrap(text, 9)
expected = "123456789\n123456789\n123456789\n!"
assert.is.same(result, expected)
result = cli.wordwrap(text, 9, nil, true)
expected = "123456789\n123456789\n123456789!"
assert.is.same(result, expected)
result = cli.wordwrap(text, 8)
expected = "12345678\n9\n12345678\n9\n12345678\n9!"
assert.is.same(result, expected)
end)
it("tests the optarg() method", function()
local key, desc, default, maxcount = "LastArg", "The lastarg description", "lastarg default", 3
local expected = { key = key, desc = desc, default = default, maxcount = maxcount}
cli:optarg(key, desc, default, maxcount)
assert.are.same(cli.optargument, expected)
end)
end) -- private functions
describe("testing public functions", function()
setup(function()
_G._TEST = true
package.loaded.cliargs = nil -- Busted uses it, but must force to reload to test it with _TEST
cli = require("cliargs")
end)
teardown(function()
_G._TEST = nil
end)
before_each(function()
cli.optional = {}
cli.required = {}
end)
after_each(function()
end)
it("tests the add_arg() method", function()
-- takes: key, descr
local key, desc = "argname", "thedescription"
cli:add_arg(key, desc)
assert.are.equal(cli.required[1].key, key)
assert.are.equal(cli.required[1].desc, desc)
end)
describe("#add_opt()", function()
describe("given a value indicator", function()
it("should work with only a short-key", function()
-- takes: key, descr, default
local key, desc, default = "-i VALUE", "thedescription", "default"
cli:add_opt(key, desc, default)
assert.are.equal(cli.optional[1].key, "i")
assert.are.equal(cli.optional[1].desc, desc)
assert.are.equal(cli.optional[1].flag, false)
assert.are.equal(cli.optional[1].default, default)
end)
it("should work with a short-key that is longer than 1 character", function()
local key, desc, default = "-Xassembler OPTIONS", "Pass on to the assembler", ""
cli:add_opt(key, desc, default)
assert.are.equal(cli.optional[1].key, "Xassembler")
assert.are.equal(cli.optional[1].desc, desc)
assert.are.equal(cli.optional[1].flag, false)
assert.are.equal(cli.optional[1].default, default)
end)
it("should work with only expanded-key", function()
-- takes: key, descr, default
local key, desc, default = "--insert=VALUE", "thedescription", "default"
cli:add_opt(key, desc, default)
assert.are.equal(cli.optional[1].expanded_key, "insert")
assert.are.equal(cli.optional[1].desc, desc)
assert.are.equal(cli.optional[1].flag, false)
assert.are.equal(cli.optional[1].default, default)
end)
it("should work with combined short + expanded-key", function()
-- takes: key, descr, default
local key, desc, default = "-i, --insert=VALUE", "thedescription", "default"
cli:add_opt(key, desc, default)
assert.are.equal(cli.optional[1].key, "i")
assert.are.equal(cli.optional[1].expanded_key, "insert")
assert.are.equal(cli.optional[1].desc, desc)
assert.are.equal(cli.optional[1].flag, false)
assert.are.equal(cli.optional[1].default, default)
end)
it("should work with combined short + expanded-key, no comma between them", function()
-- takes: key, descr, default
local key, desc, default = "-i --insert=VALUE", "thedescription", "default"
cli:add_opt(key, desc, default)
assert.are.equal(cli.optional[1].key, "i")
assert.are.equal(cli.optional[1].expanded_key, "insert")
end)
end)
describe("given no value indicator (implicit flags)", function()
it("should work with a short-key", function()
-- takes: key, descr, default
local key, desc, default = "-i", "thedescription", "default"
cli:add_opt(key, desc, default)
assert.are.equal(cli.optional[1].key, "i")
assert.are.equal(cli.optional[1].desc, desc)
assert.are.equal(cli.optional[1].flag, true)
assert.are.equal(cli.optional[1].default, nil) -- no value = flag type option, hence nil
end)
it("should work with a short-key that is longer than 1 character", function()
-- takes: key, descr, default
local key, desc, default = "-Wno-unsigned", "thedescription"
cli:add_opt(key, desc, default)
assert.are.equal(cli.optional[1].key, "Wno-unsigned")
assert.are.equal(cli.optional[1].desc, desc)
assert.are.equal(cli.optional[1].flag, true)
assert.are.equal(cli.optional[1].default, nil) -- no value = flag type option, hence nil
end)
it("should work with only expanded-key", function()
-- takes: key, descr, default
local key, desc, default = "--insert", "thedescription", "default"
cli:add_opt(key, desc, default)
assert.are.equal(cli.optional[1].expanded_key, "insert")
assert.are.equal(cli.optional[1].desc, desc)
assert.are.equal(cli.optional[1].flag, true)
assert.are.equal(cli.optional[1].default, nil) -- no value = flag type option, hence nil
end)
it("should work with combined short + expanded-key", function()
-- takes: key, descr, default
local key, desc, default = "-i, --insert", "thedescription", "default"
cli:add_opt(key, desc, default)
assert.are.equal(cli.optional[1].key, "i")
assert.are.equal(cli.optional[1].expanded_key, "insert")
assert.are.equal(cli.optional[1].desc, desc)
assert.are.equal(cli.optional[1].flag, true)
assert.are.equal(cli.optional[1].default, nil) -- no value = flag type option, hence nil
end)
end)
end)
it("tests add_flag() for setting default value", function()
-- takes: key, descr
local key, desc = "-i, --insert", "thedescription"
cli:add_flag(key, desc)
assert.are.equal(cli.optional[1].flag, true)
assert.are.equal(cli.optional[1].default, nil)
end)
it("tests add_flag() to error-out when providing a value", function()
-- takes: key, descr
local key, desc = "-i, --insert=VALUE", "thedescription"
assert.is.error(function() cli:add_flag(key, desc) end) --'=VALUE' is not allowed for a flag
end)
it("tests add_arg() with a duplicate argument", function()
-- takes: key, descr
local key, desc = "argname", "thedescription"
cli:add_arg(key, desc)
assert.are.equal(cli.required[1].key, key) -- make sure it got added
assert.is.error(function() cli:add_arg(key, desc) end) -- this should blow up
end)
it("tests add_flag() with a duplicate argument", function()
-- takes: key, descr
local key, desc, default = "--no-insert", "thedescription", nil
cli:add_flag(key, desc, default)
assert.are.equal(cli.optional[1].expanded_key, "no-insert") -- make sure it got added
assert.is.error(function() cli:add_flag("--[no-]insert", desc) end) -- this should blow up
end)
it("tests add_opt() with a duplicate flag", function()
-- takes: key, descr
local key, desc, default = "-i, --[no-]insert", "thedescription", true
cli:add_flag(key, desc, default)
assert.are.equal(cli.optional[1].key, "i") -- make sure it got added
assert.are.equal(cli.optional[1].expanded_key, "insert") -- make sure it got added
assert.is.error(function() cli:add_opt("--no-insert", desc, '') end) -- this should blow up
assert.is.error(function() cli:add_opt("--insert", desc, '') end) -- this should blow up
end)
it("tests add_opt() with a duplicate argument", function()
-- takes: key, descr
local key, desc, default = "-i", "thedescription", "default"
cli:add_opt(key, desc, default)
assert.are.equal(cli.optional[1].key, "i") -- make sure it got added
assert.is.error(function() cli:add_opt(key, desc, default) end) -- this should blow up
end)
describe("testing the 'noprint' options", function()
local old_print, touched
setup(function()
old_print = print
local interceptor = function(...)
touched = true
return old_print(...)
end
print = interceptor
end)
teardown(function()
print = (old_print or print)
end)
before_each(function()
touched = nil
end)
after_each(function()
end)
it("tests whether print_help() does not print anything, if noprint is set (includes print_usage())", function()
local key, desc, default = "-a", "thedescription", "default"
local noprint = true
cli:add_opt(key, desc, default)
local res = cli:print_help(noprint)
assert.is.equal(type(res), "string")
assert.is.equal(nil, touched)
end)
it("tests whether a parsing error through cli_error() does not print anything, if noprint is set", function()
-- generate a parse error
local key, desc = "ARGUMENT", "thedescription"
cli:add_opt(key, desc)
local noprint = true
local args = {"arg1", "arg2", "arg3", "arg4"} -- should fail for too many arguments
local res, err = cli:parse(args, noprint)
assert.is.equal(nil, res)
assert.is.equal(type(err), "string")
assert.is.equal(nil, touched)
end)
end)
end) -- public functions
end)
lua_cliargs-2.5-4/spec/cliargs_parsing_spec.lua 0000664 0000000 0000000 00000041762 12606142114 0021633 0 ustar 00root root 0000000 0000000 local cli, defaults, result
-- some helper stuff for debugging
local quoted = function(s)
return "'" .. tostring(s) .. "'"
end
local dump = function(t)
print(" ============= Dump " .. tostring(t) .. " =============")
if type(t) ~= "table" then
print(quoted(tostring(t)))
else
for k,v in pairs(t) do
print(quoted(k),quoted(v))
end
end
print(" ============= Dump " .. tostring(t) .. " =============")
end
-- fixture
local function populate_required()
cli:add_argument("INPUT", "path to the input file")
return { ["INPUT"] = nil }
end
local function populate_optarg(cnt)
cnt = cnt or 1
cli:optarg("OUTPUT", "path to the output file", "./out", cnt)
if cnt == 1 then
return { OUTPUT = "./out" }
else
return { OUTPUT = {"./out"}}
end
end
local function populate_optionals()
cli:add_option("-c, --compress=FILTER", "the filter to use for compressing output: gzip, lzma, bzip2, or none", "gzip")
cli:add_option("-o FILE", "path to output file", "/dev/stdout")
return { c = "gzip", compress = "gzip", o = "/dev/stdout" }
end
local function populate_flags()
cli:add_flag("-v, --version", "prints the program's version and exits")
cli:add_flag("-d", "script will run in DEBUG mode")
cli:add_flag("--verbose", "the script output will be very verbose")
return { d = nil, v = nil, version = nil, verbose = nil }
end
-- start tests
describe("Testing cliargs library parsing commandlines", function()
setup(function()
_G._TEST = true
end)
teardown(function()
_G._TEST = nil
end)
before_each(function()
_G.arg = nil
package.loaded.cliargs = nil -- Busted uses it, but must force to reload
cli = require("cliargs")
end)
it("tests no arguments set, nor provided", function()
local args = {}
local result = cli:parse(args)
assert.are.same(result, {})
end)
it("tests uses global arg if arguments set not passed in", function()
_G.arg = { "--version" }
local defaults = populate_flags(cli)
defaults.v = true
defaults.version = true
local result = cli:parse(true --[[no print]])
assert.are.same(result, defaults)
end)
it("tests only optionals, nothing provided", function()
local args = {}
local defaults = populate_optionals(cli)
local result = cli:parse(args)
assert.are.same(result, defaults)
end)
it("tests only required, all provided", function()
local args = { "some_file" }
populate_required(cli)
local result = cli:parse(args)
assert.are.same(result, { ["INPUT"] = "some_file" })
end)
it("tests only optionals, all provided", function()
local args = { "-o", "/dev/cdrom", "--compress=lzma" }
populate_optionals(cli)
local result = cli:parse(args)
assert.are.same(result, { o = "/dev/cdrom", c = "lzma", compress = "lzma" })
end)
it("tests optionals + required, all provided", function()
local args = { "-o", "/dev/cdrom", "-c", "lzma", "some_file" }
populate_required(cli)
populate_optionals(cli)
local result = cli:parse(args)
assert.are.same(result, {
o = "/dev/cdrom",
c = "lzma", compress = "lzma",
["INPUT"] = "some_file"
})
end)
it("tests optional using -short-key notation", function()
local defaults = populate_optionals(cli)
defaults.c = "lzma"
defaults.compress = "lzma"
local result = cli:parse({ "-c", "lzma" })
assert.are.same(result, defaults)
end)
it("tests option using -short-key value notation", function()
_G.arg = { "-out", "outfile" }
cli:add_opt("-out VALUE", "output file")
local defaults = { out = "outfile" }
local result = cli:parse()
assert.are.same(result, defaults)
end)
it("tests optional using --expanded-key notation, --x=VALUE", function()
local defaults = populate_optionals(cli)
defaults.c = "lzma"
defaults.compress = "lzma"
local result = cli:parse({ "--compress=lzma" })
assert.are.same(result, defaults)
end)
it("tests optional using alternate --expanded-key notation, --x VALUE", function()
local defaults = populate_optionals(cli)
defaults.c = "lzma"
defaults.compress = "lzma"
local result = cli:parse({ "--compress", "lzma" })
assert.are.same(result, defaults)
end)
describe("no-flag", function()
it("can set default to false for flag", function()
cli:add_flag("-R, --[no-]recursive", "copy recursively", false)
local expected = { R = false, recursive = false }
local result = cli:parse({})
assert.are.same(expected, result)
end)
it("can set default to true for flag", function()
cli:add_flag("-R, --[no-]recursive", "copy recursively", true)
local expected = { R = true, recursive = true }
local result = cli:parse({})
assert.are.same(expected, result)
end)
it("sets flag value to false", function()
cli:add_flag("-k, --[no-]keep-going", "continue as much as possible after an error", true)
local expected = { k = false, ['keep-going'] = false }
local result = cli:parse({ "--no-keep-going" })
assert.are.same(expected, result)
end)
it("sets flag value true then overwrites to false", function()
cli:add_flag("-k, --[no-]keep-going", "continue as much as possible after an error", true)
local expected = { k = false, ['keep-going'] = false }
local result = cli:parse({ "-k", "--no-keep-going" })
assert.are.same(expected, result)
end)
it("sets flag value false then overwrites to true", function()
cli:add_flag("-k, --[no-]keep-going", "continue as much as possible after an error", true)
local expected = { k = true, ['keep-going'] = true }
local result = cli:parse({ "--no-keep-going", "--keep-going" })
assert.are.same(expected, result)
end)
end)
describe("multiple values for a single key", function()
it("should work for keys that explicitly permit it", function()
cli:add_option("-k, --key=VALUE", "key that can be specified multiple times", {})
local defaults = { key = {"value1", "value2", "value3"} }
defaults.k = defaults.key
local result = cli:parse({ "--key", "value1", "-k", "value2", "--key=value3" })
assert.are.same(result, defaults)
end)
it("should bail if the default value is not an empty table", function()
assert.is.error(function()
cli:add_option("-k", "a key that can be specified multiple times", { "foo" })
end, "Default argument: expected a")
end)
it("should print [] as the default value in the --help listing", function()
cli:add_option("-k, --key=VALUE", "key that can be specified multiple times", {})
local help_msg = cli:print_help(true)
assert.is_true(
nil ~= help_msg:match("key that can be specified multiple times %(default: %[%]%)")
)
end)
end)
describe("flag options", function()
it("should turn them on using the -short-key notation", function()
local defaults = populate_flags(cli)
defaults.v = true
defaults.version = true
local result = cli:parse({ "-v" })
assert.are.same(result, defaults)
end)
it("should turn them on using the --expanded-key notation", function()
local defaults = populate_flags(cli)
defaults.v = true
defaults.version = true
local result = cli:parse({ "--version" })
assert.are.same(result, defaults)
end)
describe("given a -short-key only flag option", function()
it("works", function()
cli:add_flag("-d", "script will run in DEBUG mode")
local result = cli:parse({ "-d" })
assert.are.same(result, { d = true })
end)
end)
describe("given an --expanded-key only flag option", function()
it("works", function()
local defaults = populate_flags(cli)
defaults.verbose = true
result = cli:parse({ "--verbose" })
assert.are.same(result, defaults)
end)
end)
describe("given a value for a flag", function()
it("bails", function()
local defaults = populate_flags(cli)
defaults.verbose = true
local result, err = cli:parse({ "--verbose=something" }, true --[[no print]])
assert(result == nil, "Adding a value to a flag must error out")
assert(type(err) == "string", "Expected an error string")
end)
end)
end)
it("tests optionals + required, no optionals and to little required provided, ", function()
populate_required(cli)
populate_optionals(cli)
local result = cli:parse({}, true --[[no print]])
assert.is.falsy(result)
end)
it("tests optionals + required, no optionals and too many required provided, ", function()
populate_required(cli)
populate_optionals(cli)
local result = cli:parse({ "some_file", "some_other_file" }, true --[[no print]])
assert.is.falsy(result)
end)
it("tests optionals + required + optarg, '--' as end of optionals", function()
populate_required(cli)
populate_optarg(1)
local expected = populate_flags(cli)
expected.INPUT = "--input"
expected.OUTPUT = "-d"
expected.verbose = true
local result = cli:parse({ "--verbose", "--", "--input", "-d" })
assert.is.same(expected, result)
end)
it("tests bad short-key notation, -x=VALUE", function()
populate_optionals(cli)
local result = cli:parse({ "-o=some_file" }, true --[[no print]])
assert.is.falsy(result)
end)
it("tests unknown option", function()
populate_optionals(cli)
local result = cli:parse({ "--foo=bar" }, true --[[no print]])
assert.is.falsy(result)
end)
it("tests unknown flag", function()
populate_optionals(cli)
local result = cli:parse({ "--foo" }, true --[[no print]])
assert.is.falsy(result)
end)
it("tests optarg only, defaults, multiple allowed", function()
defaults = populate_optarg(3)
local result,err = cli:parse(true --[[no print]])
assert.is.same(defaults, result)
end)
it("tests optarg only, defaults, 1 allowed", function()
defaults = populate_optarg(1)
local result = cli:parse(true --[[no print]])
assert.is.same(defaults, result)
end)
it("tests optarg only, values, multiple allowed", function()
defaults = populate_optarg(3)
local result = cli:parse({"/output1/", "/output2/"}, true --[[no print]])
assert.is.same(result, { OUTPUT = {"/output1/", "/output2/"}})
end)
it("tests optarg only, values, 1 allowed", function()
local defaults = populate_optarg(1)
local result = cli:parse({"/output/"}, true --[[no print]])
assert.is.same(result, { OUTPUT = "/output/" })
end)
it("tests optarg only, too many values", function()
local defaults = populate_optarg(1)
local result = cli:parse({"/output1/", "/output2/"}, true --[[no print]])
assert.is.same(result, nil)
end)
it("tests optarg only, too many values", function()
populate_required()
populate_optarg(1)
local result = cli:parse({"/input/", "/output/"}, true --[[no print]])
assert.is.same(result, { INPUT = "/input/", OUTPUT = "/output/" })
end)
it("tests clearing the default of an optional", function()
populate_optionals(cli)
local result, err = cli:parse({ "--compress=" }, true --[[no print]])
assert.are.equal(nil,err)
-- are_not.equal is not working when comparing against a nil as
-- of luassert-1.2-1, using is.truthy instead for now
-- assert.are_not.equal(nil,result)
assert.is.truthy(result)
assert.are.equal("", result.compress)
end)
describe("Tests options parsing with callback", function()
local cb = {}
local function callback(key, value, altkey, opt)
cb.key, cb.value, cb.altkey = key, value, altkey
return true
end
local function callback_fail(key, value, altkey, opt)
return nil, "bad argument to " .. opt
end
before_each(function()
cb = {}
end)
it("tests short-key option", function()
cli:add_option("-k, --long-key=VALUE", "key description", "", callback)
local expected = { k = "myvalue", ["long-key"] = "myvalue" }
local result = cli:parse({ "-k", "myvalue" })
assert.are.same(expected, result)
assert.are.equal("k", cb.key)
assert.are.equal("myvalue", cb.value)
assert.are.equal("long-key", cb.altkey)
end)
it("tests expanded-key option", function()
cli:add_option("-k, --long-key=VALUE", "key description", "", callback)
local expected = { k = "val", ["long-key"] = "val" }
local result = cli:parse({ "--long-key", "val" })
assert.are.same(expected, result)
assert.are.equal("long-key", cb.key)
assert.are.equal("val", cb.value)
assert.are.equal("k", cb.altkey)
end)
it("tests expanded-key flag with not short-key", function()
cli:add_flag("--version", "prints the version and exits", callback)
local expected = { version = true }
local result = cli:parse({ "--version" })
assert.are.same(expected, result)
assert.are.equal("version", cb.key)
assert.are.equal(true, cb.value)
assert.are.equal(nil, cb.altkey)
end)
it("tests callback for no-flags", function()
cli:add_flag("-k, --[no-]long-key", "key description", callback)
local expected = { k = false, ["long-key"] = false }
local result = cli:parse({ "--no-long-key" })
assert.are.same(expected, result)
assert.are.equal("long-key", cb.key)
assert.are.equal(false, cb.value)
assert.are.equal("k", cb.altkey)
end)
it("tests callback returning error", function()
cli:set_name('myapp')
cli:add_option("-k, --long-key=VALUE", "key description", "", callback_fail)
local result, err = cli:parse({ "--long-key", "val" }, true --[[no print]])
assert(result == nil, "Failure in callback returns nil")
assert(type(err) == "string", "Expected an error string")
assert.are.equal(err, "myapp: error: bad argument to --long-key; re-run with --help for usage.")
end)
end)
describe("Tests argument parsing with callback", function()
local cb = {}
local function callback(key, value)
cb.key, cb.value = key, value
return true
end
local function callback_arg(key, value)
table.insert(cb, { key = key, value = value })
return true
end
local function callback_fail(key, value)
return nil, "bad argument for " .. key
end
before_each(function()
cb = {}
end)
it("tests one required argument", function()
cli:add_arg("ARG", "arg description", callback)
local expected = { ARG = "arg_val" }
local result = cli:parse({ "arg_val" })
assert.are.same(expected, result)
assert.are.equal("ARG", cb.key)
assert.are.equal("arg_val", cb.value)
end)
it("tests required argument callback returning error", function()
cli:set_name('myapp')
cli:add_arg("ARG", "arg description", callback_fail)
local expected = { ARG = "arg_val" }
local result, err = cli:parse({ "arg_val" }, true --[[no print]])
assert(result == nil, "Failure in callback returns nil")
assert(type(err) == "string", "Expected an error string")
assert.are.equal(err, "myapp: error: bad argument for ARG; re-run with --help for usage.")
end)
it("tests many required arguments", function()
cli:add_arg("ARG1", "arg1 description", callback_arg)
cli:add_arg("ARG2", "arg2 description", callback_arg)
cli:add_arg("ARG3", "arg3 description", callback_arg)
local expected = { ARG1 = "arg1_val", ARG2 = "arg2_val", ARG3 = "arg3_val" }
local result = cli:parse({ "arg1_val", "arg2_val", "arg3_val" })
assert.are.same(expected, result)
assert.are.same({ key = "ARG1", value = "arg1_val"}, cb[1])
assert.are.same({ key = "ARG2", value = "arg2_val"}, cb[2])
assert.are.same({ key = "ARG3", value = "arg3_val"}, cb[3])
end)
it("tests one optional argument", function()
cli:optarg("OPTARG", "optional arg description", nil, 1, callback)
local expected = { OPTARG = "opt_arg" }
local result = cli:parse({ "opt_arg" })
assert.are.same(expected, result)
assert.are.equal("OPTARG", cb.key)
assert.are.equal("opt_arg", cb.value)
end)
it("tests optional argument callback returning error", function()
cli:set_name('myapp')
cli:optarg("OPTARG", "optinoal arg description", nil, 1, callback_fail)
local expected = { ARG = "arg_val" }
local result, err = cli:parse({ "opt_arg" }, true --[[no print]])
assert(result == nil, "Failure in callback returns nil")
assert(type(err) == "string", "Expected an error string")
assert.are.equal(err, "myapp: error: bad argument for OPTARG; re-run with --help for usage.")
end)
it("tests many optional arguments", function()
cli:optarg("OPTARG", "optional arg description", nil, 3, callback_arg)
local expected = { OPTARG = { "opt_arg1", "opt_arg2", "opt_arg3" } }
local result = cli:parse({ "opt_arg1", "opt_arg2", "opt_arg3" })
assert.are.same(expected, result)
assert.are.same({ key = "OPTARG", value = "opt_arg1"}, cb[1])
assert.are.same({ key = "OPTARG", value = "opt_arg2"}, cb[2])
assert.are.same({ key = "OPTARG", value = "opt_arg3"}, cb[3])
end)
end)
end)
lua_cliargs-2.5-4/src/ 0000775 0000000 0000000 00000000000 12606142114 0014572 5 ustar 00root root 0000000 0000000 lua_cliargs-2.5-4/src/cliargs.lua 0000664 0000000 0000000 00000054145 12606142114 0016732 0 ustar 00root root 0000000 0000000 local cli, _
-- ------- --
-- Helpers --
-- ------- --
local split = function(str, pat)
local t = {}
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = str:find(fpat, last_end)
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
end
local buildline = function(words, size, overflow)
-- if overflow is set, a word longer than size, will overflow the size
-- otherwise it will be chopped in line-length pieces
local line = ""
if string.len(words[1]) > size then
-- word longer than line
if overflow then
line = words[1]
table.remove(words, 1)
else
line = words[1]:sub(1, size)
words[1] = words[1]:sub(size + 1, -1)
end
else
while words[1] and (#line + string.len(words[1]) + 1 <= size) or (line == "" and #words[1] == size) do
if line == "" then
line = words[1]
else
line = line .. " " .. words[1]
end
table.remove(words, 1)
end
end
return line, words
end
local wordwrap = function(str, size, pad, overflow)
-- if overflow is set, then words longer than a line will overflow
-- otherwise, they'll be chopped in pieces
pad = pad or 0
local line = ""
local out = ""
local padstr = string.rep(" ", pad)
local words = split(str, ' ')
while words[1] do
line, words = buildline(words, size, overflow)
if out == "" then
out = padstr .. line
else
out = out .. "\n" .. padstr .. line
end
end
return out
end
local function disect(key)
-- characters allowed are a-z, A-Z, 0-9
-- extended + values also allow; # @ _ + -
local k, ek, v
local dummy
-- if there is no comma, between short and extended, add one
_, _, dummy = key:find("^%-([%a%d]+)[%s]%-%-")
if dummy then key = key:gsub("^%-[%a%d][%s]%-%-", "-"..dummy..", --", 1) end
-- for a short key + value, replace space by "="
_, _, dummy = key:find("^%-([%a%d]+)[%s]")
if dummy then key = key:gsub("^%-([%a%d]+)[ ]", "-"..dummy.."=", 1) end
-- if there is no "=", then append one
if not key:find("=") then key = key .. "=" end
-- get value
_, _, v = key:find(".-%=(.+)")
-- get key(s), remove spaces
key = split(key, "=")[1]:gsub(" ", "")
-- get short key & extended key
_, _, k = key:find("^%-([^-][^%s,]*)")
_, _, ek = key:find("%-%-(.+)$")
if v == "" then v = nil end
return k,ek,v
end
local function callable(fn)
return type(fn) == "function" or (getmetatable(fn) or {}).__call
end
function cli_error(msg, noprint)
local msg = cli.name .. ": error: " .. msg .. '; re-run with --help for usage.'
if not noprint then print(msg) end
return nil, msg
end
-- -------- --
-- CLI Main --
-- -------- --
cli = {
name = "",
required = {},
optional = {},
optargument = {maxcount = 0},
colsz = { 0, 0 }, -- column width, help text. Set to 0 for auto detect
maxlabel = 0,
}
--- Assigns the name of the program which will be used for logging.
function cli:set_name(name)
self.name = name
end
-- Used internally to lookup an entry using either its short or expanded keys
function cli:__lookup(k, ek, t)
t = t or self.optional
local _
for _,entry in ipairs(t) do
if k and entry.key == k then return entry end
if ek and entry.expanded_key == ek then return entry end
if entry.has_no_flag then
if ek and ("no-"..entry.expanded_key) == ek then return entry end
end
end
return nil
end
--- Defines a required argument.
--- Required arguments have no special notation and are order-sensitive.
--- *Note:* the value will be stored in `args[@key]`.
--- *Aliases: `add_argument`*
---
--- ### Parameters
--- 1. **key**: the argument's "name" that will be displayed to the user
--- 2. **desc**: a description of the argument
--- 3. **callback**: *optional*; specify a function to call when this argument is parsed (the default is nil)
---
--- ### Usage example
--- The following will parse the argument (if specified) and set its value in `args["root"]`:
--- `cli:add_arg("root", "path to where root scripts can be found")`
function cli:add_arg(key, desc, callback)
assert(type(key) == "string" and type(desc) == "string", "Key and description are mandatory arguments (Strings)")
assert(callable(callback) or callback == nil, "Callback argument: expected a function or nil")
if self:__lookup(key, nil, self.required) then
error("Duplicate argument: " .. key .. ", please rename one of them.")
end
table.insert(self.required, { key = key, desc = desc, value = nil, callback = callback })
if #key > self.maxlabel then self.maxlabel = #key end
end
--- Defines an optional argument (or more than one).
--- There can be only 1 optional argument, and it has to be the last one on the argumentlist.
--- *Note:* the value will be stored in `args[@key]`. The value will be a 'string' if 'maxcount == 1',
--- or a table if 'maxcount > 1'
---
--- ### Parameters
--- 1. **key**: the argument's "name" that will be displayed to the user
--- 2. **desc**: a description of the argument
--- 3. **default**: *optional*; specify a default value (the default is nil)
--- 4. **maxcount**: *optional*; specify the maximum number of occurences allowed (default is 1)
--- 5. **callback**: *optional*; specify a function to call when this argument is parsed (the default is nil)
---
--- ### Usage example
--- The following will parse the argument (if specified) and set its value in `args["root"]`:
--- `cli:add_arg("root", "path to where root scripts can be found", "", 2)`
--- The value returned will be a table with at least 1 entry and a maximum of 2 entries
function cli:optarg(key, desc, default, maxcount, callback)
assert(type(key) == "string" and type(desc) == "string", "Key and description are mandatory arguments (Strings)")
assert(type(default) == "string" or default == nil, "Default value must either be omitted or be a string")
maxcount = maxcount or 1
maxcount = tonumber(maxcount)
assert(maxcount and maxcount>0 and maxcount<1000,"Maxcount must be a number from 1 to 999")
assert(callable(callback) or callback == nil, "Callback argument: expected a function or nil")
self.optargument = { key = key, desc = desc, default = default, maxcount = maxcount, value = nil, callback = callback }
if #key > self.maxlabel then self.maxlabel = #key end
end
-- Used internally to add an option
function cli:__add_opt(k, ek, v, label, desc, default, callback)
local flag = (v == nil) -- no value, so it's a flag
local has_no_flag = flag and (ek and ek:find('^%[no%-]') ~= nil)
local ek = has_no_flag and ek:sub(6) or ek
-- guard against duplicates
if self:__lookup(k, ek) then
error("Duplicate option: " .. (k or ek) .. ", please rename one of them.")
end
if has_no_flag and self:__lookup(nil, "no-"..ek) then
error("Duplicate option: " .. ("no-"..ek) .. ", please rename one of them.")
end
-- below description of full entry record, nils included for reference
local entry = {
key = k,
expanded_key = ek,
desc = desc,
default = default,
label = label,
flag = flag,
has_no_flag = has_no_flag,
value = default,
callback = callback,
}
table.insert(self.optional, entry)
if #label > self.maxlabel then self.maxlabel = #label end
end
--- Defines an option.
--- Optional arguments can use 3 different notations, and can accept a value.
--- *Aliases: `add_option`*
---
--- ### Parameters
--- 1. **key**: the argument identifier, can be either `-key`, or `-key, --expanded-key`:
--- if the first notation is used then a value can be defined after a space (`'-key VALUE'`),
--- if the 2nd notation is used then a value can be defined after an `=` (`'-key, --expanded-key=VALUE'`).
--- As a final option it is possible to only use the expanded key (eg. `'--expanded-key'`) both with and
--- without a value specified.
--- 2. **desc**: a description for the argument to be shown in --help
--- 3. **default**: *optional*; specify a default value (the default is nil)
--- 4. **callback**: *optional*; specify a function to call when this option is parsed (the default is nil)
---
--- ### Usage example
--- The following option will be stored in `args["i"]` and `args["input"]` with a default value of `my_file.txt`:
--- `cli:add_option("-i, --input=FILE", "path to the input file", "my_file.txt")`
function cli:add_opt(key, desc, default, callback)
-- parameterize the key if needed, possible variations:
-- 1. -key
-- 2. -key VALUE
-- 3. -key, --expanded
-- 4. -key, --expanded=VALUE
-- 5. -key --expanded
-- 6. -key --expanded=VALUE
-- 7. --expanded
-- 8. --expanded=VALUE
assert(type(key) == "string" and type(desc) == "string", "Key and description are mandatory arguments (Strings)")
assert(callable(callback) or callback == nil, "Callback argument: expected a function or nil")
assert(
(
type(default) == "string"
or default == nil
or type(default) == "boolean"
or (type(default) == "table" and next(default) == nil)
),
"Default argument: expected a string, nil, or {}"
)
local k, ek, v = disect(key)
-- set defaults
if v == nil and type(default) ~= "boolean" then default = nil end
self:__add_opt(k, ek, v, key, desc, default, callback)
end
--- Define a flag argument (on/off). This is a convenience helper for cli.add_opt().
--- See cli.add_opt() for more information.
---
--- ### Parameters
-- 1. **key**: the argument's key
-- 2. **desc**: a description of the argument to be displayed in the help listing
-- 3. **default**: *optional*; specify a default value (the default is nil)
-- 4. **callback**: *optional*; specify a function to call when this flag is parsed (the default is nil)
function cli:add_flag(key, desc, default, callback)
if type(default) == "function" then
callback = default
default = nil
end
assert(default == nil or type(default) == "boolean", "Default argument: expected a boolean, nil")
local k, ek, v = disect(key)
if v ~= nil then
error("A flag type option cannot have a value set: " .. key)
end
self:__add_opt(k, ek, nil, key, desc, default, callback)
end
--- Parses the arguments found in #arg and returns a table with the populated values.
--- (NOTE: after succesful parsing, the module will delete itself to free resources)
--- *Aliases: `parse_args`*
---
--- ### Parameters
--- 1. **arguments**: set this to arg
--- 2. **noprint**: set this flag to prevent any information (error or help info) from being printed
--- 3. **dump**: set this flag to dump the parsed variables for debugging purposes, alternatively
--- set the first option to --__DUMP__ (option with 2 trailing and leading underscores) to dump at runtime.
---
--- ### Returns
--- 1. a table containing the keys specified when the arguments were defined along with the parsed values,
--- or nil + error message (--help option is considered an error and returns nil + help message)
function cli:parse(arguments, noprint, dump)
if type(arguments) ~= "table" then
-- optional 'arguments' was not provided, so shift remaining arguments
noprint, dump, arguments = arguments, noprint, nil
end
local arguments = arguments or arg or {}
local args = {}
for k,v in pairs(arguments) do args[k] = v end -- copy args local
-- starts with --help? display the help listing and abort!
if args[1] and (args[1] == "--help" or args[1] == "-h") then
return nil, self:print_help(noprint)
end
-- starts with --__DUMP__; set dump to true to dump the parsed arguments
if dump == nil then
if args[1] and args[1] == "--__DUMP__" then
dump = true
table.remove(args, 1) -- delete it to prevent further parsing
end
end
while args[1] do
local entry = nil
local opt = args[1]
local _, optpref, optkey, optkey2, optval
_, _, optpref, optkey = opt:find("^(%-[%-]?)(.+)") -- split PREFIX & NAME+VALUE
if optkey then
_, _, optkey2, optval = optkey:find("(.-)[=](.+)") -- split value and key
if optval then
optkey = optkey2
end
end
if not optpref then
break -- no optional prefix, so options are done
end
if opt == "--" then
table.remove(args, 1)
break -- end of options
end
if optkey:sub(-1,-1) == "=" then -- check on a blank value eg. --insert=
optval = ""
optkey = optkey:sub(1,-2)
end
if optkey then
entry =
self:__lookup(optpref == '-' and optkey or nil,
optpref == '--' and optkey or nil)
end
if not optkey or not entry then
local option_type = optval and "option" or "flag"
return cli_error("unknown/bad " .. option_type .. ": " .. opt, noprint)
end
table.remove(args,1)
if optpref == "-" then
if optval then
return cli_error("short option does not allow value through '=': "..opt, noprint)
end
if entry.flag then
optval = true
else
-- not a flag, value is in the next argument
optval = args[1]
table.remove(args, 1)
end
elseif optpref == "--" then
-- using the expanded-key notation
entry = self:__lookup(nil, optkey)
if entry then
if entry.flag then
if optval then
return cli_error("flag --" .. optkey .. " does not take a value", noprint)
else
optval = not entry.has_no_flag or (optkey:sub(1,3) ~= "no-")
end
else
if not optval then
-- value is in the next argument
optval = args[1]
table.remove(args, 1)
end
end
else
return cli_error("unknown/bad flag: " .. opt, noprint)
end
end
if type(entry.value) == 'table' then
table.insert(entry.value, optval)
else
entry.value = optval
end
-- invoke the option's parse-callback, if any
if entry.callback then
local altkey = entry.key
if optkey == entry.key then
altkey = entry.expanded_key
else
optkey = entry.expanded_key
end
local status, err = entry.callback(optkey, optval, altkey, opt)
if status == nil and err then
return cli_error(err, noprint)
end
end
end
-- missing any required arguments, or too many?
if #args < #self.required or #args > #self.required + self.optargument.maxcount then
if self.optargument.maxcount > 0 then
return cli_error("bad number of arguments: " .. #self.required .."-" .. #self.required + self.optargument.maxcount .. " argument(s) must be specified, not " .. #args, noprint)
else
return cli_error("bad number of arguments: " .. #self.required .. " argument(s) must be specified, not " .. #args, noprint)
end
end
-- deal with required args here
for i, entry in ipairs(self.required) do
entry.value = args[1]
if entry.callback then
local status, err = entry.callback(entry.key, entry.value)
if status == nil and err then
return cli_error(err, noprint)
end
end
table.remove(args, 1)
end
-- deal with the last optional argument
while args[1] do
if self.optargument.maxcount > 1 then
self.optargument.value = self.optargument.value or {}
table.insert(self.optargument.value, args[1])
else
self.optargument.value = args[1]
end
if self.optargument.callback then
local status, err = self.optargument.callback(self.optargument.key, args[1])
if status == nil and err then
return cli_error(err, noprint)
end
end
table.remove(args,1)
end
-- if necessary set the defaults for the last optional argument here
if self.optargument.maxcount > 0 and not self.optargument.value then
if self.optargument.maxcount == 1 then
self.optargument.value = self.optargument.default
else
self.optargument.value = { self.optargument.default }
end
end
-- populate the results table
local results = {}
if self.optargument.maxcount > 0 then
results[self.optargument.key] = self.optargument.value
end
for _, entry in pairs(self.required) do
results[entry.key] = entry.value
end
for _, entry in pairs(self.optional) do
if entry.key then results[entry.key] = entry.value end
if entry.expanded_key then results[entry.expanded_key] = entry.value end
end
if dump then
print("\n======= Provided command line =============")
print("\nNumber of arguments: ", #arg)
for i,v in ipairs(arg) do -- use gloabl 'arg' not the modified local 'args'
print(string.format("%3i = '%s'", i, v))
end
print("\n======= Parsed command line ===============")
if #self.required > 0 then print("\nArguments:") end
for i,v in ipairs(self.required) do
print(" " .. v.key .. string.rep(" ", self.maxlabel + 2 - #v.key) .. " => '" .. v.value .. "'")
end
if self.optargument.maxcount > 0 then
print("\nOptional arguments:")
print(" " .. self.optargument.key .. "; allowed are " .. tostring(self.optargument.maxcount) .. " arguments")
if self.optargument.maxcount == 1 then
print(" " .. self.optargument.key .. string.rep(" ", self.maxlabel + 2 - #self.optargument.key) .. " => '" .. self.optargument.key .. "'")
else
for i = 1, self.optargument.maxcount do
if self.optargument.value[i] then
print(" " .. tostring(i) .. string.rep(" ", self.maxlabel + 2 - #tostring(i)) .. " => '" .. tostring(self.optargument.value[i]) .. "'")
end
end
end
end
if #self.optional > 0 then print("\nOptional parameters:") end
local doubles = {}
for _, v in pairs(self.optional) do
if not doubles[v] then
local m = v.value
if type(m) == "string" then
m = "'"..m.."'"
else
m = tostring(m) .." (" .. type(m) .. ")"
end
print(" " .. v.label .. string.rep(" ", self.maxlabel + 2 - #v.label) .. " => " .. m)
doubles[v] = v
end
end
print("\n===========================================\n\n")
return cli_error("commandline dump created as requested per '--__DUMP__' option", noprint)
end
if not _TEST then
-- cleanup entire module, as it's single use
-- remove from package.loaded table to enable the module to
-- garbage collected.
for k, v in pairs(package.loaded) do
if v == cli then
package.loaded[k] = nil
break
end
end
-- clear table in case user holds on to module table
for k, _ in pairs(cli) do
cli[k] = nil
end
end
return results
end
--- Prints the USAGE heading.
---
--- ### Parameters
---1. **noprint**: set this flag to prevent the line from being printed
---
--- ### Returns
--- 1. a string with the USAGE message.
function cli:print_usage(noprint)
-- print the USAGE heading
local msg = "Usage: " .. tostring(self.name)
if #self.optional > 0 then
msg = msg .. " [OPTIONS]"
end
if #self.required > 0 or self.optargument.maxcount > 0 then
msg = msg .. " [--]"
end
if #self.required > 0 then
for _,entry in ipairs(self.required) do
msg = msg .. " " .. entry.key
end
end
if self.optargument.maxcount == 1 then
msg = msg .. " [" .. self.optargument.key .. "]"
elseif self.optargument.maxcount == 2 then
msg = msg .. " [" .. self.optargument.key .. "-1 [" .. self.optargument.key .. "-2]]"
elseif self.optargument.maxcount > 2 then
msg = msg .. " [" .. self.optargument.key .. "-1 [" .. self.optargument.key .. "-2 [...]]]"
end
if not noprint then print(msg) end
return msg
end
--- Prints the HELP information.
---
--- ### Parameters
--- 1. **noprint**: set this flag to prevent the information from being printed
---
--- ### Returns
--- 1. a string with the HELP message.
function cli:print_help(noprint)
local msg = self:print_usage(true) .. "\n"
local col1 = self.colsz[1]
local col2 = self.colsz[2]
if col1 == 0 then col1 = cli.maxlabel end
col1 = col1 + 3 --add margins
if col2 == 0 then col2 = 72 - col1 end
if col2 <10 then col2 = 10 end
local append = function(label, desc)
label = " " .. label .. string.rep(" ", col1 - (#label + 2))
desc = wordwrap(desc, col2) -- word-wrap
desc = desc:gsub("\n", "\n" .. string.rep(" ", col1)) -- add padding
msg = msg .. label .. desc .. "\n"
end
if self.required[1] then
msg = msg .. "\nARGUMENTS: \n"
for _,entry in ipairs(self.required) do
append(entry.key, entry.desc .. " (required)")
end
end
if self.optargument.maxcount > 0 then
append(self.optargument.key, self.optargument.desc .. " (optional, default: " .. self.optargument.default .. ")")
end
if #self.optional > 0 then
msg = msg .. "\nOPTIONS: \n"
for _,entry in ipairs(self.optional) do
local desc = entry.desc
if not entry.flag and entry.default and #tostring(entry.default) > 0 then
local readable_default = type(entry.default) == "table" and "[]" or tostring(entry.default)
desc = desc .. " (default: " .. readable_default .. ")"
elseif entry.flag and entry.has_no_flag then
local readable_default = entry.default and 'on' or 'off'
desc = desc .. " (default: " .. readable_default .. ")"
end
append(entry.label, desc)
end
end
if not noprint then print(msg) end
return msg
end
--- Sets the amount of space allocated to the argument keys and descriptions in the help listing.
--- The sizes are used for wrapping long argument keys and descriptions.
--- ### Parameters
--- 1. **key_cols**: the number of columns assigned to the argument keys, set to 0 to auto detect (default: 0)
--- 1. **desc_cols**: the number of columns assigned to the argument descriptions, set to 0 to auto set the total width to 72 (default: 0)
function cli:set_colsz(key_cols, desc_cols)
self.colsz = { key_cols or self.colsz[1], desc_cols or self.colsz[2] }
end
-- finalize setup
cli._COPYRIGHT = "Copyright (C) 2011-2014 Ahmad Amireh"
cli._LICENSE = "The code is released under the MIT terms. Feel free to use it in both open and closed software as you please."
cli._DESCRIPTION = "Commandline argument parser for Lua"
cli._VERSION = "cliargs 2.5-4"
-- aliases
cli.add_argument = cli.add_arg
cli.add_option = cli.add_opt
cli.parse_args = cli.parse -- backward compatibility
-- test aliases for local functions
if _TEST then
cli.split = split
cli.wordwrap = wordwrap
end
return cli