Welcome to mirror list, hosted at ThFree Co, Russian Federation.

OptionParser.lua - github.com/torch/xlua.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: facad43b65c800b91bc65da5c735b3053a657e07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
--
-- Lua command line option parser.
-- Interface based on Pythons optparse.
-- http://docs.python.org/lib/module-optparse.html
-- (c) 2008 David Manura, Licensed under the same terms as Lua (MIT license)
--
-- To be used like this:
-- t={usage="<some usage message>", version="<version string>"}
-- op = xlua.OptionParser(t)
-- op:option{"<opt>", action=<action>, dest=<dest>, help="<help message for this option>"}
--
-- with :
--   <opt> the option string to be used (can be anything, if one letter opt, then should be -x val, more letters: -xy=val )
--   <action> one of
--   - store: store in options as key, val
--   - store_true: stores key, true
--   - store_false: stores key, false
--   <dest> is the key under which the option is saved
--
-- options,args = op.parse_args()
--
-- now options is the table of options (key, val) and args is the table with non-option arguments.
-- You can use op.fail(message) for failing and op.help() for printing the usage as you like.
--
-- modifed by Benoit Corda, Clement Farabet
--

local OptionParser = {}

function xlua.OptionParser(usage)
   local self = {}
   self.usage = usage
   self.option_descriptions = {}
   self.option_of = {}
   for k,v in pairs(OptionParser) do
      self[k] = v
   end
   self:option{"-h", "--help", action="store_true", dest="help",
               help="show this help message and exit"}
   return self
end

function OptionParser:fail(s) -- extension
   io.stderr:write(s .. '\n')
   self:help()
   os.exit(1)
end

function OptionParser:option(optdesc)
   self.option_descriptions[#self.option_descriptions+1] = optdesc
   for _,v in ipairs(optdesc) do
      self.option_of[v] = optdesc
   end
end

function OptionParser:parse(options)
   local options = options or {}
   local args = {}

   -- set the default
   for _,v in ipairs(self.option_descriptions) do
      if v.default ~= nil and options[v.dest]==nil then
         options[v.dest] = v.default
      end
   end

   if not arg then
      options.__main__ = false -- python like main
      self.options = options
      return options, args
   end
   options.__main__ = true -- python like main

   -- expand options (e.g. "--input=file" -> "--input", "file")
   local unpack = unpack or table.unpack
   local arg = {unpack(arg)}
   for i=#arg,1,-1 do local v = arg[i]
      local flag, val = v:match('^(%-%-%w+)=(.*)')
      if flag then
         arg[i] = flag
         table.insert(arg, i+1, val)
      end
   end

   local i = 1
   while i <= #arg do
      local v = arg[i]
      local optdesc = self.option_of[v]
      if optdesc then
         local default = optdesc.default
         local action = optdesc.action
         local val = default
         if action == 'store' or action == nil then
            i = i + 1
            val = arg[i] or default
            if not val then self:fail('option requires an argument ' .. v) end
         elseif action == 'store_true' then
            val = true
         elseif action == 'store_false' then
            val = false
         end
         options[optdesc.dest] = val
      else
         if v:match('^%-') then self:fail('invalid option ' .. v) end
         args[#args+1] = v
      end
      i = i + 1
   end
   for k,opt in pairs(self.option_of) do
      if opt.req and not options[opt.dest] then
         self:fail('option '.. k .. ' requires an argument ')
      end
   end
   if options.help then
      self:help()
      os.exit()
   end
   -- set the default if nil
   self.options = options
   return options, args
end

function OptionParser:flags(optdesc)
   local sflags = {}
   local action = optdesc and optdesc.action
   for _,flag in ipairs(optdesc) do
      local sflagend
      if action == nil or action == 'store' then
         local metavar = optdesc.metavar or optdesc.dest:upper()
         sflagend = #flag == 2 and ' ' .. metavar
            or  '=' .. metavar
      else
         sflagend = ''
      end
      sflags[#sflags+1] = flag .. sflagend
   end
   return table.concat(sflags, ', ')
end

function OptionParser:help()
   if arg[-1] then
      io.stdout:write("Usage: " .. self.usage:gsub('%%prog', (arg[-1] .. ' ' .. arg[0])) .. "\n")
   elseif arg[0] then
      io.stdout:write("Usage: " .. self.usage:gsub('%%prog', arg[0]) .. "\n")
   else
      io.stdout:write("Usage: " .. self.usage:gsub('%%prog', 'THISPROG') .. "\n")
   end
   io.stdout:write("\n")
   io.stdout:write("Options:\n")
   pad = 0
   for _,optdesc in ipairs(self.option_descriptions) do
      pad = math.max(pad, #self:flags(optdesc))
   end
   for _,optdesc in ipairs(self.option_descriptions) do
      local defstr = ''
      if optdesc.req then
         defstr = ' [REQUIRED]'
      elseif optdesc.default then
         defstr = ' [default = ' .. tostring(optdesc.default) .. ']'
      end
      io.stdout:write("  " .. self:flags(optdesc) ..
                   string.rep(' ', pad - #self:flags(optdesc)) ..
                "  " .. optdesc.help .. defstr .. "\n")
   end
end

function OptionParser:tostring(generatefilename, params)
   local str = ''
   if not generatefilename then
      str = '<'.. ((arg and arg[0]) or 'interpreted.lua'):gsub('.lua','') .. "> configuration:\n"
      for k,v in pairs(self.options) do
         str = str .. ' + ' .. k .. ' = ' .. tostring(v) .. '\n'
      end
   else
      local first = true
      for i,entry in ipairs(self.option_descriptions) do
         local key = entry[1]
         local match = true
         if #params > 0 then
            match = false
            for i,param in ipairs(params) do
               if key == param then match = true; break end
            end
         end
         local val = self.options[entry.dest]
         if val and match then
            if first then
               str = str .. key .. '=' .. tostring(val)
            else
               str = str .. ',' .. key .. '=' .. tostring(val)
            end
            first = false
         end
      end
      str = str:gsub('/','|'):gsub(' ','_')
   end
   return str
end

function OptionParser:summarize(compact)
   io.write(self:tostring(compact))
end