aboutsummaryrefslogtreecommitdiff
path: root/nerv/init.lua
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2016-03-02 13:36:23 +0800
committerDeterminant <ted.sybil@gmail.com>2016-03-02 13:36:23 +0800
commit3b37f42aaec7f7f20353d58f62b8afb2316b3030 (patch)
tree98978ca13ec89161f3c4e2c9c15ddb33ad3eebe5 /nerv/init.lua
parente9f5eb2202b3c94320b151b36d79feaebaa2755e (diff)
add `nerv.parse_args(argv, options)`
Diffstat (limited to 'nerv/init.lua')
-rw-r--r--nerv/init.lua103
1 files changed, 103 insertions, 0 deletions
diff --git a/nerv/init.lua b/nerv/init.lua
index 4aa7a45..fdfd531 100644
--- a/nerv/init.lua
+++ b/nerv/init.lua
@@ -172,6 +172,109 @@ function nerv.include(filename)
return dofile(nerv.dirname(caller) .. filename)
end
+--- Parse the command-line options and arguments
+function nerv.parse_args(argv, options)
+ local is_opt_exp = "^[-](.*)$"
+ local sim_opt_exp = "^[-]([a-z]+)$"
+ local opt_exp = "^[-][-]([^=]+)$"
+ local opt_with_val_exp = "^[-][-]([^=]+)=([^=]+)$"
+ local opts = {}
+ local sopts = {}
+ local args = {}
+ local function err()
+ nerv.error("invalid format of option specification")
+ end
+ for _, v in ipairs(options) do
+ if type(v) ~= "table" or
+ (v[1] == nil and v[2] == nil) or
+ v[3] == nil then
+ err()
+ end
+ opt_full = v[1]
+ opt_short = v[2]
+ opt_type = v[3]
+ local opt_meta = {type = opt_type,
+ desc = v.desc or "",
+ val = v.default}
+ if opt_short ~= nil then
+ if type(opt_short) ~= "string" then err() end
+ if opt_type ~= "bool" then
+ nerv.error("only boolean option could have short form")
+ end
+ sopts[opt_short] = opt_meta
+ end
+ if opt_full ~= nil then
+ if type(opt_full) ~= "string" then err() end
+ opts[opt_full] = opt_meta
+ end
+ end
+ for _, token in ipairs(argv) do
+ if token:match(is_opt_exp) then
+ local k = token:match(sim_opt_exp)
+ if k then
+ for c in k:gmatch"." do
+ if sopts[c] then
+ sopts[c].val = true
+ else
+ nerv.error("invalid option -%s", c)
+ end
+ end
+ else
+ local k = token:match(opt_exp)
+ if k then
+ if opts[k] == nil then
+ nerv.error("invalid option %s", token)
+ end
+ if opts[k].type ~= "bool" then
+ nerv.error("invalid option --%s: " ..
+ "a %s value needs to be specified",
+ k, opts[k].type)
+ else
+ opts[k].val = true
+ end
+ else
+ local k, v = token:match(opt_with_val_exp)
+ if k then
+ if opts[k] == nil then
+ nerv.error("invalid option %s", token)
+ end
+ if opts[k].type == "bool" then
+ if v == "yes" then
+ opts[k].val = true
+ elseif v == "no" then
+ opts[k].val = false
+ else
+ nerv.error("bool value should be \"yes\" or \"no\"")
+ end
+ elseif opts[k].type == "int" then
+ local t = tonumber(v)
+ opts[k].val = t
+ if t == nil or math.floor(t) ~= t then
+ nerv.error("int value is expected")
+ end
+ elseif opts[k].type == "float" then
+ local t = tonumber(v)
+ opts[k].val = t
+ if t == nil then
+ nerv.error("float value is expected")
+ end
+ elseif opts[k].type == "string" then
+ opts[k].val = v
+ else
+ nerv.error("unrecognized type %s", opts[k].type)
+ end
+ else
+ nerv.error("unrecognized option %s", token)
+ end
+ end
+ end
+ else
+ table.insert(args, token)
+ end
+ end
+ return args, opts
+end
+
-- the following lines trigger the initialization of basic modules
nerv.include('matrix/init.lua')