Posix Get Opt |
|
The following should behave exactly according to the [POSIX/SUS definition], except that the return value differs slightly so that there's no global state.
-- -- opt is either the option character, "?", or ":". -- -- If opt is the option character, arg is either a string or false--if optstring -- did not specify a required argument. -- -- If opt is either "?" or ":", then arg is the unknown option or the option -- lacking the required argument. Like the standard says, there's really only -- one scenario for ":" to ever be returned. And per the standard, unless -- optstring begins with a colon, "?" is returned instead. -- for opt, arg in getopt(":a:b", ...) do print("opt:", opt, "arg:", arg) end
-- -- getopt(":a:b", ...) -- works just like getopt(3). -- -- Send bug reports to william@25thandClement.com. -- function getopt(optstring, ...) local opts = { } local args = { ... } for optc, optv in optstring:gmatch"(%a)(:?)" do opts[optc] = { hasarg = optv == ":" } end return coroutine.wrap(function() local yield = coroutine.yield local i = 1 while i <= #args do local arg = args[i] i = i + 1 if arg == "--" then break elseif arg:sub(1, 1) == "-" then for j = 2, #arg do local opt = arg:sub(j, j) if opts[opt] then if opts[opt].hasarg then if j == #arg then if args[i] then yield(opt, args[i]) i = i + 1 elseif optstring:sub(1, 1) == ":" then yield(':', opt) else yield('?', opt) end else yield(opt, arg:sub(j + 1)) end break else yield(opt, false) end else yield('?', opt) end end else yield(false, arg) end end for i = i, #args do yield(false, args[i]) end end) end