# Posix Get Opt

## Pure Lua

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.

### Usage

```--
-- 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
```

### Code

```--
-- 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
```