local function help(opts) io.write(arg[0]) io.write(" ") for _, v in ipairs(opts) do if v.kind == nil then io.write("[" .. v.name .. "] ") end end io.write("\n") local max_width = 0 for _, v in ipairs(opts) do if v.kind ~= nil then max_width = math.max(v.name:len(), max_width) end end for _, v in ipairs(opts) do if v.kind == nil then goto next end if v.kind == 'property' then io.write("\t" .. "--" .. v.name .. " ") elseif v.kind == 'flag' then io.write("\t" .. "--" .. v.name .. " ") end if v.description ~= nil then io.write(string.rep(" ", max_width - v.name:len()) .. " " .. "-- ") if v.required then io.write("(required) ") end io.write(v.description) end io.write("\n") ::next:: end os.exit() end function string:flag() if self:sub(1, 2) ~= "--" then return nil end return self:sub(3) end return function (opts) local args = {} local current_index = 1 local current_flag = nil local params = {} for _, v in ipairs(opts) do if v.kind ~= nil then params[v.name] = v args[v.name] = v.default else params[#params + 1] = v end end for _, value in ipairs(arg) do local key = nil if current_flag == nil then local flag = value:flag() if flag == nil then local option = params[current_index] current_index = current_index + 1 if option == nil then print("error: too many arguments") help(opts) end key = option.name else local option = params[flag] if option == nil then print("error: unknown flag '" .. flag .. "'") help(opts) end if option.kind == 'flag' then key = flag value = true else current_flag = flag goto next end end else local option = params[current_flag] key = option.name current_flag = nil end args[key] = value ::next:: end for _, option in ipairs(opts) do if (option.kind == nil or option.required) and args[option.name] == nil then print("error: missing argument '" .. option.name .. "'") help(opts) end end return args end