elua: document getopt.lua

This commit is contained in:
Daniel Kolesa 2014-12-17 17:09:47 +00:00
parent 208ad62d3c
commit 110e6c5abb
1 changed files with 204 additions and 1 deletions

View File

@ -1,4 +1,34 @@
-- Elua getopt module
--[[ getopt.lua: An argument parsing library for Lua 5.1 and later.
This module is provided as a self-contained implementation with builtin
documentation.
TODO:
- arguments that can only be specified once (for now you can check
that manually by going over array values of opts)
- i18n support
- support for desc callback failures
Copyright (c) 2014 Daniel "q66" Kolesa <quaker66@gmail.com>
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.
]]
local M = {}
@ -125,6 +155,118 @@ local getopt_u = function(parser)
return opts, args
end
--[[
Given a parser definition, parse the arguments and return all optional
arguments, all positional arguments and the parser itself.
It takes exactly one argument, a parser.
The parser is a dictionary. It can contain these fields:
- usage - a usage string.
- prog - a program name.
- error_cb - a callback that is called when parsing fails.
- done_cb - a callback that is called when it's done parsing.
- args - the arguments.
- descs - argument descriptions.
In case of errors, this function returns nil and an error message.
You can also handle any error from the error callback of course.
Usage string is an arbitrary string that can contain a sequence "%prog".
This sequence is replaced with program name.
Program name can be explicitly specified here. If it's not, it's retrieved
from "args" as zeroth index. If that is nil, "program" is used.
Error callback is called on errors right before this function returns. It
returns no values. It takes the parser and an error message as arguments.
Done callack is called on success right before this function returns. It
takes the parser, optionala rguments and positional arguments.
Arguments ("args") is an array with zeroth index optionally specifying
program name. It contains strings, similarly to "argv" in other languages.
Descriptions (descs) is an array of tables, each table being an argument
description.
-- RETURN VALUES --
--- OPTIONAL ARGS ---
The returned optional arguments is a mixed table. It contains mappings
from argument names (without prefix) to values. The argument name here
is in this order: alias, short name, long name. The meaning of aliases
is described below. This also means that any given argument has one key
only. If a value is not given (optional or doesn't take it) it's the
boolean value "true" instead. If it is given, it's either the string
value or whatever a callback returns (see below).
It also contains array elements as the order of given arguments goes.
Those array elements have this layout:
{ optn, short = shortn, long = longn, alias = aliasn, val = stringval, ... }
"optn" refers to the same name as above (in order alias, short, long).
"shortn" refers to the short name given in the description. "longn"
refers to the long name given in the description. "alias" refers to
the optional alias. "val" is the string value that was given, if given.
This is then followed by zero or more values which are return values
of either option callback (see below) or the string value or nothing.
--- POSITIONAL ARGS ---
The returned positional arguments is a simple array of strings.
-- DESCRIPTIONS --
The most important part of the parser is descriptions. It describes
what kind of arguments can be given and also describes categories
for the help listing.
A description is represented by a table. The table has this layout:
{ shortn, longn, optional, help = helpmsg, metavar = metavar,
alias = alias, callback = retcb, list = list
}
"shortn" refers to the short name. For example if you want your argument
to be specifeable as "-x", you use "x". "longn" here refers to the long
name. For "--help", it's "help".
"optional" refers to whether it is required to specify value of the
argument. The boolean value "true" means that a value is always needed.
The value "false" means that the value can never be given.
The value "nil" means that the value is optional.
"help" refers to the description of the parameter in help listing.
The field "metavar" specifies the string under which the value field
will be displayed in help listing (see the documentation for "help").
The field "alias" can be used to specify an alias under which the
value/argument will be known in the returned optional arguments (i.e.
opts[alias]). It's fully optional, see above in "optional args".
The field "callback" can be used to specify a function that takes the
description, the parser and the string value and returns one or more
values. Those values will then be present in optional args. When multiple
values are returned from such callback, the mapping opts[n] will get you
an array of these values.
The field "list" can be used to specify a value into which values will
be appended. When you pass such parameter to your application multiple
times, the list will contain all the values provided. The mapping opts[n]
will refer to the list rather than the last value given like without list.
A description can also be used to specify a category, purely for help
listing purposes:
{ category = "catname", alias = alias }
The alias here refers to a name by which the category can be referred
to when printing help. Useful when your category name is long and contains
spaces and you want a simple "--help=mycat".
]]
M.parse = function(parser)
local ret, opts, args = pcall(getopt_u, parser)
if not ret then
@ -263,6 +405,62 @@ local help = function(parser, f, category)
f:write(table.concat(buf))
end
--[[
Given a parser, print help. The parser is the very same parser as given
to a normal parsing function.
Arguments:
- parser - the parser.
- category - optional, allows you to specify a category to print,
in which case only the given category will print (normally all
categories will print).
- f - optional file stream, defaults to io.stderr.
Keep in mind that if the second argument is given and it's not a string,
it's considered to be the file stream (without category being specified).
The help uses this format:
--------------
<USAGE STRING>
<HEADER>
The following options are supported:
<CATEGORYNAME>:
-x, --long Description for no argument.
-h[?<METAVAR>], --help=[?<METAVAR>] Description for optional argument.
-f<METAVAR>, --foo=<METAVAR> Description for mandatory argument.
<ANOTHERCATEGORYNAME>:
<MOREARGS>
<FOOTER>
--------------
The usage string can be either custom (specified within the parser) or
default, which is "Usage: <progname> [OPTIONS]" where "<progname>" is
replaced by the program name (either specified in the parser explicitly
or zeroth argument in the given args or "program" as a fallback).
The header is printed only when given as part of the parser.
The "The following optins are supported:" line is only printed when there
are options to print.
Same goes for the footer as for the header.
A metavar can be specified explicitly as part of the parameter description
in the parser. If not specified, it will check whether a "long" option is
given; if it is, it will use an uppercase version of it (for example a
default metavar for "--help" would be "HELP"). If it's not, it will
fallback to simply "VAL".
Please refer to parser documentation for more information.
]]
M.help = function(parser, category, f)
if category and type(category) ~= "string" then
f, category = category, f
@ -277,14 +475,19 @@ M.help = function(parser, category, f)
return true
end
-- A utility callback for geometry parsing (--foo=x:y:w:h).
M.geometry_parse_cb = function(desc, parser, v)
return v:match("^(%d+):(%d+):(%d+):(%d+)$")
end
-- A utility callback for size parsing (--foo=WxH).
M.size_parse_cb = function(desc, parser, v)
return v:match("^(%d+)x(%d+)$")
end
-- A utility callback generator for help. Returns a utility callback when
-- called with file stream as an argument (optional, defaults to stderr).
-- For help args that take a value, the value will be used as a category name.
M.help_cb = function(fstream)
return function(desc, parser, v)
M.help(parser, v, fstream)