99725b43ba
This library can easily process flags, arguments, and flags with arguments.
121 lines
5.3 KiB
Lua
121 lines
5.3 KiB
Lua
local cliParse = {}
|
|
local cliParseConfig
|
|
|
|
function cliParse.config(config)
|
|
-- Check if config is valid
|
|
checkArg(1, config, "table")
|
|
for flagName, argCount in pairs(config) do
|
|
if type(flagName) ~= "string" then
|
|
error("Flag name " .. tostring(flagName) .. " must be a string")
|
|
end
|
|
if type(argCount) == "table" then -- Min and max arg count specified
|
|
if type(argCount[1]) ~= "number" then
|
|
error("Min args for flag " .. flagName .. " must be a number")
|
|
end
|
|
if argCount[1] < 0 then
|
|
error("Min args for flag " .. flagName .. " must not be lower than 0")
|
|
end
|
|
if type(argCount[2]) ~= "number" then
|
|
error("Max args for flag " .. flagName .. " must be a number")
|
|
end
|
|
if argCount[2] < 0 then
|
|
error("Max args for flag " .. flagName .. " must not be lower than 0")
|
|
end
|
|
if argCount[2] < argCount[1] then
|
|
error("Max args for flag " .. flagName .. " must be more than or equal to min args")
|
|
end
|
|
elseif type(argCount) == "number" then -- Required arg count specified
|
|
if argCount < 0 then
|
|
error("Required args for flag " .. flagName .. " must not be lower than 0")
|
|
end
|
|
else
|
|
error("Arg count for flag " .. flagName .. " must be either a table of 2 numbers or a number")
|
|
end
|
|
-- Config is all good, set it
|
|
cliParseConfig = config
|
|
end
|
|
end
|
|
|
|
function cliParse.parse(...)
|
|
local args = { ... }
|
|
local returnTable = { ["flags"] = {}, ["args"] = {} } -- This will be filled out and returned in the end
|
|
|
|
for i = 1, #args do -- This is used instead of pairs() so that the code can skip ahead when it finds arguments instead of flags by just incrementing i
|
|
local flagList = {}
|
|
if args[i]:sub(1, 2) == "--" then -- Long flag
|
|
flagList = { args[i]:sub(3) }
|
|
elseif args[i]:sub(1, 1) == "-" then -- Short flag(s)
|
|
for i2 = 2, #args[i] do -- i is 2 to account for the - character at the start
|
|
table.insert(flagList, args[i]:sub(i2, i2))
|
|
end
|
|
end
|
|
for flagIndex, flag in ipairs(flagList) do -- Yes, this has to be in the argument loop for the skipahead to work.
|
|
local flagConfig = cliParseConfig[flag]
|
|
if flagConfig then -- This is a real flag
|
|
returnTable.flags[flag] = {}
|
|
if type(flagConfig) == "table" then
|
|
if flagIndex ~= #flagList then -- This flag is in a chain and it's not the last one
|
|
if flagConfig[1] ~= 0 then
|
|
return false, "Flag " .. flag .. " expects at least " .. flagConfig[1] .. " arguments, got 0"
|
|
end
|
|
else
|
|
for i2 = 1, flagConfig[1] do -- Iterate through the items AFTER the flags to find the minimum arguments
|
|
if args[i + i2]:sub(1, 1) ~= "-" then -- This checks for both long and short flags
|
|
table.insert(returnTable.flags[flag], args[i + i2]) -- Insert the argument found into the return table
|
|
else
|
|
return false, "Flag " .. flag .. " expects at least " .. flagConfig[1] .. " arguments, got " .. i2
|
|
end
|
|
end
|
|
i = i + flagConfig[1]
|
|
local i2IncrementAmount -- See line 71 and 76
|
|
for i2 = 1, flagConfig[2] - flagConfig[1] do -- Now search for the max args
|
|
if args[i + i2]:sub(1, 1) ~= "-" then -- This checks for both long and short flags
|
|
table.insert(returnTable.flags[flag], args[i + i2]) -- Insert the argument found into the return table
|
|
else
|
|
i2IncrementAmount = i2 - 1
|
|
-- Since the current argument is NOT a valid one, decrement by 1 to return to the last valid one (this is important when adding i2 to i)
|
|
break
|
|
end
|
|
end
|
|
i = i + (i2IncrementAmount or flagConfig[2])
|
|
end
|
|
else -- Flag required args are a single number
|
|
if flagIndex ~= #flagList then -- This flag is in a chain and it's not the last one
|
|
if flagConfig ~= 0 then
|
|
return false, "Flag " .. flag .. " expects " .. flagConfig .. " arguments, got 0"
|
|
end
|
|
else
|
|
for i2 = 1, flagConfig do -- Now search for the max args
|
|
if args[i + i2]:sub(1, 1) ~= "-" then -- This checks for both long and short flags
|
|
table.insert(returnTable.flags[flag], args[i + i2]) -- Insert the argument found into the return table
|
|
else
|
|
return false, "Flag " .. flag .. " expects " .. flagConfig[1] .. " arguments, got " .. i2
|
|
end
|
|
end
|
|
i = i + flagConfig
|
|
end
|
|
end
|
|
else
|
|
return false, "Unexpected flag: " .. flag
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, arg in pairs(args) do
|
|
local foundArg = false
|
|
for _, flag in pairs(returnTable.flags) do -- A loop in a loop... Peak efficiency
|
|
if table.find(flag, arg) or arg:sub(1, 1) == "-" then -- AAAND ANOTHER LOOP?!
|
|
foundArg = true
|
|
break
|
|
end
|
|
end
|
|
if not foundArg then
|
|
table.insert(returnTable.args, arg)
|
|
end
|
|
end
|
|
|
|
return returnTable
|
|
end
|
|
|
|
return cliParse
|