mirror of
https://github.com/TangentFoxy/argparse.git
synced 2025-07-28 02:52:20 +00:00
Added mutually exclusive groups
This commit is contained in:
@@ -11,7 +11,7 @@ description = {
|
|||||||
}
|
}
|
||||||
dependencies = {
|
dependencies = {
|
||||||
"lua >= 5.1, < 5.3",
|
"lua >= 5.1, < 5.3",
|
||||||
"30log >= 0.8"
|
"30log >= 0.9.1"
|
||||||
}
|
}
|
||||||
build = {
|
build = {
|
||||||
type = "builtin",
|
type = "builtin",
|
||||||
|
67
spec/mutex_spec.lua
Normal file
67
spec/mutex_spec.lua
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
local Parser = require "argparse"
|
||||||
|
|
||||||
|
describe("tests related to mutexes", function()
|
||||||
|
it("handles mutex correctly", function()
|
||||||
|
local parser = Parser()
|
||||||
|
parser:mutex(
|
||||||
|
parser:flag "-q" "--quiet"
|
||||||
|
:description "Supress logging. ",
|
||||||
|
parser:flag "-v" "--verbose"
|
||||||
|
:description "Print additional debug information. "
|
||||||
|
)
|
||||||
|
|
||||||
|
local args = parser:parse{"-q"}
|
||||||
|
assert.same({quiet = true}, args)
|
||||||
|
args = parser:parse{"-v"}
|
||||||
|
assert.same({verbose = true}, args)
|
||||||
|
args = parser:parse{}
|
||||||
|
assert.same({}, args)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("raises an error if mutex is broken", function()
|
||||||
|
local parser = Parser()
|
||||||
|
parser:mutex(
|
||||||
|
parser:flag "-q" "--quiet"
|
||||||
|
:description "Supress logging. ",
|
||||||
|
parser:flag "-v" "--verbose"
|
||||||
|
:description "Print additional debug information. "
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.has_error(function() parser:parse{"-qv"} end, "option '-v' can not be used together with option '-q'")
|
||||||
|
assert.has_error(function() parser:parse{"-v", "--quiet"} end, "option '--quiet' can not be used together with option '-v'")
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("handles multiple mutexes", function()
|
||||||
|
local parser = Parser()
|
||||||
|
parser:mutex(
|
||||||
|
parser:flag "-q" "--quiet",
|
||||||
|
parser:flag "-v" "--verbose"
|
||||||
|
)
|
||||||
|
parser:mutex(
|
||||||
|
parser:flag "-l" "--local",
|
||||||
|
parser:option "-f" "--from"
|
||||||
|
)
|
||||||
|
|
||||||
|
local args = parser:parse{"-qq", "-fTHERE"}
|
||||||
|
assert.same({quiet = true, from = "THERE"}, args)
|
||||||
|
args = parser:parse{"-vl"}
|
||||||
|
assert.same({verbose = true, ["local"] = true}, args)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("handles mutexes in commands", function()
|
||||||
|
local parser = Parser()
|
||||||
|
parser:mutex(
|
||||||
|
parser:flag "-q" "--quiet",
|
||||||
|
parser:flag "-v" "--verbose"
|
||||||
|
)
|
||||||
|
local install = parser:command "install"
|
||||||
|
install:mutex(
|
||||||
|
install:flag "-l" "--local",
|
||||||
|
install:option "-f" "--from"
|
||||||
|
)
|
||||||
|
|
||||||
|
local args = parser:parse{"install", "-l"}
|
||||||
|
assert.same({install = true, ["local"] = true}, args)
|
||||||
|
assert.has_error(function() parser:parse{"install", "-qlv"} end, "option '-v' can not be used together with option '-q'")
|
||||||
|
end)
|
||||||
|
end)
|
@@ -158,4 +158,25 @@ describe("tests related to usage message generation", function()
|
|||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("creates correct usage message for mutexes", function()
|
||||||
|
local parser = Parser "foo"
|
||||||
|
:add_help(false)
|
||||||
|
parser:mutex(
|
||||||
|
parser:flag "-q" "--quiet",
|
||||||
|
parser:flag "-v" "--verbose",
|
||||||
|
parser:flag "-i" "--interactive"
|
||||||
|
)
|
||||||
|
parser:mutex(
|
||||||
|
parser:flag "-l" "--local",
|
||||||
|
parser:option "-f" "--from"
|
||||||
|
)
|
||||||
|
parser:option "--yet-another-option"
|
||||||
|
|
||||||
|
assert.equal(table.concat({
|
||||||
|
"Usage: foo ([-q] | [-v] | [-i]) ([-l] | [-f <from>])",
|
||||||
|
" [--yet-another-option <yet-another-option>]"
|
||||||
|
}, "\r\n"), parser:get_usage()
|
||||||
|
)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
@@ -157,6 +157,7 @@ do -- Create classes with setters
|
|||||||
_arguments = {},
|
_arguments = {},
|
||||||
_options = {},
|
_options = {},
|
||||||
_commands = {},
|
_commands = {},
|
||||||
|
_mutexes = {},
|
||||||
_require_command = true
|
_require_command = true
|
||||||
}, {
|
}, {
|
||||||
name = typecheck.string "name",
|
name = typecheck.string "name",
|
||||||
@@ -424,6 +425,17 @@ function Parser:command(...)
|
|||||||
return command
|
return command
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Parser:mutex(...)
|
||||||
|
local options = {...}
|
||||||
|
|
||||||
|
for i, option in ipairs(options) do
|
||||||
|
assert(getmetatable(option) == Option, ("bad argument #%d to 'mutex' (Option expected)"):format(i))
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(self._mutexes, options)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
local max_usage_width = 70
|
local max_usage_width = 70
|
||||||
local usage_welcome = "Usage: "
|
local usage_welcome = "Usage: "
|
||||||
|
|
||||||
@@ -442,9 +454,25 @@ function Parser:get_usage()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- set of mentioned elements
|
||||||
|
local used = {}
|
||||||
|
|
||||||
|
for _, mutex in ipairs(self._mutexes) do
|
||||||
|
local buf = {}
|
||||||
|
|
||||||
|
for _, option in ipairs(mutex) do
|
||||||
|
table.insert(buf, option:_get_usage())
|
||||||
|
used[option] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
add("(" .. table.concat(buf, " | ") .. ")")
|
||||||
|
end
|
||||||
|
|
||||||
for _, elements in ipairs{self._options, self._arguments} do
|
for _, elements in ipairs{self._options, self._arguments} do
|
||||||
for _, element in ipairs(elements) do
|
for _, element in ipairs(elements) do
|
||||||
add(element:_get_usage())
|
if not used[element] then
|
||||||
|
add(element:_get_usage())
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -583,6 +611,8 @@ function Parser:_parse(args, errhandler)
|
|||||||
local options = {}
|
local options = {}
|
||||||
local arguments = {}
|
local arguments = {}
|
||||||
local commands
|
local commands
|
||||||
|
local option_mutexes = {}
|
||||||
|
local used_mutexes = {}
|
||||||
local opt_context = {}
|
local opt_context = {}
|
||||||
local com_context
|
local com_context
|
||||||
local result = {}
|
local result = {}
|
||||||
@@ -726,6 +756,16 @@ function Parser:_parse(args, errhandler)
|
|||||||
invocations[option] = 0
|
invocations[option] = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for _, mutex in ipairs(parser._mutexes) do
|
||||||
|
for _, option in ipairs(mutex) do
|
||||||
|
if not option_mutexes[option] then
|
||||||
|
option_mutexes[option] = {mutex}
|
||||||
|
else
|
||||||
|
table.insert(option_mutexes[option], mutex)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for _, argument in ipairs(parser._arguments) do
|
for _, argument in ipairs(parser._arguments) do
|
||||||
table.insert(arguments, argument)
|
table.insert(arguments, argument)
|
||||||
invocations[argument] = 0
|
invocations[argument] = 0
|
||||||
@@ -784,6 +824,17 @@ function Parser:_parse(args, errhandler)
|
|||||||
end
|
end
|
||||||
|
|
||||||
cur_option = opt_context[data]
|
cur_option = opt_context[data]
|
||||||
|
|
||||||
|
if option_mutexes[cur_option] then
|
||||||
|
for _, mutex in ipairs(option_mutexes[cur_option]) do
|
||||||
|
if used_mutexes[mutex] and used_mutexes[mutex] ~= cur_option then
|
||||||
|
error_("option '%s' can not be used together with option '%s'", data, used_mutexes[mutex]._name)
|
||||||
|
else
|
||||||
|
used_mutexes[mutex] = cur_option
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
do_action(cur_option)
|
do_action(cur_option)
|
||||||
invoke(cur_option)
|
invoke(cur_option)
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user