Merge remote-tracking branch 'luarocks/refs/pull/1/head'

This commit is contained in:
daurnimator
2019-05-29 00:04:42 +10:00
6 changed files with 210 additions and 92 deletions

View File

@@ -28,6 +28,47 @@ If the property ``add_help`` of a parser is set to ``false``, no help option wil
Options:
/? Show this help message and exit.
Help command
------------
If the property ``add_help_command`` of a parser is set to ``true``, a help command will be added to it. A string or table value can be used to configure the command.
.. code-block:: lua
:linenos:
local parser = argparse()
:add_help_command(true)
parser:command "install"
:description "Install a rock."
.. code-block:: none
$ lua script.lua help
.. code-block:: none
Usage: script.lua [-h] <command> ...
Options:
-h, --help Show this help message and exit.
Commands:
help Show help for commands.
install Install a rock.
.. code-block:: none
$ lua script.lua help install
.. code-block:: none
Usage: script.lua install [-h]
Install a rock.
Options:
-h, --help Show this help message and exit.
Disabling option handling
-------------------------
@@ -132,6 +173,7 @@ Property Type
``require_command`` Boolean
``handle_options`` Boolean
``add_help`` Boolean or string or table
``add_help_command`` Boolean or string or table
``command_target`` String
``usage_max_width`` Number
``usage_margin`` Number

View File

