local CmdLine = torch.class('torch.CmdLine') local function strip(str) return string.match(str, '%-*(.*)') end local function pad(str, sz) return str .. string.rep(' ', sz-#str) end function CmdLine:error(msg) print('') io.stderr:write(msg) print('') self:help() os.exit(1) end function CmdLine:__readArgument__(params, arg, i, nArgument) local argument = self.arguments[nArgument] local value = arg[i] if nArgument > #self.arguments then self:error('invalid argument: ' .. value) end if argument.type and type(value) ~= argument.type then self:error('invalid argument type for argument ' .. argument.key .. ' (should be ' .. argument.type .. ')') end params[strip(argument.key)] = value return 1 end function CmdLine:__readOption__(params, arg, i) local key = arg[i] local option = self.options[key] if not option then self:error('unknown option ' .. key) end if option.type and option.type == 'boolean' then params[strip(key)] = not option.default return 1 else local value = arg[i+1] if not value then self:error('missing argument for option ' .. key) end if not option.type or option.type == 'string' then elseif option.type == 'number' then value = tonumber(value) else self:error('unknown required option type ' .. option.type) end if not value then self:error('invalid type for option ' .. key .. ' (should be ' .. option.type .. ')') end params[strip(key)] = value return 2 end end function CmdLine:__init(argseparator_,keyseparator_) self.argseparator = argseparator_ or ',' self.keyseparator = keyseparator_ or '=' self.options = {} self.arguments = {} self.helplines = {} self.dateformat = nil self.silentio = false end function CmdLine:silent() self.silentio = true end function CmdLine:addTime(name, format) format = format or '%Y-%m-%d %H:%M:%S' if type(format) ~= 'string' then error('Argument has to be string') end if name ~= nil then name = '[' .. name .. ']: ' else name = '' end self.dateformat = format .. name end function CmdLine:argument(key, help, _type_) table.insert(self.arguments, {key=key, help=help, type=_type_}) table.insert(self.helplines, self.arguments[#self.arguments]) end function CmdLine:option(key, default, help, _type_) if default == nil then error('option ' .. key .. ' has no default value') end _type_ = _type_ or type(default) if type(default) ~= _type_ then error('option ' .. key .. ' has wrong default type value') end self.options[key] = {key=key, default=default, help=help, type=_type_} table.insert(self.helplines, self.options[key]) end function CmdLine:default() local params = {} for option,v in pairs(self.options) do params[strip(option)] = v.default end return params end function CmdLine:parse(arg) local i = 1 local params = self:default() local nArgument = 0 while i <= #arg do if arg[i] == '-help' or arg[i] == '-h' or arg[i] == '--help' then self:help(arg) os.exit(0) end if self.options[arg[i]] then i = i + self:__readOption__(params, arg, i) else nArgument = nArgument + 1 i = i + self:__readArgument__(params, arg, i, nArgument) end end if nArgument ~= #self.arguments then self:error('not enough arguments') end return params end function CmdLine:string(prefix, params, ignore) local arguments = {} local options = {} prefix = prefix or '' for k,v in pairs(params) do if ignore[k] then print('-- ignore option ' .. k) elseif self.options['-' .. k] then if v ~= self.options['-' .. k].default or ignore[k] == false then if type(v) == 'boolean' then if v then v = 't' else v = 'f' end end table.insert(options, k .. self.keyseparator .. v) print(k,v,self.options['-' .. k].default) end else local narg for i=1,#self.arguments do if strip(self.arguments[i].key) == k then narg = i end end if narg then arguments[narg] = k .. self.keyseparator .. v else print('WARNING: unknown option/argument: ' .. k .. ' IGNORING for DIRECTORY NAME') end end end table.sort(options) local str = table.concat(arguments, self.argseparator) if str == '' then str = table.concat(options, self.argseparator) else str = str .. self.argseparator .. table.concat(options, self.argseparator) end if str == '' then return prefix else return prefix .. self.argseparator .. str end end local oprint = nil function CmdLine:log(file, params) local f = (io.type(file) == 'file' and file) or io.open(file, 'w') oprint = oprint or print -- get the current print function lazily function print(...) local n = select("#", ...) local arg = {...} if not self.silentio then oprint(...) end local str = {} if self.dateformat then table.insert(str, os.date(self.dateformat)) end for i=1,n do table.insert(str,tostring(arg[i])) end table.insert(str,'\n') f:write(table.concat(str,' ')) f:flush() end print('[program started on ' .. os.date() .. ']') print('[command line arguments]') if params then for k,v in pairs(params) do print(k,v) end end print('[----------------------]') end function CmdLine:text(txt) txt = txt or '' assert(type(txt) == 'string') table.insert(self.helplines, txt) end function CmdLine:help(arg) io.write('Usage: ') if arg then io.write(arg[0] .. ' ') end io.write('[options]') for i=1,#self.arguments do io.write(' <' .. strip(self.arguments[i].key) .. '>') end io.write('\n') -- first pass to compute max length local optsz = 0 for _,option in ipairs(self.helplines) do if type(option) == 'table' then if option.default ~= nil then -- it is an option if #option.key > optsz then optsz = #option.key end else -- it is an argument if #strip(option.key)+2 > optsz then optsz = #strip(option.key)+2 end end end end -- second pass to print for _,option in ipairs(self.helplines) do if type(option) == 'table' then io.write(' ') if option.default ~= nil then -- it is an option io.write(pad(option.key, optsz)) if option.help then io.write(' ' .. option.help) end io.write(' [' .. tostring(option.default) .. ']') else -- it is an argument io.write(pad('<' .. strip(option.key) .. '>', optsz)) if option.help then io.write(' ' .. option.help) end end else io.write(option) -- just some additional help end io.write('\n') end end