optparse.lua 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. --[[
  2. Lua-based partial reimplementation of Python's
  3. optparse [2-3] command-line parsing module.
  4. SYNOPSIS
  5. local OptionParser = require "pythonic.optparse" . OptionParser
  6. local opt = OptionParser{usage="%prog [options] [gzip-file...]",
  7. version="foo 1.23", add_help_option=false}
  8. opt.add_option{"-h", "--help", action="store_true", dest="help",
  9. help="give this help"}
  10. opt.add_option{
  11. "-f", "--force", dest="force", action="store_true",
  12. help="force overwrite of output file"}
  13. local options, args = opt.parse_args()
  14. if options.help then opt.print_help(); os.exit(1) end
  15. if options.force then print 'f' end
  16. for _, name in ipairs(args) do print(name) end
  17. DESCRIPTION
  18. This library provides a command-line parsing[1] similar to Python optparse [2-3].
  19. Note: Python also supports getopt [4].
  20. STATUS
  21. This module is fairly basic but could be expanded.
  22. API
  23. See source code and also compare to Python's docs [2,3] for details because
  24. the following documentation is incomplete.
  25. opt = OptionParser {usage=usage, version=version, add_help_option=add_help_option}
  26. Create command line parser.
  27. opt.add_options{shortflag, longflag, action=action, metavar=metavar, dest=dest, help=help}
  28. Add command line option specification. This may be called multiple times.
  29. opt.parse_args() --> options, args
  30. Perform argument parsing.
  31. DEPENDENCIES
  32. None (other than Lua 5.1 or 5.2)
  33. REFERENCES
  34. [1] http://lua-users.org/wiki/CommandLineParsing
  35. [2] http://docs.python.org/lib/optparse-defining-options.html
  36. [3] http://blog.doughellmann.com/2007/08/pymotw-optparse.html
  37. [4] http://docs.python.org/lib/module-getopt.html
  38. LICENSE
  39. (c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT).
  40. Permission is hereby granted, free of charge, to any person obtaining a copy
  41. of this software and associated documentation files (the "Software"), to deal
  42. in the Software without restriction, including without limitation the rights
  43. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  44. copies of the Software, and to permit persons to whom the Software is
  45. furnished to do so, subject to the following conditions:
  46. The above copyright notice and this permission notice shall be included in
  47. all copies or substantial portions of the Software.
  48. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  49. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  50. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  51. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  52. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  53. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  54. THE SOFTWARE.
  55. (end license)
  56. --]]
  57. return function(t)
  58. local usage = t.usage
  59. --local version = t.version
  60. local o = {}
  61. local option_descriptions = {}
  62. local option_of = {}
  63. function o.add_option(optdesc)
  64. option_descriptions[#option_descriptions+1] = optdesc
  65. for _,v in ipairs(optdesc) do
  66. option_of[v] = optdesc
  67. end
  68. end
  69. local function split(inputstr, seperator)
  70. if seperator == nil then
  71. seperator = "%s"
  72. end
  73. local out={}
  74. local i=1
  75. for substring in string.gmatch(inputstr, "([^"..seperator.."]+)") do
  76. out[i] = substring
  77. i = i + 1
  78. end
  79. return out
  80. end
  81. function o.parse_args(arg)
  82. -- expand options (e.g. "--input=file" -> "--input", "file")
  83. local arg = split(arg)
  84. for i=#arg,1,-1 do local v = arg[i]
  85. local flag, val = v:match('^(%-%-%w+)=(.*)')
  86. if flag then
  87. arg[i] = flag
  88. table.insert(arg, i+1, val)
  89. end
  90. end
  91. local options = {}
  92. local args = {}
  93. local i = 1
  94. while i <= #arg do local v = arg[i]
  95. local optdesc = option_of[v]
  96. if optdesc then
  97. local action = optdesc.action
  98. local val
  99. if action == 'store' or action == nil then
  100. i = i + 1
  101. val = arg[i]
  102. if not val then return false, 'option requires an argument ' .. v end
  103. elseif action == 'store_true' then
  104. val = true
  105. elseif action == 'store_false' then
  106. val = false
  107. end
  108. options[optdesc.dest] = val
  109. else
  110. if v:match('^%-') then return false, 'invalid option ' .. v end
  111. args[#args+1] = v
  112. end
  113. i = i + 1
  114. end
  115. if options.help then
  116. return false, o.print_help()
  117. end
  118. return true, options, args
  119. end
  120. local function flags_str(optdesc)
  121. local sflags = {}
  122. local action = optdesc.action
  123. for _,flag in ipairs(optdesc) do
  124. local sflagend
  125. if action == nil or action == 'store' then
  126. local metavar = optdesc.metavar or optdesc.dest:upper()
  127. sflagend = #flag == 2 and ' ' .. metavar or '=' .. metavar
  128. else
  129. sflagend = ''
  130. end
  131. sflags[#sflags+1] = flag .. sflagend
  132. end
  133. return table.concat(sflags, ', ')
  134. end
  135. function o.print_help()
  136. local helpout = "Usage: " .. usage .. "\n\n" .. "Options:\n"
  137. local maxwidth = 0
  138. for _,optdesc in ipairs(option_descriptions) do
  139. maxwidth = math.max(maxwidth, #flags_str(optdesc))
  140. end
  141. for _,optdesc in ipairs(option_descriptions) do
  142. helpout = helpout .. " " .. ('%-'..maxwidth..'s '):format(flags_str(optdesc)) .. optdesc.help .. "\n"
  143. end
  144. return helpout
  145. end
  146. -- if t.add_help_option == nil or t.add_help_option == true then
  147. -- o.add_option{"--help", action="store_true", dest="help", help="show this help message and exit"}
  148. -- end
  149. return o
  150. end