@@ -77,13 +77,13 @@ Options:
parser:option "--config"
assert.equal([[
Usage: foo [-q] --from <from> [--config <config>] [-h]
Usage: foo [-h] [-q] --from <from> [--config <config>]
Options:
-h, --help Show this help message and exit.
-q, --quiet
--from <from>
--config <config>
-h, --help Show this help message and exit.]], parser:get_help())
--config <config>]], parser:get_help())
end)
it("adds margin for multiline descriptions", function()
@@ -97,13 +97,13 @@ Sets verbosity level.
-vv: Report all debugging information.]]
assert.equal([[
Usage: foo [-v] [-h]
Usage: foo [-h] [-v]
Options:
-h, --help Show this help message and exit.
-v Sets verbosity level.
-v: Report all warnings.
-vv: Report all debugging information.
-h, --help Show this help message and exit.]], parser:get_help())
-vv: Report all debugging information.]], parser:get_help())
end)
it("puts different aliases on different lines if there are arguments", function()
@@ -112,12 +112,12 @@ Options:
parser:option "-o --output"
assert.equal([[
Usage: foo [-o <output>] [-h]
Usage: foo [-h] [-o <output>]
Options:
-h, --help Show this help message and exit.
-o <output>,
--output <output>
-h, --help Show this help message and exit.]], parser:get_help())
--output <output>]], parser:get_help())
end)
it("handles description with more lines than usage", function()
@@ -131,13 +131,13 @@ If '-' is passed, output to stdount.
]]
assert.equal([[
Usage: foo [-o <output>] [-h]
Usage: foo [-h] [-o <output>]
Options:
-h, --help Show this help message and exit.
-o <output>, Sets output file.
--output <output> If missing, 'a.out' is used by default.
If '-' is passed, output to stdount.
-h, --help Show this help message and exit.]], parser:get_help())
If '-' is passed, output to stdount.]], parser:get_help())
end)
it("handles description with less lines than usage", function()
@@ -147,12 +147,12 @@ Options:
:description "Sets output file."
assert.equal([[
Usage: foo [-o <output>] [-h]
Usage: foo [-h] [-o <output>]
Options:
-h, --help Show this help message and exit.
-o <output>, Sets output file.
--output <output>
-h, --help Show this help message and exit.]], parser:get_help())
--output <output>]], parser:get_help())
end)
it("handles very long argument lists", function()
@@ -167,10 +167,10 @@ Options:
Usage: foo [-h] [-t <foo> <bar> <baz> ...]
Options:
-h, --help Show this help message and exit.
-t <foo> <bar> <baz> ...,
--at-least-three <foo> <bar> <baz> ...
Sometimes argument lists are really long.
-h, --help Show this help message and exit.]], parser:get_help())
Sometimes argument lists are really long.]], parser:get_help())
end)
it("shows default values", function()
@@ -182,12 +182,12 @@ Options:
:description "Port."
assert.equal([[
Usage: foo [-o <o>] [-p <p>] [-h]
Usage: foo [-h] [-o <o>] [-p <p>]
Options:
-h, --help Show this help message and exit.
-o <o> default: a.out
-p <p> Port. (default: 8080)
-h, --help Show this help message and exit.]], parser:get_help())
-p <p> Port. (default: 8080)]], parser:get_help())
end)
it("does not show default value when show_default == false", function()
@@ -201,12 +201,12 @@ Options:
:description "Port."
assert.equal([[
Usage: foo [-o <o>] [-p <p>] [-h]
Usage: foo [-h] [-o <o>] [-p <p>]
Options:
-h, --help Show this help message and exit.
-o <o>
-p <p> Port.
-h, --help Show this help message and exit.]], parser:get_help())
-p <p> Port.]], parser:get_help())
end)
it("creates correct help message for commands", function()
@@ -217,11 +217,11 @@ Options:
run:option "--where"
assert.equal([[
Usage: foo [-q] [-h] <command> ...
Usage: foo [-h] [-q] <command> ...
Options:
-q, --quiet
-h, --help Show this help message and exit.
-q, --quiet
Commands:
run Run! ]], parser:get_help())
@@ -234,11 +234,11 @@ Commands:
run:option "--where"
assert.equal([[
Usage: foo run [--where <where>] [-h]
Usage: foo run [-h] [--where <where>]
Options:
--where <where>
-h, --help Show this help message and exit.]], run:get_help())
-h, --help Show this help message and exit.
--where <where>]], run:get_help())
end)
it("uses message provided by user", function()
@@ -265,14 +265,14 @@ I don't like your format of help messages]], parser:get_help())
:hidden(true)
assert.equal([[
Usage: foo [--feature] [-h] <normal> <command> ...
Usage: foo [-h] [--feature] <normal> <command> ...
Arguments:
normal
Options:
--feature
-h, --help Show this help message and exit.
--feature
Commands:
good
@@ -359,8 +359,8 @@ Options for setting style:
parser:command "another-command"
assert.equal([[
Usage: foo [--use-default-args] [--something] [--test <test>]
[--version] [-h] <foo> <bar> [<optional>] <command> ...
Usage: foo [-h] [--use-default-args] [--something] [--test <test>]
[--version] <foo> <bar> [<optional>] <command> ...
Main arguments:
foo
@@ -375,8 +375,8 @@ Main options:
--test <test>
Other options:
--version
-h, --help Show this help message and exit.
--version
Some commands:
foo
@@ -404,7 +404,7 @@ Because it has lots of complex behaviour.
That needs documenting.]]
assert.equal([[
Usage: foo [-p] [-f <foo>] [-h] <arg1> <arg2>
Usage: foo [-h] [-p] [-f <foo>] <arg1> <arg2>
Arguments:
@@ -414,13 +414,13 @@ Arguments:
Options:
-h, --help Show this help message and exit.
-p This is a thing.
-f <foo>, And this things uses many lines.
--foo <foo> Because it has lots of complex behaviour.
That needs documenting.
-h, --help Show this help message and exit.]], parser:get_help())
That needs documenting.]], parser:get_help())
end)
it("inherits help_vertical_space in commands", function()
@@ -439,29 +439,29 @@ Options:
cmd2:flag("-d", "Do d thing.")
assert.equal([[
Usage: foo cmd1 [-a] [-b] [-h]
Usage: foo cmd1 [-h] [-a] [-b]
Options:
-h, --help Show this help message and exit.
-a Do a thing.
-b Do b thing.
-h, --help Show this help message and exit.]], cmd1:get_help())
-b Do b thing.]], cmd1:get_help())
assert.equal([[
Usage: foo cmd2 [-c] [-d] [-h]
Usage: foo cmd2 [-h] [-c] [-d]
Options:
-h, --help Show this help message and exit.
-c Do c thing.
-d Do d thing.
-h, --help Show this help message and exit.]], cmd2:get_help())
-d Do d thing.]], cmd2:get_help())
end)
it("allows configuring margins using help_usage_margin and help_description_margin", function()
@@ -483,18 +483,18 @@ Because it has lots of complex behaviour.
That needs documenting.]]
assert.equal([[
Usage: foo [-p] [-f <foo>] [-h] <arg1> <arg2>
Usage: foo [-h] [-p] [-f <foo>] <arg1> <arg2>
Arguments:
arg1 Argument number one.
arg2 Argument number two.
Options:
-h, --help Show this help message and exit.
-p This is a thing.
-f <foo>, And this things uses many lines.
--foo <foo> Because it has lots of complex behaviour.
That needs documenting.
-h, --help Show this help message and exit.]], parser:get_help())
That needs documenting.]], parser:get_help())
end)
describe("autowrap", function()
@@ -512,9 +512,10 @@ Options:
:description "See above."
assert.equal([[
Usage: foo [-f <foo>] [-b <bar>] [-h]
Usage: foo [-h] [-f <foo>] [-b <bar>]
Options:
-h, --help Show this help message and exit.
-f <foo>, Lorem ipsum dolor sit amet, consectetur adipiscing
--foo <foo> elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis
@@ -525,8 +526,7 @@ Options:
cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
-b <bar>, See above.
--bar <bar>
-h, --help Show this help message and exit.]], parser:get_help())
--bar <bar>]], parser:get_help())
end)
it("preserves existing line breaks", function()
@@ -542,16 +542,16 @@ Another one.
parser:option "-b --bar"
assert.equal([[
Usage: foo [-f <foo>] [-b <bar>] [-h]
Usage: foo [-h] [-f <foo>] [-b <bar>]
Options:
-h, --help Show this help message and exit.
-f <foo>, This is a long line, it should be broken down into
--foo <foo> several lines. It just keeps going and going.
This should always be a new line.
Another one.
-b <bar>,
--bar <bar>
-h, --help Show this help message and exit.]], parser:get_help())
--bar <bar>]], parser:get_help())
end)
it("preserves indentation", function()
@@ -565,17 +565,17 @@ Options:
" That was an empty line there, preserve it.")
assert.equal([[
Usage: foo [-f <foo>] [-h]
Usage: foo [-h] [-f <foo>]
Options:
-h, --help Show this help message and exit.
-f <foo>, This is a long line, it should be broken down into
--foo <foo> several lines.
This paragraph is indented with three spaces, so
when it gets broken down into several lines, they
will be, too.
That was an empty line there, preserve it.
-h, --help Show this help message and exit.]], parser:get_help())
That was an empty line there, preserve it.]], parser:get_help())
end)
it("preserves indentation of list items", function()
@@ -591,9 +591,10 @@ Options:
assert.equal([[
Usage: foo [-f <foo>] [-h]
Usage: foo [-h] [-f <foo>]
Options:
-h, --help Show this help message and exit.
-f <foo>, Let's start a list:
--foo <foo>
* Here is a list item.
@@ -602,8 +603,7 @@ Options:
+ Here is a nested list item. Word. Word. Word. Word.
Word. Bird. Word. Bird. Bird. Bird.
* Back to normal list, this one uses several spaces
after the list item mark. Bird. Bird. Bird.
-h, --help Show this help message and exit.]], parser:get_help())
after the list item mark. Bird. Bird. Bird.]], parser:get_help())
end)
it("preserves multiple spaces between words", function()
@@ -614,12 +614,12 @@ Options:
:description("This is a long line with two spaces between words, it should be broken down.")
assert.equal([[
Usage: foo [-f <foo>] [-h]
Usage: foo [-h] [-f <foo>]
Options:
-h, --help Show this help message and exit.
-f <foo>, This is a long line with two spaces between
--foo <foo> words, it should be broken down.
-h, --help Show this help message and exit.]], parser:get_help())
--foo <foo> words, it should be broken down.]], parser:get_help())
end)
it("autowraps description and epilog", function()

View File

@@ -18,7 +18,7 @@ describe("tests related to CLI behaviour #unsafe", function()
describe("error messages", function()
it("generates correct error message without arguments", function()
assert.equal([[
Usage: ]]..script..[[ [-v] [-h] <input> [<command>] ...
Usage: ]]..script..[[ [-h] [-v] <input> [<command>] ...
Error: missing argument 'input'
]], get_output(""))
@@ -26,7 +26,7 @@ Error: missing argument 'input'
it("generates correct error message with too many arguments", function()
assert.equal([[
Usage: ]]..script..[[ [-v] [-h] <input> [<command>] ...
Usage: ]]..script..[[ [-h] [-v] <input> [<command>] ...
Error: unknown command 'bar'
]], get_output("foo bar"))
@@ -34,7 +34,7 @@ Error: unknown command 'bar'
it("generates correct error message with unexpected argument", function()
assert.equal([[
Usage: ]]..script..[[ [-v] [-h] <input> [<command>] ...
Usage: ]]..script..[[ [-h] [-v] <input> [<command>] ...
Error: option '--verbose' does not take arguments
]], get_output("--verbose=true"))
@@ -42,7 +42,7 @@ Error: option '--verbose' does not take arguments
it("generates correct error message with unexpected option", function()
assert.equal([[
Usage: ]]..script..[[ [-v] [-h] <input> [<command>] ...
Usage: ]]..script..[[ [-h] [-v] <input> [<command>] ...
Error: unknown option '-q'
Did you mean one of these: '-h' '-v'?
@@ -51,7 +51,7 @@ Did you mean one of these: '-h' '-v'?
it("generates correct error message and tip with unexpected command", function()
assert.equal([[
Usage: ]]..script..[[ [-v] [-h] <input> [<command>] ...
Usage: ]]..script..[[ [-h] [-v] <input> [<command>] ...
Error: unknown command 'nstall'
Did you mean 'install'?
@@ -60,7 +60,7 @@ Did you mean 'install'?
it("generates correct error message without arguments in command", function()
assert.equal([[
Usage: ]]..script..[[ install [-f <from>] [-h] <rock> [<version>]
Usage: ]]..script..[[ install [-h] [-f <from>] <rock> [<version>]
Error: missing argument 'rock'
]], get_output("foo install"))
@@ -68,7 +68,7 @@ Error: missing argument 'rock'
it("generates correct error message and tip in command", function()
assert.equal([[
Usage: ]]..script..[[ install [-f <from>] [-h] <rock> [<version>]
Usage: ]]..script..[[ install [-h] [-f <from>] <rock> [<version>]
Error: unknown option '--form'
Did you mean '--from'?
@@ -77,9 +77,9 @@ Did you mean '--from'?
end)
describe("help messages", function()
it("generates correct help message", function()
it("generates correct help message using help flag", function()
assert.equal([[
Usage: ]]..script..[[ [-v] [-h] <input> [<command>] ...
Usage: ]]..script..[[ [-h] [-v] <input> [<command>] ...
A testing program.
@@ -87,17 +87,37 @@ Arguments:
input
Options:
-v, --verbose Sets verbosity level.
-h, --help Show this help message and exit.
-v, --verbose Sets verbosity level.
Commands:
help Show help for commands.
install Install a rock.
]], get_output("--help"))
end)
it("generates correct help message for command", function()
it("generates correct help message using help command", function()
assert.equal([[
Usage: ]]..script..[[ install [-f <from>] [-h] <rock> [<version>]
Usage: ]]..script..[[ [-h] [-v] <input> [<command>] ...
A testing program.
Arguments:
input
Options:
-h, --help Show this help message and exit.
-v, --verbose Sets verbosity level.
Commands:
help Show help for commands.
install Install a rock.
]], get_output("foo help"))
end)
it("generates correct help message for command using help flag", function()
assert.equal([[
Usage: ]]..script..[[ install [-h] [-f <from>] <rock> [<version>]
Install a rock.
@@ -106,11 +126,28 @@ Arguments:
version Version of the rock.
Options:
-h, --help Show this help message and exit.
-f <from>, Fetch the rock from this server.
--from <from>
-h, --help Show this help message and exit.
]], get_output("foo install --help"))
end)
it("generates correct help message for command using help command", function()
assert.equal([[
Usage: ]]..script..[[ install [-h] [-f <from>] <rock> [<version>]
Install a rock.
Arguments:
rock Name of the rock.
version Version of the rock.
Options:
-h, --help Show this help message and exit.
-f <from>, Fetch the rock from this server.
--from <from>
]], get_output("foo help install"))
end)
end)
describe("data flow", function()

View File

@@ -3,6 +3,7 @@ local Parser = require "argparse"
local parser = Parser()
:description "A testing program."
:add_help_command(true)
:require_command(false)
parser:argument "input"

View File

@@ -320,7 +320,7 @@ Usage: foo ([--opt1 <opt1>] | [--opt3 <opt3>] | [--opt5 <opt5>])
:args "*"
assert.equals([=[
Usage: foo [--set-important-property <set_important_property>] [-h]
Usage: foo [-h] [--set-important-property <set_important_property>]
<long_argument_name> <very_long_words> [--include [<include>] ...]]=], parser:get_usage())
end)
@@ -336,9 +336,9 @@ Usage: foo [--set-important-property <set_important_property>] [-h]
:args "*"
assert.equals([=[
Usage: foo
Usage: foo [-h]
[--set-important-property <set_important_property>]
[-h] <long_argument_name> <very_long_words>
<long_argument_name> <very_long_words>
[--include [<include>] ...]]=], parser:get_usage())
end)
end)

View File

@@ -202,9 +202,9 @@ end}
local add_help = {"add_help", function(self, value)
typecheck("add_help", {"boolean", "string", "table"}, value)
if self._has_help then
table.remove(self._options)
self._has_help = false
if self._help_option_idx then
table.remove(self._options, self._help_option_idx)
self._help_option_idx = nil
end
if value then
@@ -223,7 +223,50 @@ local add_help = {"add_help", function(self, value)
help "-h" "--help"
end
self._has_help = true
self._help_option_idx = #self._options
end
end}
local add_help_command = {"add_help_command", function(self, value)
typecheck("add_help_command", {"boolean", "string", "table"}, value)
if self._help_command_idx then
table.remove(self._commands, self._help_command_idx)
self._help_command_idx = nil
end
if value then
local help = self:command()
:description "Show help for commands."
help:argument "command"
:description "The command to show help for."
:args "?"
:action(function(_, _, cmd)
if not cmd then
print(self:get_help())
os.exit(0)
else
for _, command in ipairs(self._commands) do
for _, alias in ipairs(command._aliases) do
if alias == cmd then
print(command:get_help())
os.exit(0)
end
end
end
end
help:error(("unknown command '%s'"):format(cmd))
end)
if value ~= true then
help = help(value)
end
if not help._name then
help "help"
end
self._help_command_idx = #self._commands
end
end}
@@ -252,7 +295,8 @@ local Parser = class({
typechecked("help_usage_margin", "number"),
typechecked("help_description_margin", "number"),
typechecked("help_max_width", "number"),
add_help
add_help,
add_help_command
})
local Command = class({
@@ -600,13 +644,7 @@ end
function Parser:option(...)
local option = Option(...)
if self._has_help then
table.insert(self._options, #self._options, option)
else
table.insert(self._options, option)
end
table.insert(self._options, option)
return option
end