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