Skip to content

Commit

Permalink
Redesign argument storing
Browse files Browse the repository at this point in the history
* Use state objects instead of tons of locals in the main
  function.
* Use actions for storing arguments into result table.
  Actions are now called at the end of each invocation,
  with result table, target index, arguments and overwrite flag as
  arguments.
* Remove command actions.
* Improve error messages, refer to options by the last used alias
  instead of the main name.

TODO:

* Improve error messages further ("argument 'foo' is required"
  -> "missing argument 'foo'", etc.).
* Add actions for positional arguments.
* Add actions for commands (should be called with final results
  after parsing is over, in "innermost first" order).
* Allow referring to built-in actions by strings a-la Python
  (e.g. action = "store_false").
* Allow setting initial value to be stored at target index
  for each option (perhaps use default value for that).
* Add more tests, particularly for actions.
  • Loading branch information
mpeterv committed Oct 29, 2015
1 parent 98114c6 commit 247c8a9
Show file tree
Hide file tree
Showing 7 changed files with 407 additions and 369 deletions.
33 changes: 10 additions & 23 deletions spec/actions_spec.lua
Expand Up @@ -3,8 +3,14 @@ getmetatable(Parser()).error = function(_, msg) error(msg) end

describe("tests related to actions", function()
it("calls actions for options", function()
local action1 = spy.new(function() end)
local action2 = spy.new(function() end)
local action1 = spy.new(function(_, _, arg)
assert.equal("nowhere", arg)
end)
local expected_args = {"Alice", "Bob"}
local action2 = spy.new(function(_, _, args)
assert.same(expected_args, args)
expected_args = {"Emma", "John"}
end)

local parser = Parser()
parser:option "-f" "--from" {
Expand All @@ -16,8 +22,7 @@ describe("tests related to actions", function()
args = 2
}

local args = parser:parse{"-fnowhere", "--pair", "Alice", "Bob", "-p", "Emma", "John"}
assert.same({from = "nowhere", pair = {{"Alice", "Bob"}, {"Emma", "John"}}}, args)
parser:parse{"-fnowhere", "--pair", "Alice", "Bob", "-p", "Emma", "John"}
assert.spy(action1).called(1)
assert.spy(action2).called(2)
end)
Expand All @@ -39,27 +44,9 @@ describe("tests related to actions", function()
action = function(...) return action3(...) end
}

local args = parser:parse{"-vv", "--quiet"}
assert.same({verbose = 2, quiet = true}, args)
parser:parse{"-vv", "--quiet"}
assert.spy(action1).called(2)
assert.spy(action2).called(1)
assert.spy(action3).called(0)
end)

it("calls actions for commands", function()
local action = spy.new(function() end)

local parser = Parser "name"
parser:flag "-v" "--verbose" {
count = "0-3"
}
local add = parser:command "add" {
action = function(...) return action(...) end
}
add:argument "something"

local args = parser:parse{"add", "me"}
assert.same({add = true, verbose = 0, something = "me"}, args)
assert.spy(action).called(1)
end)
end)
10 changes: 5 additions & 5 deletions spec/arguments_spec.lua
Expand Up @@ -97,7 +97,7 @@ describe("tests related to positional arguments", function()
local parser = Parser()
parser:argument "foo"

assert.has_error(function() parser:parse{} end, "too few arguments")
assert.has_error(function() parser:parse{} end, "argument 'foo' is required")
end)

