Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

argparse.lua 39KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527
  1. -- The MIT License (MIT)
  2. -- Copyright (c) 2013 - 2018 Peter Melnichenko
  3. -- Permission is hereby granted, free of charge, to any person obtaining a copy of
  4. -- this software and associated documentation files (the "Software"), to deal in
  5. -- the Software without restriction, including without limitation the rights to
  6. -- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  7. -- the Software, and to permit persons to whom the Software is furnished to do so,
  8. -- subject to the following conditions:
  9. -- The above copyright notice and this permission notice shall be included in all
  10. -- copies or substantial portions of the Software.
  11. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  13. -- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  14. -- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  15. -- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  16. -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  17. local function deep_update(t1, t2)
  18. for k, v in pairs(t2) do
  19. if type(v) == "table" then
  20. v = deep_update({}, v)
  21. end
  22. t1[k] = v
  23. end
  24. return t1
  25. end
  26. -- A property is a tuple {name, callback}.
  27. -- properties.args is number of properties that can be set as arguments
  28. -- when calling an object.
  29. local function class(prototype, properties, parent)
  30. -- Class is the metatable of its instances.
  31. local cl = {}
  32. cl.__index = cl
  33. if parent then
  34. cl.__prototype = deep_update(deep_update({}, parent.__prototype), prototype)
  35. else
  36. cl.__prototype = prototype
  37. end
  38. if properties then
  39. local names = {}
  40. -- Create setter methods and fill set of property names.
  41. for _, property in ipairs(properties) do
  42. local name, callback = property[1], property[2]
  43. cl[name] = function(self, value)
  44. if not callback(self, value) then
  45. self["_" .. name] = value
  46. end
  47. return self
  48. end
  49. names[name] = true
  50. end
  51. function cl.__call(self, ...)
  52. -- When calling an object, if the first argument is a table,
  53. -- interpret keys as property names, else delegate arguments
  54. -- to corresponding setters in order.
  55. if type((...)) == "table" then
  56. for name, value in pairs((...)) do
  57. if names[name] then
  58. self[name](self, value)
  59. end
  60. end
  61. else
  62. local nargs = select("#", ...)
  63. for i, property in ipairs(properties) do
  64. if i > nargs or i > properties.args then
  65. break
  66. end
  67. local arg = select(i, ...)
  68. if arg ~= nil then
  69. self[property[1]](self, arg)
  70. end
  71. end
  72. end
  73. return self
  74. end
  75. end
  76. -- If indexing class fails, fallback to its parent.
  77. local class_metatable = {}
  78. class_metatable.__index = parent
  79. function class_metatable.__call(self, ...)
  80. -- Calling a class returns its instance.
  81. -- Arguments are delegated to the instance.
  82. local object = deep_update({}, self.__prototype)
  83. setmetatable(object, self)
  84. return object(...)
  85. end
  86. return setmetatable(cl, class_metatable)
  87. end
  88. local function typecheck(name, types, value)
  89. for _, type_ in ipairs(types) do
  90. if type(value) == type_ then
  91. return true
  92. end
  93. end
  94. error(("bad property '%s' (%s expected, got %s)"):format(name, table.concat(types, " or "), type(value)))
  95. end
  96. local function typechecked(name, ...)
  97. local types = {...}
  98. return {name, function(_, value) typecheck(name, types, value) end}
  99. end
  100. local multiname = {"name", function(self, value)
  101. typecheck("name", {"string"}, value)
  102. for alias in value:gmatch("%S+") do
  103. self._name = self._name or alias
  104. table.insert(self._aliases, alias)
  105. end
  106. -- Do not set _name as with other properties.
  107. return true
  108. end}
  109. local function parse_boundaries(str)
  110. if tonumber(str) then
  111. return tonumber(str), tonumber(str)
  112. end
  113. if str == "*" then
  114. return 0, math.huge
  115. end
  116. if str == "+" then
  117. return 1, math.huge
  118. end
  119. if str == "?" then
  120. return 0, 1
  121. end
  122. if str:match "^%d+%-%d+$" then
  123. local min, max = str:match "^(%d+)%-(%d+)$"
  124. return tonumber(min), tonumber(max)
  125. end
  126. if str:match "^%d+%+$" then
  127. local min = str:match "^(%d+)%+$"
  128. return tonumber(min), math.huge
  129. end
  130. end
  131. local function boundaries(name)
  132. return {name, function(self, value)
  133. typecheck(name, {"number", "string"}, value)
  134. local min, max = parse_boundaries(value)
  135. if not min then
  136. error(("bad property '%s'"):format(name))
  137. end
  138. self["_min" .. name], self["_max" .. name] = min, max
  139. end}
  140. end
  141. local actions = {}
  142. local option_action = {"action", function(_, value)
  143. typecheck("action", {"function", "string"}, value)
  144. if type(value) == "string" and not actions[value] then
  145. error(("unknown action '%s'"):format(value))
  146. end
  147. end}
  148. local option_init = {"init", function(self)
  149. self._has_init = true
  150. end}
  151. local option_default = {"default", function(self, value)
  152. if type(value) ~= "string" then
  153. self._init = value
  154. self._has_init = true
  155. return true
  156. end
  157. end}
  158. local add_help = {"add_help", function(self, value)
  159. typecheck("add_help", {"boolean", "string", "table"}, value)
  160. if self._has_help then
  161. table.remove(self._options)
  162. self._has_help = false
  163. end
  164. if value then
  165. local help = self:flag()
  166. :description "Show this help message and exit."
  167. :action(function()
  168. print(self:get_help())
  169. os.exit(0)
  170. end)
  171. if value ~= true then
  172. help = help(value)
  173. end
  174. if not help._name then
  175. help "-h" "--help"
  176. end
  177. self._has_help = true
  178. end
  179. end}
  180. local Parser = class({
  181. _arguments = {},
  182. _options = {},
  183. _commands = {},
  184. _mutexes = {},
  185. _groups = {},
  186. _require_command = true,
  187. _handle_options = true
  188. }, {
  189. args = 3,
  190. typechecked("name", "string"),
  191. typechecked("description", "string"),
  192. typechecked("epilog", "string"),
  193. typechecked("usage", "string"),
  194. typechecked("help", "string"),
  195. typechecked("require_command", "boolean"),
  196. typechecked("handle_options", "boolean"),
  197. typechecked("action", "function"),
  198. typechecked("command_target", "string"),
  199. typechecked("help_vertical_space", "number"),
  200. typechecked("usage_margin", "number"),
  201. typechecked("usage_max_width", "number"),
  202. typechecked("help_usage_margin", "number"),
  203. typechecked("help_description_margin", "number"),
  204. typechecked("help_max_width", "number"),
  205. add_help
  206. })
  207. local Command = class({
  208. _aliases = {}
  209. }, {
  210. args = 3,
  211. multiname,
  212. typechecked("description", "string"),
  213. typechecked("epilog", "string"),
  214. typechecked("target", "string"),
  215. typechecked("usage", "string"),
  216. typechecked("help", "string"),
  217. typechecked("require_command", "boolean"),
  218. typechecked("handle_options", "boolean"),
  219. typechecked("action", "function"),
  220. typechecked("command_target", "string"),
  221. typechecked("help_vertical_space", "number"),
  222. typechecked("usage_margin", "number"),
  223. typechecked("usage_max_width", "number"),
  224. typechecked("help_usage_margin", "number"),
  225. typechecked("help_description_margin", "number"),
  226. typechecked("help_max_width", "number"),
  227. typechecked("hidden", "boolean"),
  228. add_help
  229. }, Parser)
  230. local Argument = class({
  231. _minargs = 1,
  232. _maxargs = 1,
  233. _mincount = 1,
  234. _maxcount = 1,
  235. _defmode = "unused",
  236. _show_default = true
  237. }, {
  238. args = 5,
  239. typechecked("name", "string"),
  240. typechecked("description", "string"),
  241. option_default,
  242. typechecked("convert", "function", "table"),
  243. boundaries("args"),
  244. typechecked("target", "string"),
  245. typechecked("defmode", "string"),
  246. typechecked("show_default", "boolean"),
  247. typechecked("argname", "string", "table"),
  248. typechecked("hidden", "boolean"),
  249. option_action,
  250. option_init
  251. })
  252. local Option = class({
  253. _aliases = {},
  254. _mincount = 0,
  255. _overwrite = true
  256. }, {
  257. args = 6,
  258. multiname,
  259. typechecked("description", "string"),
  260. option_default,
  261. typechecked("convert", "function", "table"),
  262. boundaries("args"),
  263. boundaries("count"),
  264. typechecked("target", "string"),
  265. typechecked("defmode", "string"),
  266. typechecked("show_default", "boolean"),
  267. typechecked("overwrite", "boolean"),
  268. typechecked("argname", "string", "table"),
  269. typechecked("hidden", "boolean"),
  270. option_action,
  271. option_init
  272. }, Argument)
  273. function Parser:_inherit_property(name, default)
  274. local element = self
  275. while true do
  276. local value = element["_" .. name]
  277. if value ~= nil then
  278. return value
  279. end
  280. if not element._parent then
  281. return default
  282. end
  283. element = element._parent
  284. end
  285. end
  286. function Argument:_get_argument_list()
  287. local buf = {}
  288. local i = 1
  289. while i <= math.min(self._minargs, 3) do
  290. local argname = self:_get_argname(i)
  291. if self._default and self._defmode:find "a" then
  292. argname = "[" .. argname .. "]"
  293. end
  294. table.insert(buf, argname)
  295. i = i+1
  296. end
  297. while i <= math.min(self._maxargs, 3) do
  298. table.insert(buf, "[" .. self:_get_argname(i) .. "]")
  299. i = i+1
  300. if self._maxargs == math.huge then
  301. break
  302. end
  303. end
  304. if i < self._maxargs then
  305. table.insert(buf, "...")
  306. end
  307. return buf
  308. end
  309. function Argument:_get_usage()
  310. local usage = table.concat(self:_get_argument_list(), " ")
  311. if self._default and self._defmode:find "u" then
  312. if self._maxargs > 1 or (self._minargs == 1 and not self._defmode:find "a") then
  313. usage = "[" .. usage .. "]"
  314. end
  315. end
  316. return usage
  317. end
  318. function actions.store_true(result, target)
  319. result[target] = true
  320. end
  321. function actions.store_false(result, target)
  322. result[target] = false
  323. end
  324. function actions.store(result, target, argument)
  325. result[target] = argument
  326. end
  327. function actions.count(result, target, _, overwrite)
  328. if not overwrite then
  329. result[target] = result[target] + 1
  330. end
  331. end
  332. function actions.append(result, target, argument, overwrite)
  333. result[target] = result[target] or {}
  334. table.insert(result[target], argument)
  335. if overwrite then
  336. table.remove(result[target], 1)
  337. end
  338. end
  339. function actions.concat(result, target, arguments, overwrite)
  340. if overwrite then
  341. error("'concat' action can't handle too many invocations")
  342. end
  343. result[target] = result[target] or {}
  344. for _, argument in ipairs(arguments) do
  345. table.insert(result[target], argument)
  346. end
  347. end
  348. function Argument:_get_action()
  349. local action, init
  350. if self._maxcount == 1 then
  351. if self._maxargs == 0 then
  352. action, init = "store_true", nil
  353. else
  354. action, init = "store", nil
  355. end
  356. else
  357. if self._maxargs == 0 then
  358. action, init = "count", 0
  359. else
  360. action, init = "append", {}
  361. end
  362. end
  363. if self._action then
  364. action = self._action
  365. end
  366. if self._has_init then
  367. init = self._init
  368. end
  369. if type(action) == "string" then
  370. action = actions[action]
  371. end
  372. return action, init
  373. end
  374. -- Returns placeholder for `narg`-th argument.
  375. function Argument:_get_argname(narg)
  376. local argname = self._argname or self:_get_default_argname()
  377. if type(argname) == "table" then
  378. return argname[narg]
  379. else
  380. return argname
  381. end
  382. end
  383. function Argument:_get_default_argname()
  384. return "<" .. self._name .. ">"
  385. end
  386. function Option:_get_default_argname()
  387. return "<" .. self:_get_default_target() .. ">"
  388. end
  389. -- Returns labels to be shown in the help message.
  390. function Argument:_get_label_lines()
  391. return {self._name}
  392. end
  393. function Option:_get_label_lines()
  394. local argument_list = self:_get_argument_list()
  395. if #argument_list == 0 then
  396. -- Don't put aliases for simple flags like `-h` on different lines.
  397. return {table.concat(self._aliases, ", ")}
  398. end
  399. local longest_alias_length = -1
  400. for _, alias in ipairs(self._aliases) do
  401. longest_alias_length = math.max(longest_alias_length, #alias)
  402. end
  403. local argument_list_repr = table.concat(argument_list, " ")
  404. local lines = {}
  405. for i, alias in ipairs(self._aliases) do
  406. local line = (" "):rep(longest_alias_length - #alias) .. alias .. " " .. argument_list_repr
  407. if i ~= #self._aliases then
  408. line = line .. ","
  409. end
  410. table.insert(lines, line)
  411. end
  412. return lines
  413. end
  414. function Command:_get_label_lines()
  415. return {table.concat(self._aliases, ", ")}
  416. end
  417. function Argument:_get_description()
  418. if self._default and self._show_default then
  419. if self._description then
  420. return ("%s (default: %s)"):format(self._description, self._default)
  421. else
  422. return ("default: %s"):format(self._default)
  423. end
  424. else
  425. return self._description or ""
  426. end
  427. end
  428. function Command:_get_description()
  429. return self._description or ""
  430. end
  431. function Option:_get_usage()
  432. local usage = self:_get_argument_list()
  433. table.insert(usage, 1, self._name)
  434. usage = table.concat(usage, " ")
  435. if self._mincount == 0 or self._default then
  436. usage = "[" .. usage .. "]"
  437. end
  438. return usage
  439. end
  440. function Argument:_get_default_target()
  441. return self._name
  442. end
  443. function Option:_get_default_target()
  444. local res
  445. for _, alias in ipairs(self._aliases) do
  446. if alias:sub(1, 1) == alias:sub(2, 2) then
  447. res = alias:sub(3)
  448. break
  449. end
  450. end
  451. res = res or self._name:sub(2)
  452. return (res:gsub("-", "_"))
  453. end
  454. function Option:_is_vararg()
  455. return self._maxargs ~= self._minargs
  456. end
  457. function Parser:_get_fullname()
  458. local parent = self._parent
  459. local buf = {self._name}
  460. while parent do
  461. table.insert(buf, 1, parent._name)
  462. parent = parent._parent
  463. end
  464. return table.concat(buf, " ")
  465. end
  466. function Parser:_update_charset(charset)
  467. charset = charset or {}
  468. for _, command in ipairs(self._commands) do
  469. command:_update_charset(charset)
  470. end
  471. for _, option in ipairs(self._options) do
  472. for _, alias in ipairs(option._aliases) do
  473. charset[alias:sub(1, 1)] = true
  474. end
  475. end
  476. return charset
  477. end
  478. function Parser:argument(...)
  479. local argument = Argument(...)
  480. table.insert(self._arguments, argument)
  481. return argument
  482. end
  483. function Parser:option(...)
  484. local option = Option(...)
  485. if self._has_help then
  486. table.insert(self._options, #self._options, option)
  487. else
  488. table.insert(self._options, option)
  489. end
  490. return option
  491. end
  492. function Parser:flag(...)
  493. return self:option():args(0)(...)
  494. end
  495. function Parser:command(...)
  496. local command = Command():add_help(true)(...)
  497. command._parent = self
  498. table.insert(self._commands, command)
  499. return command
  500. end
  501. function Parser:mutex(...)
  502. local elements = {...}
  503. for i, element in ipairs(elements) do
  504. local mt = getmetatable(element)
  505. assert(mt == Option or mt == Argument, ("bad argument #%d to 'mutex' (Option or Argument expected)"):format(i))
  506. end
  507. table.insert(self._mutexes, elements)
  508. return self
  509. end
  510. function Parser:group(name, ...)
  511. assert(type(name) == "string", ("bad argument #1 to 'group' (string expected, got %s)"):format(type(name)))
  512. local group = {name = name, ...}
  513. for i, element in ipairs(group) do
  514. local mt = getmetatable(element)
  515. assert(mt == Option or mt == Argument or mt == Command,
  516. ("bad argument #%d to 'group' (Option or Argument or Command expected)"):format(i + 1))
  517. end
  518. table.insert(self._groups, group)
  519. return self
  520. end
  521. local usage_welcome = "Usage: "
  522. function Parser:get_usage()
  523. if self._usage then
  524. return self._usage
  525. end
  526. local usage_margin = self:_inherit_property("usage_margin", #usage_welcome)
  527. local max_usage_width = self:_inherit_property("usage_max_width", 70)
  528. local lines = {usage_welcome .. self:_get_fullname()}
  529. local function add(s)
  530. if #lines[#lines]+1+#s <= max_usage_width then
  531. lines[#lines] = lines[#lines] .. " " .. s
  532. else
  533. lines[#lines+1] = (" "):rep(usage_margin) .. s
  534. end
  535. end
  536. -- Normally options are before positional arguments in usage messages.
  537. -- However, vararg options should be after, because they can't be reliable used
  538. -- before a positional argument.
  539. -- Mutexes come into play, too, and are shown as soon as possible.
  540. -- Overall, output usages in the following order:
  541. -- 1. Mutexes that don't have positional arguments or vararg options.
  542. -- 2. Options that are not in any mutexes and are not vararg.
  543. -- 3. Positional arguments - on their own or as a part of a mutex.
  544. -- 4. Remaining mutexes.
  545. -- 5. Remaining options.
  546. local elements_in_mutexes = {}
  547. local added_elements = {}
  548. local added_mutexes = {}
  549. local argument_to_mutexes = {}
  550. local function add_mutex(mutex, main_argument)
  551. if added_mutexes[mutex] then
  552. return
  553. end
  554. added_mutexes[mutex] = true
  555. local buf = {}
  556. for _, element in ipairs(mutex) do
  557. if not element._hidden and not added_elements[element] then
  558. if getmetatable(element) == Option or element == main_argument then
  559. table.insert(buf, element:_get_usage())
  560. added_elements[element] = true
  561. end
  562. end
  563. end
  564. if #buf == 1 then
  565. add(buf[1])
  566. elseif #buf > 1 then
  567. add("(" .. table.concat(buf, " | ") .. ")")
  568. end
  569. end
  570. local function add_element(element)
  571. if not element._hidden and not added_elements[element] then
  572. add(element:_get_usage())
  573. added_elements[element] = true
  574. end
  575. end
  576. for _, mutex in ipairs(self._mutexes) do
  577. local is_vararg = false
  578. local has_argument = false
  579. for _, element in ipairs(mutex) do
  580. if getmetatable(element) == Option then
  581. if element:_is_vararg() then
  582. is_vararg = true
  583. end
  584. else
  585. has_argument = true
  586. argument_to_mutexes[element] = argument_to_mutexes[element] or {}
  587. table.insert(argument_to_mutexes[element], mutex)
  588. end
  589. elements_in_mutexes[element] = true
  590. end
  591. if not is_vararg and not has_argument then
  592. add_mutex(mutex)
  593. end
  594. end
  595. for _, option in ipairs(self._options) do
  596. if not elements_in_mutexes[option] and not option:_is_vararg() then
  597. add_element(option)
  598. end
  599. end
  600. -- Add usages for positional arguments, together with one mutex containing them, if they are in a mutex.
  601. for _, argument in ipairs(self._arguments) do
  602. -- Pick a mutex as a part of which to show this argument, take the first one that's still available.
  603. local mutex
  604. if elements_in_mutexes[argument] then
  605. for _, argument_mutex in ipairs(argument_to_mutexes[argument]) do
  606. if not added_mutexes[argument_mutex] then
  607. mutex = argument_mutex
  608. end
  609. end
  610. end
  611. if mutex then
  612. add_mutex(mutex, argument)
  613. else
  614. add_element(argument)
  615. end
  616. end
  617. for _, mutex in ipairs(self._mutexes) do
  618. add_mutex(mutex)
  619. end
  620. for _, option in ipairs(self._options) do
  621. add_element(option)
  622. end
  623. if #self._commands > 0 then
  624. if self._require_command then
  625. add("<command>")
  626. else
  627. add("[<command>]")
  628. end
  629. add("...")
  630. end
  631. return table.concat(lines, "\n")
  632. end
  633. local function split_lines(s)
  634. if s == "" then
  635. return {}
  636. end
  637. local lines = {}
  638. if s:sub(-1) ~= "\n" then
  639. s = s .. "\n"
  640. end
  641. for line in s:gmatch("([^\n]*)\n") do
  642. table.insert(lines, line)
  643. end
  644. return lines
  645. end
  646. local function autowrap_line(line, max_length)
  647. -- Algorithm for splitting lines is simple and greedy.
  648. local result_lines = {}
  649. -- Preserve original indentation of the line, put this at the beginning of each result line.
  650. -- If the first word looks like a list marker ('*', '+', or '-'), add spaces so that starts
  651. -- of the second and the following lines vertically align with the start of the second word.
  652. local indentation = line:match("^ *")
  653. if line:find("^ *[%*%+%-]") then
  654. indentation = indentation .. " " .. line:match("^ *[%*%+%-]( *)")
  655. end
  656. -- Parts of the last line being assembled.
  657. local line_parts = {}
  658. -- Length of the current line.
  659. local line_length = 0
  660. -- Index of the next character to consider.
  661. local index = 1
  662. while true do
  663. local word_start, word_finish, word = line:find("([^ ]+)", index)
  664. if not word_start then
  665. -- Ignore trailing spaces, if any.
  666. break
  667. end
  668. local preceding_spaces = line:sub(index, word_start - 1)
  669. index = word_finish + 1
  670. if (#line_parts == 0) or (line_length + #preceding_spaces + #word <= max_length) then
  671. -- Either this is the very first word or it fits as an addition to the current line, add it.
  672. table.insert(line_parts, preceding_spaces) -- For the very first word this adds the indentation.
  673. table.insert(line_parts, word)
  674. line_length = line_length + #preceding_spaces + #word
  675. else
  676. -- Does not fit, finish current line and put the word into a new one.
  677. table.insert(result_lines, table.concat(line_parts))
  678. line_parts = {indentation, word}
  679. line_length = #indentation + #word
  680. end
  681. end
  682. if #line_parts > 0 then
  683. table.insert(result_lines, table.concat(line_parts))
  684. end
  685. if #result_lines == 0 then
  686. -- Preserve empty lines.
  687. result_lines[1] = ""
  688. end
  689. return result_lines
  690. end
  691. -- Automatically wraps lines within given array,
  692. -- attempting to limit line length to `max_length`.
  693. -- Existing line splits are preserved.
  694. local function autowrap(lines, max_length)
  695. local result_lines = {}
  696. for _, line in ipairs(lines) do
  697. local autowrapped_lines = autowrap_line(line, max_length)
  698. for _, autowrapped_line in ipairs(autowrapped_lines) do
  699. table.insert(result_lines, autowrapped_line)
  700. end
  701. end
  702. return result_lines
  703. end
  704. function Parser:_get_element_help(element)
  705. local label_lines = element:_get_label_lines()
  706. local description_lines = split_lines(element:_get_description())
  707. local result_lines = {}
  708. -- All label lines should have the same length (except the last one, it has no comma).
  709. -- If too long, start description after all the label lines.
  710. -- Otherwise, combine label and description lines.
  711. local usage_margin_len = self:_inherit_property("help_usage_margin", 3)
  712. local usage_margin = (" "):rep(usage_margin_len)
  713. local description_margin_len = self:_inherit_property("help_description_margin", 25)
  714. local description_margin = (" "):rep(description_margin_len)
  715. local help_max_width = self:_inherit_property("help_max_width")
  716. if help_max_width then
  717. local description_max_width = math.max(help_max_width - description_margin_len, 10)
  718. description_lines = autowrap(description_lines, description_max_width)
  719. end
  720. if #label_lines[1] >= (description_margin_len - usage_margin_len) then
  721. for _, label_line in ipairs(label_lines) do
  722. table.insert(result_lines, usage_margin .. label_line)
  723. end
  724. for _, description_line in ipairs(description_lines) do
  725. table.insert(result_lines, description_margin .. description_line)
  726. end
  727. else
  728. for i = 1, math.max(#label_lines, #description_lines) do
  729. local label_line = label_lines[i]
  730. local description_line = description_lines[i]
  731. local line = ""
  732. if label_line then
  733. line = usage_margin .. label_line
  734. end
  735. if description_line and description_line ~= "" then
  736. line = line .. (" "):rep(description_margin_len - #line) .. description_line
  737. end
  738. table.insert(result_lines, line)
  739. end
  740. end
  741. return table.concat(result_lines, "\n")
  742. end
  743. local function get_group_types(group)
  744. local types = {}
  745. for _, element in ipairs(group) do
  746. types[getmetatable(element)] = true
  747. end
  748. return types
  749. end
  750. function Parser:_add_group_help(blocks, added_elements, label, elements)
  751. local buf = {label}
  752. for _, element in ipairs(elements) do
  753. if not element._hidden and not added_elements[element] then
  754. added_elements[element] = true
  755. table.insert(buf, self:_get_element_help(element))
  756. end
  757. end
  758. if #buf > 1 then
  759. table.insert(blocks, table.concat(buf, ("\n"):rep(self:_inherit_property("help_vertical_space", 0) + 1)))
  760. end
  761. end
  762. function Parser:get_help()
  763. if self._help then
  764. return self._help
  765. end
  766. local blocks = {self:get_usage()}
  767. local help_max_width = self:_inherit_property("help_max_width")
  768. if self._description then
  769. local description = self._description
  770. if help_max_width then
  771. description = table.concat(autowrap(split_lines(description), help_max_width), "\n")
  772. end
  773. table.insert(blocks, description)
  774. end
  775. -- 1. Put groups containing arguments first, then other arguments.
  776. -- 2. Put remaining groups containing options, then other options.
  777. -- 3. Put remaining groups containing commands, then other commands.
  778. -- Assume that an element can't be in several groups.
  779. local groups_by_type = {
  780. [Argument] = {},
  781. [Option] = {},
  782. [Command] = {}
  783. }
  784. for _, group in ipairs(self._groups) do
  785. local group_types = get_group_types(group)
  786. for _, mt in ipairs({Argument, Option, Command}) do
  787. if group_types[mt] then
  788. table.insert(groups_by_type[mt], group)
  789. break
  790. end
  791. end
  792. end
  793. local default_groups = {
  794. {name = "Arguments", type = Argument, elements = self._arguments},
  795. {name = "Options", type = Option, elements = self._options},
  796. {name = "Commands", type = Command, elements = self._commands}
  797. }
  798. local added_elements = {}
  799. for _, default_group in ipairs(default_groups) do
  800. local type_groups = groups_by_type[default_group.type]
  801. for _, group in ipairs(type_groups) do
  802. self:_add_group_help(blocks, added_elements, group.name .. ":", group)
  803. end
  804. local default_label = default_group.name .. ":"
  805. if #type_groups > 0 then
  806. default_label = "Other " .. default_label:gsub("^.", string.lower)
  807. end
  808. self:_add_group_help(blocks, added_elements, default_label, default_group.elements)
  809. end
  810. if self._epilog then
  811. local epilog = self._epilog
  812. if help_max_width then
  813. epilog = table.concat(autowrap(split_lines(epilog), help_max_width), "\n")
  814. end
  815. table.insert(blocks, epilog)
  816. end
  817. return table.concat(blocks, "\n\n")
  818. end
  819. local function get_tip(context, wrong_name)
  820. local context_pool = {}
  821. local possible_name
  822. local possible_names = {}
  823. for name in pairs(context) do
  824. if type(name) == "string" then
  825. for i = 1, #name do
  826. possible_name = name:sub(1, i - 1) .. name:sub(i + 1)
  827. if not context_pool[possible_name] then
  828. context_pool[possible_name] = {}
  829. end
  830. table.insert(context_pool[possible_name], name)
  831. end
  832. end
  833. end
  834. for i = 1, #wrong_name + 1 do
  835. possible_name = wrong_name:sub(1, i - 1) .. wrong_name:sub(i + 1)
  836. if context[possible_name] then
  837. possible_names[possible_name] = true
  838. elseif context_pool[possible_name] then
  839. for _, name in ipairs(context_pool[possible_name]) do
  840. possible_names[name] = true
  841. end
  842. end
  843. end
  844. local first = next(possible_names)
  845. if first then
  846. if next(possible_names, first) then
  847. local possible_names_arr = {}
  848. for name in pairs(possible_names) do
  849. table.insert(possible_names_arr, "'" .. name .. "'")
  850. end
  851. table.sort(possible_names_arr)
  852. return "\nDid you mean one of these: " .. table.concat(possible_names_arr, " ") .. "?"
  853. else
  854. return "\nDid you mean '" .. first .. "'?"
  855. end
  856. else
  857. return ""
  858. end
  859. end
  860. local ElementState = class({
  861. invocations = 0
  862. })
  863. function ElementState:__call(state, element)
  864. self.state = state
  865. self.result = state.result
  866. self.element = element
  867. self.target = element._target or element:_get_default_target()
  868. self.action, self.result[self.target] = element:_get_action()
  869. return self
  870. end
  871. function ElementState:error(fmt, ...)
  872. self.state:error(fmt, ...)
  873. end
  874. function ElementState:convert(argument, index)
  875. local converter = self.element._convert
  876. if converter then
  877. local ok, err
  878. if type(converter) == "function" then
  879. ok, err = converter(argument)
  880. elseif type(converter[index]) == "function" then
  881. ok, err = converter[index](argument)
  882. else
  883. ok = converter[argument]
  884. end
  885. if ok == nil then
  886. self:error(err and "%s" or "malformed argument '%s'", err or argument)
  887. end
  888. argument = ok
  889. end
  890. return argument
  891. end
  892. function ElementState:default(mode)
  893. return self.element._defmode:find(mode) and self.element._default
  894. end
  895. local function bound(noun, min, max, is_max)
  896. local res = ""
  897. if min ~= max then
  898. res = "at " .. (is_max and "most" or "least") .. " "
  899. end
  900. local number = is_max and max or min
  901. return res .. tostring(number) .. " " .. noun .. (number == 1 and "" or "s")
  902. end
  903. function ElementState:set_name(alias)
  904. self.name = ("%s '%s'"):format(alias and "option" or "argument", alias or self.element._name)
  905. end
  906. function ElementState:invoke()
  907. self.open = true
  908. self.overwrite = false
  909. if self.invocations >= self.element._maxcount then
  910. if self.element._overwrite then
  911. self.overwrite = true
  912. else
  913. local num_times_repr = bound("time", self.element._mincount, self.element._maxcount, true)
  914. self:error("%s must be used %s", self.name, num_times_repr)
  915. end
  916. else
  917. self.invocations = self.invocations + 1
  918. end
  919. self.args = {}
  920. if self.element._maxargs <= 0 then
  921. self:close()
  922. end
  923. return self.open
  924. end
  925. function ElementState:pass(argument)
  926. argument = self:convert(argument, #self.args + 1)
  927. table.insert(self.args, argument)
  928. if #self.args >= self.element._maxargs then
  929. self:close()
  930. end
  931. return self.open
  932. end
  933. function ElementState:complete_invocation()
  934. while #self.args < self.element._minargs do
  935. self:pass(self.element._default)
  936. end
  937. end
  938. function ElementState:close()
  939. if self.open then
  940. self.open = false
  941. if #self.args < self.element._minargs then
  942. if self:default("a") then
  943. self:complete_invocation()
  944. else
  945. if #self.args == 0 then
  946. if getmetatable(self.element) == Argument then
  947. self:error("missing %s", self.name)
  948. elseif self.element._maxargs == 1 then
  949. self:error("%s requires an argument", self.name)
  950. end
  951. end
  952. self:error("%s requires %s", self.name, bound("argument", self.element._minargs, self.element._maxargs))
  953. end
  954. end
  955. local args
  956. if self.element._maxargs == 0 then
  957. args = self.args[1]
  958. elseif self.element._maxargs == 1 then
  959. if self.element._minargs == 0 and self.element._mincount ~= self.element._maxcount then
  960. args = self.args
  961. else
  962. args = self.args[1]
  963. end
  964. else
  965. args = self.args
  966. end
  967. self.action(self.result, self.target, args, self.overwrite)
  968. end
  969. end
  970. local ParseState = class({
  971. result = {},
  972. options = {},
  973. arguments = {},
  974. argument_i = 1,
  975. element_to_mutexes = {},
  976. mutex_to_element_state = {},
  977. command_actions = {}
  978. })
  979. function ParseState:__call(parser, error_handler)
  980. self.parser = parser
  981. self.error_handler = error_handler
  982. self.charset = parser:_update_charset()
  983. self:switch(parser)
  984. return self
  985. end
  986. function ParseState:error(fmt, ...)
  987. self.error_handler(self.parser, fmt:format(...))
  988. end
  989. function ParseState:switch(parser)
  990. self.parser = parser
  991. if parser._action then
  992. table.insert(self.command_actions, {action = parser._action, name = parser._name})
  993. end
  994. for _, option in ipairs(parser._options) do
  995. option = ElementState(self, option)
  996. table.insert(self.options, option)
  997. for _, alias in ipairs(option.element._aliases) do
  998. self.options[alias] = option
  999. end
  1000. end
  1001. for _, mutex in ipairs(parser._mutexes) do
  1002. for _, element in ipairs(mutex) do
  1003. if not self.element_to_mutexes[element] then
  1004. self.element_to_mutexes[element] = {}
  1005. end
  1006. table.insert(self.element_to_mutexes[element], mutex)
  1007. end
  1008. end
  1009. for _, argument in ipairs(parser._arguments) do
  1010. argument = ElementState(self, argument)
  1011. table.insert(self.arguments, argument)
  1012. argument:set_name()
  1013. argument:invoke()
  1014. end
  1015. self.handle_options = parser._handle_options
  1016. self.argument = self.arguments[self.argument_i]
  1017. self.commands = parser._commands
  1018. for _, command in ipairs(self.commands) do
  1019. for _, alias in ipairs(command._aliases) do
  1020. self.commands[alias] = command
  1021. end
  1022. end
  1023. end
  1024. function ParseState:get_option(name)
  1025. local option = self.options[name]
  1026. if not option then
  1027. self:error("unknown option '%s'%s", name, get_tip(self.options, name))
  1028. else
  1029. return option
  1030. end
  1031. end
  1032. function ParseState:get_command(name)
  1033. local command = self.commands[name]
  1034. if not command then
  1035. if #self.commands > 0 then
  1036. self:error("unknown command '%s'%s", name, get_tip(self.commands, name))
  1037. else
  1038. self:error("too many arguments")
  1039. end
  1040. else
  1041. return command
  1042. end
  1043. end
  1044. function ParseState:check_mutexes(element_state)
  1045. if self.element_to_mutexes[element_state.element] then
  1046. for _, mutex in ipairs(self.element_to_mutexes[element_state.element]) do
  1047. local used_element_state = self.mutex_to_element_state[mutex]
  1048. if used_element_state and used_element_state ~= element_state then
  1049. self:error("%s can not be used together with %s", element_state.name, used_element_state.name)
  1050. else
  1051. self.mutex_to_element_state[mutex] = element_state
  1052. end
  1053. end
  1054. end
  1055. end
  1056. function ParseState:invoke(option, name)
  1057. self:close()
  1058. option:set_name(name)
  1059. self:check_mutexes(option, name)
  1060. if option:invoke() then
  1061. self.option = option
  1062. end
  1063. end
  1064. function ParseState:pass(arg)
  1065. if self.option then
  1066. if not self.option:pass(arg) then
  1067. self.option = nil
  1068. end
  1069. elseif self.argument then
  1070. self:check_mutexes(self.argument)
  1071. if not self.argument:pass(arg) then
  1072. self.argument_i = self.argument_i + 1
  1073. self.argument = self.arguments[self.argument_i]
  1074. end
  1075. else
  1076. local command = self:get_command(arg)
  1077. self.result[command._target or command._name] = true
  1078. if self.parser._command_target then
  1079. self.result[self.parser._command_target] = command._name
  1080. end
  1081. self:switch(command)
  1082. end
  1083. end
  1084. function ParseState:close()
  1085. if self.option then
  1086. self.option:close()
  1087. self.option = nil
  1088. end
  1089. end
  1090. function ParseState:finalize()
  1091. self:close()
  1092. for i = self.argument_i, #self.arguments do
  1093. local argument = self.arguments[i]
  1094. if #argument.args == 0 and argument:default("u") then
  1095. argument:complete_invocation()
  1096. else
  1097. argument:close()
  1098. end
  1099. end
  1100. if self.parser._require_command and #self.commands > 0 then
  1101. self:error("a command is required")
  1102. end
  1103. for _, option in ipairs(self.options) do
  1104. option.name = option.name or ("option '%s'"):format(option.element._name)
  1105. if option.invocations == 0 then
  1106. if option:default("u") then
  1107. option:invoke()
  1108. option:complete_invocation()
  1109. option:close()
  1110. end
  1111. end
  1112. local mincount = option.element._mincount
  1113. if option.invocations < mincount then
  1114. if option:default("a") then
  1115. while option.invocations < mincount do
  1116. option:invoke()
  1117. option:close()
  1118. end
  1119. elseif option.invocations == 0 then
  1120. self:error("missing %s", option.name)
  1121. else
  1122. self:error("%s must be used %s", option.name, bound("time", mincount, option.element._maxcount))
  1123. end
  1124. end
  1125. end
  1126. for i = #self.command_actions, 1, -1 do
  1127. self.command_actions[i].action(self.result, self.command_actions[i].name)
  1128. end
  1129. end
  1130. function ParseState:parse(args)
  1131. for _, arg in ipairs(args) do
  1132. local plain = true
  1133. if self.handle_options then
  1134. local first = arg:sub(1, 1)
  1135. if self.charset[first] then
  1136. if #arg > 1 then
  1137. plain = false
  1138. if arg:sub(2, 2) == first then
  1139. if #arg == 2 then
  1140. if self.options[arg] then
  1141. local option = self:get_option(arg)
  1142. self:invoke(option, arg)
  1143. else
  1144. self:close()
  1145. end
  1146. self.handle_options = false
  1147. else
  1148. local equals = arg:find "="
  1149. if equals then
  1150. local name = arg:sub(1, equals - 1)
  1151. local option = self:get_option(name)
  1152. if option.element._maxargs <= 0 then
  1153. self:error("option '%s' does not take arguments", name)
  1154. end
  1155. self:invoke(option, name)
  1156. self:pass(arg:sub(equals + 1))
  1157. else
  1158. local option = self:get_option(arg)
  1159. self:invoke(option, arg)
  1160. end
  1161. end
  1162. else
  1163. for i = 2, #arg do
  1164. local name = first .. arg:sub(i, i)
  1165. local option = self:get_option(name)
  1166. self:invoke(option, name)
  1167. if i ~= #arg and option.element._maxargs > 0 then
  1168. self:pass(arg:sub(i + 1))
  1169. break
  1170. end
  1171. end
  1172. end
  1173. end
  1174. end
  1175. end
  1176. if plain then
  1177. self:pass(arg)
  1178. end
  1179. end
  1180. self:finalize()
  1181. return self.result
  1182. end
  1183. function Parser:error(msg)
  1184. io.stderr:write(("%s\n\nError: %s\n"):format(self:get_usage(), msg))
  1185. os.exit(1)
  1186. end
  1187. -- Compatibility with strict.lua and other checkers:
  1188. local default_cmdline = rawget(_G, "arg") or {}
  1189. function Parser:_parse(args, error_handler)
  1190. return ParseState(self, error_handler):parse(args or default_cmdline)
  1191. end
  1192. function Parser:parse(args)
  1193. return self:_parse(args, self.error)
  1194. end
  1195. local function xpcall_error_handler(err)
  1196. return tostring(err) .. "\noriginal " .. debug.traceback("", 2):sub(2)
  1197. end
  1198. function Parser:pparse(args)
  1199. local parse_error
  1200. local ok, result = xpcall(function()
  1201. return self:_parse(args, function(_, err)
  1202. parse_error = err
  1203. error(err, 0)
  1204. end)
  1205. end, xpcall_error_handler)
  1206. if ok then
  1207. return true, result
  1208. elseif not parse_error then
  1209. error(result, 0)
  1210. else
  1211. return false, parse_error
  1212. end
  1213. end
  1214. local argparse = {}
  1215. argparse.version = "0.6.0"
  1216. setmetatable(argparse, {__call = function(_, ...)
  1217. return Parser(default_cmdline[0]):add_help(true)(...)
  1218. end})
  1219. return argparse