<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://the.satanic.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ACLI</id>
	<title>Module:CLI - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://the.satanic.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ACLI"/>
	<link rel="alternate" type="text/html" href="https://the.satanic.wiki/index.php?title=Module:CLI&amp;action=history"/>
	<updated>2026-04-20T06:31:01Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://the.satanic.wiki/index.php?title=Module:CLI&amp;diff=10874&amp;oldid=prev</id>
		<title>WikiGOD: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://the.satanic.wiki/index.php?title=Module:CLI&amp;diff=10874&amp;oldid=prev"/>
		<updated>2021-04-30T02:23:49Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 02:23, 30 April 2021&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key zzegtzyr_mw19226-mwjf_:diff:1.41:old-10873:rev-10874 --&gt;
&lt;/table&gt;</summary>
		<author><name>WikiGOD</name></author>
	</entry>
	<entry>
		<id>https://the.satanic.wiki/index.php?title=Module:CLI&amp;diff=10873&amp;oldid=prev</id>
		<title>Mediawiki&gt;8nml at 08:41, 12 June 2020</title>
		<link rel="alternate" type="text/html" href="https://the.satanic.wiki/index.php?title=Module:CLI&amp;diff=10873&amp;oldid=prev"/>
		<updated>2020-06-12T08:41:45Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--  &amp;lt;nowiki&amp;gt;&lt;br /&gt;
