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