local _ = require "lua-ext"
local function default_opt_unknown(opt_repr)
error(("Unrecognized option: %q"):format(opt_repr))
end
local function handle_opt(get_arg_value, opt_repr, opt_unknown, unkeyed_opt, keyed_opt)
if keyed_opt then
local handle_with_value = keyed_opt
handle_with_value(opt_repr, get_arg_value())
elseif unkeyed_opt then
local handle_without_value = unkeyed_opt
handle_without_value(opt_repr)
else
local handle_unknown = opt_unknown
handle_unknown(opt_repr)
end
end
local function getopt(argv, short_opts, long_opts)
local opt_unknown = short_opts["?"] or default_opt_unknown
local argv_index = 1
local argc = #argv
while argv_index <= argc do
local arg = argv[argv_index]
if arg:sub(1, 1) ~= "-" then
break
end
if arg == "-" then
break
end
if arg == "--" then
argv_index = argv_index + 1
break
end
if arg:sub(1, 2) == "--" then
local arg_equals = arg:find("=", 1, true)
local opt_repr = arg
if arg_equals then
opt_repr = opt_repr:sub(1, arg_equals - 1)
end
local opt_repr_substr = opt_repr:sub(3)
local long_unkeyed_opt = long_opts[opt_repr_substr]
local long_keyed_opt = long_opts[opt_repr_substr .. ":"]
if type(long_keyed_opt) == "string" then
long_keyed_opt = short_opts[long_keyed_opt]
end
if type(long_unkeyed_opt) == "string" then
if long_keyed_opt == nil then
long_keyed_opt = short_opts[long_unkeyed_opt .. ":"]
end
long_unkeyed_opt = short_opts[long_unkeyed_opt]
end
local function get_arg_value()
if arg_equals then
return arg:sub(arg_equals + 1)
end
local next_argv_index = argv_index + 1
if next_argv_index <= argc then
local arg_value = argv[next_argv_index]
argv_index = next_argv_index
return arg_value
end
error(("Value not provided for option: %q"):format(opt_repr))
end
handle_opt(get_arg_value, opt_repr, opt_unknown, long_unkeyed_opt, long_keyed_opt)
else
local new_arg_wanted = false
for arg_index, arg_char in arg:chars(2) do
local opt_repr = "-" .. arg_char
local function get_arg_value()
local next_argv_index = argv_index + 1
if arg_index == #arg and next_argv_index <= argc then
local arg_value = argv[next_argv_index]
new_arg_wanted, argv_index = true, next_argv_index
return arg_value
end
error(("Value not provided for option: %q"):format(opt_repr))
end
handle_opt(get_arg_value, opt_repr, opt_unknown, short_opts[arg_char], short_opts[arg_char .. ":"])
if new_arg_wanted then
break
end
end
end
argv_index = argv_index + 1
end
return argv_index
end
return getopt