1*340f5e56SDavid van Moolenbroek-- Lua command line option parser. 2*340f5e56SDavid van Moolenbroek-- Interface based on Pythons optparse. 3*340f5e56SDavid van Moolenbroek-- http://docs.python.org/lib/module-optparse.html 4*340f5e56SDavid van Moolenbroek-- (c) 2008 David Manura, Licensed under the same terms as Lua (MIT license) 5*340f5e56SDavid van Moolenbroek-- 6*340f5e56SDavid van Moolenbroek-- To be used like this: 7*340f5e56SDavid van Moolenbroek-- t={usage="<some usage message>", version="<version string>"} 8*340f5e56SDavid van Moolenbroek-- op=OptionParser(t) 9*340f5e56SDavid van Moolenbroek-- op=add_option{"<opt>", action=<action>, dest=<dest>, help="<help message for this option>"} 10*340f5e56SDavid van Moolenbroek-- 11*340f5e56SDavid van Moolenbroek-- with : 12*340f5e56SDavid van Moolenbroek-- <opt> the option string to be used (can be anything, if one letter opt, then should be -x val, more letters: -xy=val ) 13*340f5e56SDavid van Moolenbroek-- <action> one of 14*340f5e56SDavid van Moolenbroek-- - store: store in options as key, val 15*340f5e56SDavid van Moolenbroek-- - store_true: stores key, true 16*340f5e56SDavid van Moolenbroek-- - store_false: stores key, false 17*340f5e56SDavid van Moolenbroek-- <dest> is the key under which the option is saved 18*340f5e56SDavid van Moolenbroek-- 19*340f5e56SDavid van Moolenbroek-- options,args = op.parse_args() 20*340f5e56SDavid van Moolenbroek-- 21*340f5e56SDavid van Moolenbroek-- now options is the table of options (key, val) and args is the table with non-option arguments. 22*340f5e56SDavid van Moolenbroek-- You can use op.fail(message) for failing and op.print_help() for printing the usage as you like. 23*340f5e56SDavid van Moolenbroek 24*340f5e56SDavid van Moolenbroekfunction OptionParser(t) 25*340f5e56SDavid van Moolenbroek local usage = t.usage 26*340f5e56SDavid van Moolenbroek local version = t.version 27*340f5e56SDavid van Moolenbroek 28*340f5e56SDavid van Moolenbroek local o = {} 29*340f5e56SDavid van Moolenbroek local option_descriptions = {} 30*340f5e56SDavid van Moolenbroek local option_of = {} 31*340f5e56SDavid van Moolenbroek 32*340f5e56SDavid van Moolenbroek function o.fail(s) -- extension 33*340f5e56SDavid van Moolenbroek io.stderr:write(s .. '\n') 34*340f5e56SDavid van Moolenbroek os.exit(1) 35*340f5e56SDavid van Moolenbroek end 36*340f5e56SDavid van Moolenbroek 37*340f5e56SDavid van Moolenbroek function o.add_option(optdesc) 38*340f5e56SDavid van Moolenbroek option_descriptions[#option_descriptions+1] = optdesc 39*340f5e56SDavid van Moolenbroek for _,v in ipairs(optdesc) do 40*340f5e56SDavid van Moolenbroek option_of[v] = optdesc 41*340f5e56SDavid van Moolenbroek end 42*340f5e56SDavid van Moolenbroek end 43*340f5e56SDavid van Moolenbroek function o.parse_args() 44*340f5e56SDavid van Moolenbroek -- expand options (e.g. "--input=file" -> "--input", "file") 45*340f5e56SDavid van Moolenbroek local arg = {unpack(arg)} 46*340f5e56SDavid van Moolenbroek for i=#arg,1,-1 do local v = arg[i] 47*340f5e56SDavid van Moolenbroek local flag, val = v:match('^(%-%-%w+)=(.*)') 48*340f5e56SDavid van Moolenbroek if flag then 49*340f5e56SDavid van Moolenbroek arg[i] = flag 50*340f5e56SDavid van Moolenbroek table.insert(arg, i+1, val) 51*340f5e56SDavid van Moolenbroek end 52*340f5e56SDavid van Moolenbroek end 53*340f5e56SDavid van Moolenbroek 54*340f5e56SDavid van Moolenbroek local options = {} 55*340f5e56SDavid van Moolenbroek local args = {} 56*340f5e56SDavid van Moolenbroek local i = 1 57*340f5e56SDavid van Moolenbroek while i <= #arg do local v = arg[i] 58*340f5e56SDavid van Moolenbroek local optdesc = option_of[v] 59*340f5e56SDavid van Moolenbroek if optdesc then 60*340f5e56SDavid van Moolenbroek local action = optdesc.action 61*340f5e56SDavid van Moolenbroek local val 62*340f5e56SDavid van Moolenbroek if action == 'store' or action == nil then 63*340f5e56SDavid van Moolenbroek i = i + 1 64*340f5e56SDavid van Moolenbroek val = arg[i] 65*340f5e56SDavid van Moolenbroek if not val then o.fail('option requires an argument ' .. v) end 66*340f5e56SDavid van Moolenbroek elseif action == 'store_true' then 67*340f5e56SDavid van Moolenbroek val = true 68*340f5e56SDavid van Moolenbroek elseif action == 'store_false' then 69*340f5e56SDavid van Moolenbroek val = false 70*340f5e56SDavid van Moolenbroek end 71*340f5e56SDavid van Moolenbroek options[optdesc.dest] = val 72*340f5e56SDavid van Moolenbroek else 73*340f5e56SDavid van Moolenbroek if v:match('^%-') then o.fail('invalid option ' .. v) end 74*340f5e56SDavid van Moolenbroek args[#args+1] = v 75*340f5e56SDavid van Moolenbroek end 76*340f5e56SDavid van Moolenbroek i = i + 1 77*340f5e56SDavid van Moolenbroek end 78*340f5e56SDavid van Moolenbroek if options.help then 79*340f5e56SDavid van Moolenbroek o.print_help() 80*340f5e56SDavid van Moolenbroek os.exit() 81*340f5e56SDavid van Moolenbroek end 82*340f5e56SDavid van Moolenbroek if options.version then 83*340f5e56SDavid van Moolenbroek io.stdout:write(t.version .. "\n") 84*340f5e56SDavid van Moolenbroek os.exit() 85*340f5e56SDavid van Moolenbroek end 86*340f5e56SDavid van Moolenbroek return options, args 87*340f5e56SDavid van Moolenbroek end 88*340f5e56SDavid van Moolenbroek 89*340f5e56SDavid van Moolenbroek local function flags_str(optdesc) 90*340f5e56SDavid van Moolenbroek local sflags = {} 91*340f5e56SDavid van Moolenbroek local action = optdesc.action 92*340f5e56SDavid van Moolenbroek for _,flag in ipairs(optdesc) do 93*340f5e56SDavid van Moolenbroek local sflagend 94*340f5e56SDavid van Moolenbroek if action == nil or action == 'store' then 95*340f5e56SDavid van Moolenbroek local metavar = optdesc.metavar or optdesc.dest:upper() 96*340f5e56SDavid van Moolenbroek sflagend = #flag == 2 and ' ' .. metavar 97*340f5e56SDavid van Moolenbroek or '=' .. metavar 98*340f5e56SDavid van Moolenbroek else 99*340f5e56SDavid van Moolenbroek sflagend = '' 100*340f5e56SDavid van Moolenbroek end 101*340f5e56SDavid van Moolenbroek sflags[#sflags+1] = flag .. sflagend 102*340f5e56SDavid van Moolenbroek end 103*340f5e56SDavid van Moolenbroek return table.concat(sflags, ', ') 104*340f5e56SDavid van Moolenbroek end 105*340f5e56SDavid van Moolenbroek 106*340f5e56SDavid van Moolenbroek function o.print_help() 107*340f5e56SDavid van Moolenbroek io.stdout:write("Usage: " .. usage:gsub('%%prog', arg[0]) .. "\n") 108*340f5e56SDavid van Moolenbroek io.stdout:write("\n") 109*340f5e56SDavid van Moolenbroek io.stdout:write("Options:\n") 110*340f5e56SDavid van Moolenbroek for _,optdesc in ipairs(option_descriptions) do 111*340f5e56SDavid van Moolenbroek io.stdout:write(" " .. flags_str(optdesc) .. 112*340f5e56SDavid van Moolenbroek " " .. optdesc.help .. "\n") 113*340f5e56SDavid van Moolenbroek end 114*340f5e56SDavid van Moolenbroek end 115*340f5e56SDavid van Moolenbroek o.add_option{"--help", action="store_true", dest="help", 116*340f5e56SDavid van Moolenbroek help="show this help message and exit"} 117*340f5e56SDavid van Moolenbroek if t.version then 118*340f5e56SDavid van Moolenbroek o.add_option{"--version", action="store_true", dest="version", 119*340f5e56SDavid van Moolenbroek help="output version info."} 120*340f5e56SDavid van Moolenbroek end 121*340f5e56SDavid van Moolenbroek return o 122*340f5e56SDavid van Moolenbroekend 123*340f5e56SDavid van Moolenbroek 124