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