Improved command line parsing

The first character after control character is now not required to be a letter
This commit is contained in:
mpeterv
2014-02-23 16:15:49 +04:00
parent ad4959b137
commit fc65c85a13
3 changed files with 31 additions and 23 deletions

View File

@@ -23,12 +23,12 @@ describe("tests related to help message generation", function()
it("uses custom help option", function() it("uses custom help option", function()
local parser = Parser "foo" local parser = Parser "foo"
:add_help {aliases = {"\\?"}} :add_help {name = "/?"}
assert.equal(table.concat({ assert.equal(table.concat({
"Usage: foo [\\?]", "Usage: foo [/?]",
"", "",
"Options: ", "Options: ",
" \\? Show this help message and exit. " " /? Show this help message and exit. "
}, "\r\n"), parser:prepare():get_help()) }, "\r\n"), parser:prepare():get_help())
end) end)

View File

@@ -16,6 +16,14 @@ describe("tests related to options", function()
assert.same({server = "foo"}, args) assert.same({server = "foo"}, args)
end) end)
it("handles non-standard charset", function()
local parser = Parser()
parser:option "/s"
parser:flag "/?"
local args = parser:parse{"/s", "foo", "/?"}
assert.same({s = "foo", ["?"] = true}, args)
end)
it("handles GNU-style long options", function() it("handles GNU-style long options", function()
local parser = Parser() local parser = Parser()
parser:option("-s", "--server") parser:option("-s", "--server")

View File

@@ -267,7 +267,11 @@ function Parser:prepare()
end) end)
if #self._help_option._aliases == 0 then if #self._help_option._aliases == 0 then
self._help_option "-h" "--help" if self._help_option._name then
self._help_option._aliases[1] = self._help_option._name
else
self._help_option "-h" "--help"
end
end end
if not self._help_option._description then if not self._help_option._description then
@@ -282,7 +286,7 @@ function Parser:prepare()
end end
for _, command in ipairs(self._commands) do for _, command in ipairs(self._commands) do
command._target =command._target or command._name command._target = command._target or command._name
command._name = self._name .. " " .. command._name command._name = self._name .. " " .. command._name
end end
@@ -700,26 +704,11 @@ function Parser:_parse(args, errhandler)
first = data:sub(1, 1) first = data:sub(1, 1)
if charset[first] then if charset[first] then
if #data > 1 then if #data > 1 then
if data:sub(2, 2):match "[a-zA-Z]" then plain = false
plain = false if data:sub(2, 2) == first then
for i = 2, #data do
name = first .. data:sub(i, i)
option = get_option(name)
handle_option(name)
if i ~= #data and option._minargs > 0 then
handle_argument(data:sub(i+1))
break
end
end
elseif data:sub(2, 2) == first then
if #data == 2 then if #data == 2 then
plain = false
handle_options = false handle_options = false
elseif data:sub(3, 3):match "[a-zA-Z]" then else
plain = false
local equal = data:find "=" local equal = data:find "="
if equal then if equal then
name = data:sub(1, equal-1) name = data:sub(1, equal-1)
@@ -733,6 +722,17 @@ function Parser:_parse(args, errhandler)
handle_option(data) handle_option(data)
end end
end end
else
for i = 2, #data do
name = first .. data:sub(i, i)
option = get_option(name)
handle_option(name)
if i ~= #data and option._minargs > 0 then
handle_argument(data:sub(i+1))
break
end
end
end end
end end
end end