--- CLI command-line generator for development &amp;amp; debugging tools.&lt;br /&gt;
--  This module is used to execute command lines containing command line&lt;br /&gt;
--  arguments. Command line strings are quoted similarly to shell quotes&lt;br /&gt;
--  in Unix and Windows command lines. Unlike Unix, single quoting is&lt;br /&gt;
--  supported.&lt;br /&gt;
--  &lt;br /&gt;
--  The command line string supports these environment variables:&lt;br /&gt;
--   * `%PATH%` - calling module in the Lua stack.&lt;br /&gt;
--   * `%OS%` - Lua version (5.1 for the foreseeable future).&lt;br /&gt;
--  &lt;br /&gt;
--  This module is supplied arguments in the Scribunto console. The&lt;br /&gt;
--  general command synopsis (in man command format) is:&lt;br /&gt;
--  {{#tag:pre|p &amp;quot;&amp;lt;command&amp;gt; [&amp;lt;arg&amp;gt;] [--flag [ &amp;lt;value&amp;gt;]]&amp;quot;}}&lt;br /&gt;
--  The help command will output a command synopsis in the [man command&lt;br /&gt;
--  format](https://linux.die.net/man/7/man-pages).&lt;br /&gt;
--  &lt;br /&gt;
--  This module supports the following syntax:&lt;br /&gt;
--   * Positional arguments (space-delimited): `one two three`&lt;br /&gt;
--   * Boolean command flags: `-one`, `--one`&lt;br /&gt;
--   * Variable command flags: `--one &amp;quot;numero uno&amp;quot;`&lt;br /&gt;
--   * Quoted arguments: `one &amp;quot;numero dos&amp;quot;`&lt;br /&gt;
--   * Variable assignments: `one=&amp;quot;one&amp;quot;`&lt;br /&gt;
--   * Escapes: quotes as `\\&amp;quot;` or `\\&amp;#039;` and spaces as `\\ `&lt;br /&gt;
--  &lt;br /&gt;
--  The first positional argument is recognised as a command word and is&lt;br /&gt;
--  executed within the command object. The command sends its output to&lt;br /&gt;
--  the [[Lua templating/Debug console|Scribunto console]] using&lt;br /&gt;
--  @{mw.log}. Note that command flags must be placed after positional&lt;br /&gt;
--  arguments to work.&lt;br /&gt;
--  &lt;br /&gt;
--  The command API prints the CLI usage if the `help` command word or&lt;br /&gt;
--  `--help`/`-help` flag is supplied. When a command is combined with&lt;br /&gt;
--  `--help` or `-help`, or a command word is defined as a second&lt;br /&gt;
--  positional argument, the help statement is tailored to the specific&lt;br /&gt;
--  command, its usage and options.&lt;br /&gt;
--  &lt;br /&gt;
--  @release            beta&lt;br /&gt;
--  @classmod           CommandLine&lt;br /&gt;
--  @pragma             ulist&lt;br /&gt;
--  @pragma             noluaref&lt;br /&gt;
--  @author             [[User:8nml|8nml]]&lt;br /&gt;
--  @attribution        [[github:laurent|@laurent]] ([[github:laurent/massren|Github]])&lt;br /&gt;
--  @demo               [[Module:Docbunto/cli]]&lt;br /&gt;
--  @see                [https://stackoverflow.com/a/46973603 Original code (Go)].&lt;br /&gt;
local CommandLine = {}&lt;br /&gt;
&lt;br /&gt;
--  Module dependencies.&lt;br /&gt;
local util = require &amp;#039;libraryUtil&amp;#039;&lt;br /&gt;
local _VERSION = _VERSION&lt;br /&gt;
local pairs, ipairs, next, rawget, error = pairs, ipairs, next, rawget, error&lt;br /&gt;
local tostring, tonumber, type, setmetatable = tostring, tonumber, type, setmetatable&lt;br /&gt;
local log, traceback, remove, insert = mw.log, debug.traceback, table.remove, table.insert&lt;br /&gt;
&lt;br /&gt;
--  Module variables.&lt;br /&gt;
local CLI_INTERPRETER = &amp;#039;LuaSandbox&amp;#039;&lt;br /&gt;
local CLI_STATE_START = &amp;#039;start&amp;#039;&lt;br /&gt;
local CLI_STATE_QUOTE = &amp;#039;quote&amp;#039;&lt;br /&gt;
local CLI_STATE_ARG = &amp;#039;argument&amp;#039;&lt;br /&gt;
&lt;br /&gt;
--- Converts a Lua string representation of a primitive.&lt;br /&gt;
--  @param              {string} str Unquoted string, or Lua primitive&lt;br /&gt;
--                      as a string representation.&lt;br /&gt;
--  @return             {number|boolean|string} Lua primitive that&lt;br /&gt;
--                      corresponds to string, or origiinal string.&lt;br /&gt;
local function tovalue(str)&lt;br /&gt;
    if tonumber(str) then&lt;br /&gt;
        return tonumber(str)&lt;br /&gt;
    elseif str == &amp;#039;true&amp;#039; then&lt;br /&gt;
        return true&lt;br /&gt;
    elseif str == &amp;#039;false&amp;#039; then&lt;br /&gt;
        return false&lt;br /&gt;
    elseif str == &amp;#039;nil&amp;#039; then&lt;br /&gt;
        return nil&lt;br /&gt;
    else&lt;br /&gt;
        return str&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Adds a metatable for indexing CLI options table by name.&lt;br /&gt;
local function options_metatable(t, k)&lt;br /&gt;
    for _, opt in ipairs(t) do&lt;br /&gt;
        if k == opt.name or (opt.alias and k == opt.alias) then&lt;br /&gt;
            return opt&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return rawget(t, k)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Synopsis generator function.&lt;br /&gt;
--  @param              {table} options Array of option names or option&lt;br /&gt;
--                      configurations.&lt;br /&gt;
--  @param              {table} config Command line configuration.&lt;br /&gt;
--  @return             {string} Command line sypnosis.&lt;br /&gt;
local function synopsis(options, config, word)&lt;br /&gt;
    local buffer, optconf = {}&lt;br /&gt;
&lt;br /&gt;
    table.insert(buffer, &amp;#039;    p &amp;quot;&amp;#039;)&lt;br /&gt;
    table.insert(buffer, word)&lt;br /&gt;
    table.insert(buffer, #options ~= 0 and &amp;#039; &amp;#039; or &amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    for index, opt in ipairs(options) do&lt;br /&gt;
        optconf = type(opt) == &amp;#039;table&amp;#039; and opt or config.options[opt]&lt;br /&gt;
        table.insert(buffer, index ~= 1 and &amp;#039; &amp;#039; or &amp;#039;&amp;#039;)&lt;br /&gt;
        table.insert(buffer, optconf.required and (optconf.alias and &amp;#039;{&amp;#039; or &amp;#039;&amp;#039;) or &amp;#039;[&amp;#039;)&lt;br /&gt;
        table.insert(buffer, type(optconf.name) == &amp;#039;number&amp;#039;&lt;br /&gt;
            and (&amp;#039;&amp;lt;&amp;#039; .. (optconf.alias or tostring(optconf.name)) .. &amp;#039;&amp;gt;&amp;#039;)&lt;br /&gt;
            or  (&lt;br /&gt;
                    &amp;#039;--&amp;#039; .. optconf.name ..&lt;br /&gt;
                    (optconf.type and &amp;#039; &amp;#039; or &amp;#039;&amp;#039;) ..&lt;br /&gt;
                    (optconf.type and (&amp;#039;&amp;lt;&amp;#039;.. optconf.type ..&amp;#039;&amp;gt;&amp;#039;) or &amp;#039;&amp;#039;)&lt;br /&gt;
                )&lt;br /&gt;
        )&lt;br /&gt;
        table.insert(buffer, optconf.alias and &amp;#039; | &amp;#039; or &amp;#039;&amp;#039;)&lt;br /&gt;
        table.insert(buffer, optconf.alias&lt;br /&gt;
            and (&lt;br /&gt;
                (#optconf.alias == 1 and &amp;#039;-&amp;#039; or &amp;#039;--&amp;#039;) ..&lt;br /&gt;
                optconf.alias ..&lt;br /&gt;
                (optconf.type and &amp;#039; &amp;#039; or &amp;#039;&amp;#039;) ..&lt;br /&gt;
                (optconf.type and (&amp;#039;&amp;lt;&amp;#039;.. optconf.type ..&amp;#039;&amp;gt;&amp;#039;) or &amp;#039;&amp;#039;)&lt;br /&gt;
            )&lt;br /&gt;
            or  &amp;#039;&amp;#039;&lt;br /&gt;
        )&lt;br /&gt;
        table.insert(buffer, optconf.required and (optconf.alias and &amp;#039;}&amp;#039; or &amp;#039;&amp;#039;) or &amp;#039;]&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    table.insert(buffer, &amp;#039;&amp;quot;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    return table.concat(buffer)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Okay, what do **YOU** think this does?&lt;br /&gt;
local function padright(str, len, char)&lt;br /&gt;
    char = char or &amp;#039; &amp;#039;&lt;br /&gt;
    return str .. string.rep(char, len - #str)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Command line function generator.&lt;br /&gt;
--  @param              {table} config&lt;br /&gt;
--                      Command line configuration.&lt;br /&gt;
--  @param              {string} config.description&lt;br /&gt;
--                      Interfaced module description.&lt;br /&gt;
--  @param              {table} config.commands&lt;br /&gt;
--                      Object containing command methods.&lt;br /&gt;
--  @param              {table} config.words&lt;br /&gt;
--                      Configuration object with command methods as&lt;br /&gt;
--                      keys. Each table contains the following&lt;br /&gt;
--                      configuration table fields:&lt;br /&gt;
--                       ** `description` Description of command.&lt;br /&gt;
--                      (string)&lt;br /&gt;
--                       ** `options` Dependent options for command.&lt;br /&gt;
--                      (table)&lt;br /&gt;
--  @param[opt]         {table} config.options&lt;br /&gt;
--                      Command line options configuration. This option&lt;br /&gt;
--                      is defined as an array with option configuration&lt;br /&gt;
--                      tables as elements. Each table contains the&lt;br /&gt;
--                      following configuration table fields:&lt;br /&gt;
--                       ** `name` Name of option. Accepts number when&lt;br /&gt;
--                      the option is a positional argument. (string&lt;br /&gt;
--                      or number)&lt;br /&gt;
--                       ** `alias` Alias for option. (string; optional)&lt;br /&gt;
--                       ** `description` Description of option. (string)&lt;br /&gt;
--                       ** `type` Type of option. Omitted for boolean&lt;br /&gt;
--                      flags. (optional)&lt;br /&gt;
--                       ** `required` Whether the argument or flag is&lt;br /&gt;
--                      not optional. Default: `false`. (boolean;&lt;br /&gt;
--                      optional)&lt;br /&gt;
--  @return             {function} Command line handler. Help commands&lt;br /&gt;
--                      will produce a command synopsis detailing usage,&lt;br /&gt;
--                      a list of commands and a list of options. Other&lt;br /&gt;
--                      commands will be executed if a corresponding&lt;br /&gt;
--                      method is present in `config.commands`.&lt;br /&gt;
function CommandLine:new(config)&lt;br /&gt;
    util.checkType(&amp;#039;new&amp;#039;, 1, config, &amp;#039;table&amp;#039;)&lt;br /&gt;
    util.checkTypeForNamedArg(&amp;#039;new&amp;#039;, &amp;#039;description&amp;#039;, config.description, &amp;#039;string&amp;#039;)&lt;br /&gt;
    util.checkTypeForNamedArg(&amp;#039;new&amp;#039;, &amp;#039;commands&amp;#039;, config.commands, &amp;#039;table&amp;#039;)&lt;br /&gt;
    util.checkTypeForNamedArg(&amp;#039;new&amp;#039;, &amp;#039;words&amp;#039;, config.words, &amp;#039;table&amp;#039;)&lt;br /&gt;
    util.checkTypeForNamedArg(&amp;#039;new&amp;#039;, &amp;#039;options&amp;#039;, config.options, &amp;#039;table&amp;#039;, true)&lt;br /&gt;
    setmetatable(config.options, { __index = options_metatable })&lt;br /&gt;
&lt;br /&gt;
    return function(command)&lt;br /&gt;
        local args, argv, argc = self:parse(command, config)&lt;br /&gt;
        local word = remove(args, 1)&lt;br /&gt;
&lt;br /&gt;
        if ((word == &amp;#039;help&amp;#039;) or args.help) then&lt;br /&gt;
            if&lt;br /&gt;
                args[1] or&lt;br /&gt;
                (word and word ~= &amp;#039;help&amp;#039; and args.help == true) or&lt;br /&gt;
                type(args.help) == &amp;#039;string&amp;#039;&lt;br /&gt;
            then&lt;br /&gt;
                local command; if word == &amp;#039;help&amp;#039; then&lt;br /&gt;
                    command = args[1]&lt;br /&gt;
                elseif type(args.help) == &amp;#039;boolean&amp;#039; then&lt;br /&gt;
                    command = word&lt;br /&gt;
                elseif type(args.help) == &amp;#039;string&amp;#039; then&lt;br /&gt;
                    command = args.help&lt;br /&gt;
                end&lt;br /&gt;
&lt;br /&gt;
                if not command or not config.words[command] then&lt;br /&gt;
                    log(&amp;#039;&amp;quot;&amp;#039; .. tostring(command) .. &amp;#039;&amp;quot; is not a recognised command. Printing help..&amp;#039;)&lt;br /&gt;
                    log(&amp;#039;&amp;#039;)&lt;br /&gt;
                    CommandLine:new(config) &amp;#039;help&amp;#039;&lt;br /&gt;
                    return&lt;br /&gt;
                end&lt;br /&gt;
&lt;br /&gt;
                log(tostring(command) .. &amp;#039;: &amp;#039; .. config.words[command].description)&lt;br /&gt;
&lt;br /&gt;
                if not config.words[command].options then&lt;br /&gt;
                    return&lt;br /&gt;
                end&lt;br /&gt;
                log(&amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
                log(&amp;#039;Command sypnosis:&amp;#039;)&lt;br /&gt;
                log(synopsis(config.words[command].options, config, command))&lt;br /&gt;
                log(&amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
                log(&amp;#039;Command line options available in &amp;quot;&amp;#039; .. tostring(command) .. &amp;#039;&amp;quot;:&amp;#039;)&lt;br /&gt;
                for _, opt in ipairs(config.words[command].options) do&lt;br /&gt;
                    log(&lt;br /&gt;
                        &amp;#039;    &amp;#039; ..&lt;br /&gt;
                        padright(&lt;br /&gt;
                            tostring(config.options[opt].name) ..&lt;br /&gt;
                            (config.options[opt].alias and (&amp;#039; | &amp;#039; .. config.options[opt].alias) or &amp;#039;&amp;#039;),&lt;br /&gt;
                            24&lt;br /&gt;
                        ) ..&lt;br /&gt;
                        &amp;#039;: &amp;#039; ..&lt;br /&gt;
                        config.options[opt].description&lt;br /&gt;
                    )&lt;br /&gt;
                end&lt;br /&gt;
&lt;br /&gt;
            else&lt;br /&gt;
                log(config.description)&lt;br /&gt;
                log(&amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
                log(&amp;#039;General command line sypnosis:&amp;#039;)&lt;br /&gt;
                log(synopsis(config.options, config, &amp;#039;&amp;lt;command&amp;gt;&amp;#039;))&lt;br /&gt;
                log(&amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
                log(&amp;#039;Commands available in &amp;#039; .. args[0] .. &amp;#039;:&amp;#039;)&lt;br /&gt;
                for word, wordconf in pairs(config.words) do&lt;br /&gt;
                    log(&amp;#039;    &amp;#039; .. padright(tostring(word), 24) .. &amp;#039;: &amp;#039; .. wordconf.description)&lt;br /&gt;
                end&lt;br /&gt;
                log(&amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
                log(&amp;#039;Command line options available in &amp;#039; .. args[0] .. &amp;#039;:&amp;#039;)&lt;br /&gt;
                for _, optconf in ipairs(config.options) do&lt;br /&gt;
                    log(&lt;br /&gt;
                        &amp;#039;    &amp;#039; ..&lt;br /&gt;
                        padright(&lt;br /&gt;
                            tostring(optconf.name) ..&lt;br /&gt;
                            (optconf.alias and (&amp;#039; | &amp;#039; .. optconf.alias) or &amp;#039;&amp;#039;),&lt;br /&gt;
                            24&lt;br /&gt;
                        ) ..&lt;br /&gt;
                        &amp;#039;: &amp;#039; ..&lt;br /&gt;
                        optconf.description&lt;br /&gt;
                    )&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
        elseif word and config.commands[word] then&lt;br /&gt;
            return config.commands[word](args)&lt;br /&gt;
        else&lt;br /&gt;
            log(&amp;#039;&amp;quot;&amp;#039; .. tostring(word) .. &amp;#039;&amp;quot; is not a recognised command. Printing help..&amp;#039;)&lt;br /&gt;
            log(&amp;#039;&amp;#039;)&lt;br /&gt;
            CommandLine:new(config) &amp;#039;help&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Command line shell quote parser.&lt;br /&gt;
--  @function           CommandLine:parse&lt;br /&gt;
--  @param              {string} command Command line to be parsed.&lt;br /&gt;
--  @param[opt]         {table} config Command line configuration.&lt;br /&gt;
--  @error[377]         {string} &amp;quot;empty command line&amp;quot;&lt;br /&gt;
--  @error[382]         {string} &amp;quot;unterminated quote in command line:&lt;br /&gt;
--                      $command&amp;quot;&lt;br /&gt;
--  @error[424]         {string} &amp;quot;unconfigured argument or flag &amp;quot;$arg&amp;quot;&lt;br /&gt;
--                      in command line&amp;quot;&lt;br /&gt;
--  @return             {table} Map of processed arguments. The array,&lt;br /&gt;
--                      or sequential keys in the map list positional&lt;br /&gt;
--                      arguments in the command line. The flags in&lt;br /&gt;
--                      the command line are converted into named&lt;br /&gt;
--                      arguments. Metadata fields:&lt;br /&gt;
--                       * `0` The CLI module name or context.&lt;br /&gt;
--                       * `&amp;quot;PATH&amp;quot;` The CLI module name or context.&lt;br /&gt;
--                       * `-1` The Lua interpreter Scribunto uses.&lt;br /&gt;
--                       * `-2` The Lua version Scribunto runs.&lt;br /&gt;
--                       * `&amp;quot;OS&amp;quot;` The Lua version Scribunto runs.&lt;br /&gt;
--  @return             {table} Array of processed arguments. Includes&lt;br /&gt;
--                      the metadata fields listed above.&lt;br /&gt;
--  @return             {table} Number of arguments passed by the user,&lt;br /&gt;
--                      counted like the C or C++ `argc` convention.&lt;br /&gt;
function CommandLine:parse(command, config)&lt;br /&gt;
    util.checkType(&amp;#039;parse&amp;#039;, 1, command, &amp;#039;string&amp;#039;)&lt;br /&gt;
    util.checkType(&amp;#039;parse&amp;#039;, 2, config, &amp;#039;table&amp;#039;, true)&lt;br /&gt;
    config = config or { options = {} }&lt;br /&gt;
&lt;br /&gt;
    local args = {}&lt;br /&gt;
    local argv = {}&lt;br /&gt;
    local argc = 0&lt;br /&gt;
&lt;br /&gt;
    -- Initialise stack variables.&lt;br /&gt;
    local state = CLI_STATE_START&lt;br /&gt;
    local stack = &amp;#039;&amp;#039;&lt;br /&gt;
    local quote = &amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
    local escape_next = true&lt;br /&gt;
&lt;br /&gt;
    -- Attach version, interpreter &amp;amp; module path to argument value array.&lt;br /&gt;
    argv[-2] = _VERSION&lt;br /&gt;
    argv[-1] = CLI_INTERPRETER&lt;br /&gt;
    argv[0] = mw.title.getCurrentTitle().prefixedText&lt;br /&gt;
    for modulename in (traceback() or &amp;#039;&amp;#039;):gmatch(&amp;#039;\n\t([^(%[][^:\n]+:[^:\n]+)&amp;#039;) do&lt;br /&gt;
        if not modulename:find(&amp;#039;:CLI%f[%z: ]&amp;#039;) then&lt;br /&gt;
            argv[0] = modulename:gsub(&amp;#039;(input):%d+$&amp;#039;, &amp;#039;%1&amp;#039;)&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Attach version, interpreter and module path to argument map array.&lt;br /&gt;
    args[-1] = argv[-1]&lt;br /&gt;
    args[0] = argv[0]&lt;br /&gt;
    args.PATH = argv[0]&lt;br /&gt;
    args.OS = argv[-2]&lt;br /&gt;
&lt;br /&gt;
    -- Replace %PATH% with the module name.&lt;br /&gt;
    command = command:gsub(&amp;#039;%%PATH%%&amp;#039;, argv[0])&lt;br /&gt;
&lt;br /&gt;
    -- Replace %OS% with the Lua version.&lt;br /&gt;
    command = command:gsub(&amp;#039;%%OS%%&amp;#039;, argv[-2])&lt;br /&gt;
&lt;br /&gt;
    -- Parse command chunks.&lt;br /&gt;
    local cmd_length = 0&lt;br /&gt;
    for chunk in command:gmatch(&amp;#039;.&amp;#039;) do&lt;br /&gt;
        cmd_length = cmd_length + 1&lt;br /&gt;
        -- Shell quote parsing.&lt;br /&gt;
        if state == CLI_STATE_QUOTE then&lt;br /&gt;
            -- Reset the stack and state.&lt;br /&gt;
            if chunk == quote then&lt;br /&gt;
                insert(argv, stack)&lt;br /&gt;
                stack = &amp;#039;&amp;#039;&lt;br /&gt;
                state = CLI_STATE_START&lt;br /&gt;
            else&lt;br /&gt;
                stack = stack .. chunk&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
        elseif escape_next then&lt;br /&gt;
            stack = stack .. chunk&lt;br /&gt;
            escape_next = false&lt;br /&gt;
&lt;br /&gt;
        elseif chunk == &amp;#039;\\&amp;#039; then&lt;br /&gt;
            escape_next = true&lt;br /&gt;
&lt;br /&gt;
        elseif chunk == &amp;#039;&amp;quot;&amp;#039; or chunk == &amp;quot;&amp;#039;&amp;quot; then&lt;br /&gt;
            state = CLI_STATE_QUOTE&lt;br /&gt;
            quote = chunk&lt;br /&gt;
&lt;br /&gt;
        elseif state == CLI_STATE_ARG then&lt;br /&gt;
            if chunk == &amp;#039; &amp;#039; or chunk == &amp;#039;\t&amp;#039; then&lt;br /&gt;
                insert(argv, stack)&lt;br /&gt;
                stack = &amp;#039;&amp;#039;&lt;br /&gt;
                state = CLI_STATE_START&lt;br /&gt;
            else&lt;br /&gt;
                stack = stack .. chunk&lt;br /&gt;
                if #command == cmd_length then&lt;br /&gt;
                    insert(argv, stack)&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
        elseif chunk ~= &amp;#039; &amp;#039; and chunk ~= &amp;#039;\t&amp;#039; then&lt;br /&gt;
            state = CLI_STATE_ARG&lt;br /&gt;
            stack = stack .. chunk&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Check for empty command line.&lt;br /&gt;
    local argc = #argv&lt;br /&gt;
    if argc == 0 then&lt;br /&gt;
        error(&amp;#039;empty command line&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Check for unterminated strings.&lt;br /&gt;
    if state == CLI_STATE_QUOTE then&lt;br /&gt;
        error(&amp;#039;unterminated quote in command line: &amp;#039; .. command)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Command line argument parsing.&lt;br /&gt;
    for index, arg in ipairs(argv) do&lt;br /&gt;
        argv[index] = tovalue(arg)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    for index, arg in ipairs(argv) do&lt;br /&gt;
        -- Command line flag parsing.&lt;br /&gt;
        if type(arg) == &amp;#039;string&amp;#039; and arg:find(&amp;#039;^%-&amp;#039;) then&lt;br /&gt;
            arg = arg:gsub(&amp;#039;^%-%-?&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
            if type(argv[index + 1]) == &amp;#039;string&amp;#039; and not argv[index + 1]:find(&amp;#039;^%-&amp;#039;) then&lt;br /&gt;
                index = index + 1&lt;br /&gt;
                args[arg] = argv[index]&lt;br /&gt;
            else&lt;br /&gt;
                args[arg] = true&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
        -- Command line variable parsing.&lt;br /&gt;
        elseif type(arg) == &amp;#039;string&amp;#039; and arg:find(&amp;#039;%S=%S&amp;#039;) then&lt;br /&gt;
            local key = arg:match(&amp;#039;^[^=]+&amp;#039;)&lt;br /&gt;
            key = tonumber(key) or key&lt;br /&gt;
            local val = arg:match(&amp;#039;[^=]+$&amp;#039;)&lt;br /&gt;
            args[key] = val&lt;br /&gt;
            _G[key] = val&lt;br /&gt;
&lt;br /&gt;
        -- Positional command line arguments.&lt;br /&gt;
        else&lt;br /&gt;
            insert(args, arg)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Check for undefined options when configured.&lt;br /&gt;
    for arg in pairs(args) do&lt;br /&gt;
        if&lt;br /&gt;
            next(config.options) and&lt;br /&gt;
            (args[1] ~= &amp;#039;help&amp;#039; and arg ~= &amp;#039;help&amp;#039;) and&lt;br /&gt;
            (arg ~= &amp;#039;PATH&amp;#039; and arg ~= &amp;#039;OS&amp;#039;) and&lt;br /&gt;
            ( type(arg) ~= &amp;#039;number&amp;#039; or (arg &amp;gt;= 2) ) and&lt;br /&gt;
            not config.options[type(arg) == &amp;#039;number&amp;#039; and (arg - 1) or arg]&lt;br /&gt;
        then&lt;br /&gt;
            error(&amp;#039;unconfigured argument or flag &amp;quot;&amp;#039; .. (type(arg) == &amp;#039;number&amp;#039; and tostring(arg - 1) or arg) .. &amp;#039;&amp;quot; in command line&amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Alias translation for configured argument options.&lt;br /&gt;
    if type(config) == &amp;#039;table&amp;#039; and type(config.options) == &amp;#039;table&amp;#039; then&lt;br /&gt;
        for _, optconf in ipairs(config.options) do&lt;br /&gt;
            if optconf.alias and args[optconf.alias] then&lt;br /&gt;
                args[optconf.name] = args[optconf.alias]&lt;br /&gt;
                remove(args, optconf.alias)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return args, argv, argc&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return CommandLine&lt;br /&gt;
--  &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mediawiki&gt;8nml</name></author>
	</entry>
</feed>