Command Line Module


This module is intended for processing command line parameters of Lua scripts. It doesn't try to be POSIX (or any other standard) compliant, since it is very Lua-oriented and allows to specify parameters of any Lua data type.

The module exports just one function: cmdline.getparam (its detailed description is given in the comment preceding the function body).

See also: GetOpt, AlternativeGetOpt and PosixGetOpt

cmdline.lua

-- started: 2008年04月12日 by Shmuel Zeigerman
-- license: public domain
local ipairs,pairs,setfenv,tonumber,loadstring,type =
 ipairs,pairs,setfenv,tonumber,loadstring,type
local tinsert, tconcat = table.insert, table.concat
module(...)
local function commonerror (msg)
 return nil, ("[cmdline]: " .. msg)
end
local function argerror (msg, numarg)
 msg = msg and (": " .. msg) or ""
 return nil, ("[cmdline]: bad argument #" .. numarg .. msg)
end
local function iderror (numarg)
 return argerror("ID not valid", numarg)
end
local function idcheck (id)
 return id:match("^[%a_][%w_]*$") and true
end
--[[------------------------------------------------------------------------
Syntax:
 t_out = getparam(t_in [,options] [,params])
Parameters:
 t_in: table - list of string arguments to be processed in order
 (usually it is the `arg' table created by the Lua interpreter).
 * if an argument begins with ,ドル the $ is skipped and the rest is inserted
 into the array part of the output table.
 * if an argument begins with -, the rest is a sequence of variables
 (separated by commas or semicolons) that are all set to true;
 example: -var1,var2 --> var1,var2 = true,true
 * if an argument begins with !, the rest is a Lua chunk;
 example: !a=(40+3)*5;b=20;name="John";window={w=600,h=480}
 * if an argument contains =, then it is an assignment in the form
 var1,...=value (no space is allowed around the =)
 * if value begins with ,ドル the $ is skipped, the rest is a string
 example: var1,var2=$ --> var1,var2 = "",""
 example: var1,var2=125ドル --> var1,var2 = "125","125"
 example: var1,var2=$125ドル --> var1,var2 = "125ドル","125ドル"
 * if value is convertible to number, it is a number
 example: var1,var2=125 --> var1,var2 = 125,125
 * otherwise it is a string
 example: name=John --> name = "John"
 * if an argument neither begins with one of the special characters (-,!,$),
 nor contains =, it is inserted as is into the array part of the output
 table.
 options (optional): a list of names of all command-line options and parameters
 permitted in the application; used to check that each found option
 is valid; no checks are done if not supplied.
 params (optional): a list of names of all command-line parameters required
 by the application; used to check that each required parameter is present;
 no checks are done if not supplied.
Returns:
 On success: the output table, e.g. { [1]="./myfile.txt", name="John", age=40 }
 On error: nil followed by error message string.
--]]------------------------------------------------------------------------
function getparam (t_in, options, params)
 local t_out = {}
 for i,v in ipairs(t_in) do
 local prefix, command = v:sub(1,1), v:sub(2)
 if prefix == "$" then
 tinsert(t_out, command)
 elseif prefix == "-" then
 for id in command:gmatch"[^,;]+" do
 if not idcheck(id) then return iderror(i) end
 t_out[id] = true
 end
 elseif prefix == "!" then
 local f, err = loadstring(command)
 if not f then return argerror(err, i) end
 setfenv(f, t_out)()
 elseif v:find("=") then
 local ids, val = v:match("^([^=]+)%=(.*)") -- no space around =
 if not ids then return argerror("invalid assignment syntax", i) end
 val = val:sub(1,1)=="$" and val:sub(2) or tonumber(val) or val
 for id in ids:gmatch"[^,;]+" do
 if not idcheck(id) then return iderror(i) end
 t_out[id] = val
 end
 else
 tinsert(t_out, v)
 end
 end
 if options then
 local lookup, unknown = {}, {}
 for _,v in ipairs(options) do lookup[v] = true end
 for k,_ in pairs(t_out) do
 if lookup[k]==nil and type(k)=="string" then tinsert(unknown, k) end
 end
 if #unknown > 0 then
 return commonerror("unknown options: " .. tconcat(unknown, ", "))
 end
 end
 if params then
 local missing = {}
 for _,v in ipairs(params) do
 if t_out[v]==nil then tinsert(missing, v) end
 end
 if #missing > 0 then
 return commonerror("missing parameters: " .. tconcat(missing, ", "))
 end
 end
 return t_out
end

test_cmdline.lua

require "cmdline"
local getparam = cmdline.getparam
local function assertgood(...) return assert(getparam(...)) end
local function assertbad(...) return assert(not getparam(...)) end
local t_in = {
 "var1,var1b=John",
 "var2,var2b=$Peter",
 "var3,var3b=005ドル",
 "var4,var4b=005",
 "!var5=8/2;var6=var5*40;var7=\"Ann\"",
 "!var8=nil",
 "!var9={} and 5 and 6",
 "-a,b2,c",
 "abcd",
 "/bin",
 "$-abc"
}
local function test1(t_out)
 assert (t_out.var1 == "John" and t_out.var1b == "John")
 assert (t_out.var2 == "Peter" and t_out.var2b == "Peter")
 assert (t_out.var3 == "005" and t_out.var3b == "005")
 assert (t_out.var4 == 5 and t_out.var4b == 5)
 assert (t_out.var5 == 4)
 assert (t_out.var6 == 160)
 assert (t_out.var7 == "Ann")
 assert (t_out.var8 == nil)
 assert (t_out.var9 == 6)
 assert (t_out.a==true and t_out.b2==true and t_out.c==true)
 assert (t_out[1] == "abcd")
 assert (t_out[2] == "/bin")
 assert (t_out[3] == "-abc")
end
local options = {
 "var1", "var1b", "var2", "var2b", "var3", "var3b", "var4", "var4b", "var5",
 "var6", "var7", "var8", "var9", "a", "b2", "c"
}
local t_out = assertgood(t_in) -- no options checking
test1(t_out)
local t_out = assertgood(t_in, options) -- options checking
test1(t_out)
assertbad(t_in, {}) -- no options permitted
local t_out = assertgood(t_in, nil, {3, "var1"}) -- parameters checking
test1(t_out)
assertbad(t_in, nil, {"var0"}) -- parameter missing
local t_bad = { -- bad syntax tests
 {"!abc"}, {"--88"}, {"-a,8,b"}, {"=8a=1"}
}
for _,v in ipairs(t_bad) do assertbad(v) end
print ("OK: test_cmdline")

RecentChanges · preferences
edit · history
Last edited December 11, 2009 6:40 pm GMT (diff)

AltStyle によって変換されたページ (->オリジナル) /