Home | History | Annotate | Line # | Download | only in lua
optparse.lua revision 1.1.1.1.44.1
      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 
     24 function 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 = {table.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
    122 end
    123 
    124