it("handles extra arguments with several arguments correctly", function()
Expand All @@ -113,15 +113,15 @@ describe("tests related to positional arguments", function()
parser:argument "foo1"
parser:argument "foo2"

assert.has_error(function() parser:parse{"bar"} end, "too few arguments")
assert.has_error(function() parser:parse{"bar"} end, "argument 'foo2' is required")
end)

it("handles too few arguments with multi-argument correctly", function()
local parser = Parser()
parser:argument "foo" {
args = "+"
}
assert.has_error(function() parser:parse{} end, "too few arguments")
assert.has_error(function() parser:parse{} end, "argument 'foo' is required")
end)

it("handles too many arguments with multi-argument correctly", function()
Expand All @@ -137,7 +137,7 @@ describe("tests related to positional arguments", function()
parser:argument "foo" {
args = "2-4"
}
assert.has_error(function() parser:parse{"foo"} end, "too few arguments")
assert.has_error(function() parser:parse{"foo"} end, "argument 'foo' requires at least 2 arguments")
end)

it("handles too many arguments with several multi-arguments correctly", function()
Expand All @@ -159,7 +159,7 @@ describe("tests related to positional arguments", function()
parser:argument "foo2" {
args = "*"
}
assert.has_error(function() parser:parse{} end, "too few arguments")
assert.has_error(function() parser:parse{} end, "argument 'foo1' is required")
end)
end)
end)
2 changes: 1 addition & 1 deletion spec/default_spec.lua
Expand Up @@ -55,7 +55,7 @@ describe("tests related to default values", function()
assert.same({output = "a.out"}, args)
args = parser:parse{"--output", "foo.txt"}
assert.same({output = "foo.txt"}, args)
assert.has_error(function() parser:parse{"-o"} end, "too few arguments")
assert.has_error(function() parser:parse{"-o"} end, "option '-o' requires an argument")
end)

it("handles option with default value for multi-argument option correctly", function()
Expand Down
4 changes: 2 additions & 2 deletions spec/integrity_spec.lua
Expand Up @@ -20,7 +20,7 @@ describe("tests related to CLI behaviour #unsafe", function()
assert.equal([[
Usage: ]]..script..[[ [-v] [-h] <input> [<command>] ...
Error: too few arguments
Error: argument 'input' is required
]], get_output(""))
end)

Expand Down Expand Up @@ -62,7 +62,7 @@ Did you mean 'install'?
assert.equal([[
Usage: ]]..script..[[ install [-f <from>] [-h] <rock> [<version>]
Error: too few arguments
Error: argument 'rock' is required
]], get_output("foo install"))
end)

Expand Down
5 changes: 3 additions & 2 deletions spec/options_spec.lua
Expand Up @@ -258,7 +258,8 @@ describe("tests related to options", function()
it("handles lack of required argument correctly", function()
local parser = Parser()
parser:option "-s" "--server"
assert.has_error(function() parser:parse{"--server"} end, "too few arguments")
assert.has_error(function() parser:parse{"--server"} end, "option '--server' requires an argument")
assert.has_error(function() parser:parse{"-s"} end, "option '-s' requires an argument")
end)

it("handles unknown options correctly", function()
Expand Down Expand Up @@ -289,7 +290,7 @@ describe("tests related to options", function()
count = 1,
overwrite = false
}
assert.has_error(function() parser:parse{"-qq"} end, "option '-q' must be used at most 1 time")
assert.has_error(function() parser:parse{"-qq"} end, "option '-q' must be used 1 time")
end)

it("handles too few invocations correctly", function()
Expand Down
8 changes: 4 additions & 4 deletions spec/pparse_spec.lua
Expand Up @@ -15,13 +15,13 @@ describe("tests related to :pparse()", function()
parser:argument "foo"
local ok, errmsg = parser:pparse{}
assert.is_false(ok)
assert.equal("too few arguments", errmsg)
assert.equal("argument 'foo' is required", errmsg)
end)

it("still raises an error if it is caused by misconfiguration", function()
it("rethrows errors from callbacks", function()
local parser = Parser()
parser:flag "--foo"
:action(error)
assert.has_error(function() parser:pparse{"--foo"} end)
:action(function() error("some error message") end)
assert.error_matches(function() parser:pparse{"--foo"} end, "some error message")
end)
end)

0 comments on commit 247c8a9

Please sign in to comment.