From e92c37b6e3b30268033eaf2ad634998340c0fa3e Mon Sep 17 00:00:00 2001 From: Paul Ouellette Date: Wed, 12 Jun 2019 16:03:43 -0400 Subject: Use argparse for command line argument parsing Supports main options and init and lint commands --- src/bin/luarocks | 2 +- src/bin/luarocks-admin | 2 +- src/luarocks/cmd.lua | 250 +++++++++++++++++++++++++++++----------------- src/luarocks/cmd/help.lua | 139 -------------------------- src/luarocks/cmd/init.lua | 52 +++++----- src/luarocks/cmd/lint.lua | 32 +++--- src/luarocks/util.lua | 164 ++---------------------------- 7 files changed, 209 insertions(+), 432 deletions(-) delete mode 100644 src/luarocks/cmd/help.lua diff --git a/src/bin/luarocks b/src/bin/luarocks index d982530c..f277b348 100755 --- a/src/bin/luarocks +++ b/src/bin/luarocks @@ -33,4 +33,4 @@ local commands = { test = "luarocks.cmd.test", } -cmd.run_command(description, commands, "luarocks.cmd.external", ...) +cmd.run_command("luarocks", description, commands, "luarocks.cmd.external", ...) diff --git a/src/bin/luarocks-admin b/src/bin/luarocks-admin index 71e17b55..ddbe0f48 100755 --- a/src/bin/luarocks-admin +++ b/src/bin/luarocks-admin @@ -16,4 +16,4 @@ local commands = { refresh_cache = "luarocks.admin.cmd.refresh_cache", } -cmd.run_command(description, commands, "luarocks.admin.cmd.external", ...) +cmd.run_command("luarocks-admin", description, commands, "luarocks.admin.cmd.external", ...) diff --git a/src/luarocks/cmd.lua b/src/luarocks/cmd.lua index 1ead6c4b..23ca023a 100644 --- a/src/luarocks/cmd.lua +++ b/src/luarocks/cmd.lua @@ -2,16 +2,14 @@ --- Functions for command-line scripts. local cmd = {} -local unpack = unpack or table.unpack - local loader = require("luarocks.loader") local util = require("luarocks.util") local path = require("luarocks.path") -local deps = require("luarocks.deps") local cfg = require("luarocks.core.cfg") local dir = require("luarocks.dir") local fun = require("luarocks.fun") local fs = require("luarocks.fs") +local argparse = require("argparse") local hc_ok, hardcoded = pcall(require, "luarocks.core.hardcoded") if not hc_ok then @@ -91,8 +89,8 @@ do else replace_tree(flags, cfg.home_tree) end - elseif flags["project-tree"] then - local tree = flags["project-tree"] + elseif flags["project_tree"] then + local tree = flags["project_tree"] table.insert(cfg.rocks_trees, 1, { name = "project", root = tree } ) loader.load_rocks_trees() path.use_tree(tree) @@ -131,14 +129,14 @@ local function process_server_flags(flags) cfg.rocks_servers = fun.concat(dev_servers, cfg.rocks_servers) end - if flags["only-server"] then + if flags["only_server"] then if flags["dev"] then return nil, "--only-server cannot be used with --dev" end if flags["server"] then return nil, "--only-server cannot be used with --server" end - cfg.rocks_servers = { flags["only-server"] } + cfg.rocks_servers = { flags["only_server"] } end return true @@ -231,12 +229,12 @@ do end local function detect_lua_via_flags(flags, project_dir) - local lua_version = flags["lua-version"] + local lua_version = flags["lua_version"] or find_default_lua_version(flags, project_dir) or (project_dir and find_version_from_config(project_dir)) - if flags["lua-dir"] then - local detected, err = util.find_lua(flags["lua-dir"], lua_version) + if flags["lua_dir"] then + local detected, err = util.find_lua(flags["lua_dir"], lua_version) if not detected then die(err) end @@ -265,13 +263,13 @@ do end detect_config_via_flags = function(flags) - local project_dir, given = find_project_dir(flags["project-tree"]) + local project_dir, given = find_project_dir(flags["project_tree"]) local detected = detect_lua_via_flags(flags, project_dir) - if flags["lua-version"] then - detected.given_lua_version = flags["lua-version"] + if flags["lua_version"] then + detected.given_lua_version = flags["lua_version"] end - if flags["lua-dir"] then - detected.given_lua_dir = flags["lua-dir"] + if flags["lua_dir"] then + detected.given_lua_dir = flags["lua_dir"] end if given then detected.given_project_dir = project_dir @@ -306,6 +304,103 @@ do end end +local function get_status(status) + return status and "ok" or "not found" +end + +local function get_config_text() + local buf = "Configuration:\n Lua version: "..cfg.lua_version.."\n" + if cfg.luajit_version then + buf = buf.." LuaJIT version: "..cfg.luajit_version.."\n" + end + buf = buf.."\n Configuration files:\n" + local conf = cfg.config_files + buf = buf.." System : "..fs.absolute_name(conf.system.file).." ("..get_status(conf.system.found)..")\n" + if conf.user.file then + buf = buf.." User : "..fs.absolute_name(conf.user.file).." ("..get_status(conf.user.found)..")\n" + else + buf = buf.." User : disabled in this LuaRocks installation.\n" + end + if conf.project then + buf = buf.." Project : "..fs.absolute_name(conf.project.file).." ("..get_status(conf.project.found)..")\n" + end + buf = buf.."\n Rocks trees in use: \n" + for _, tree in ipairs(cfg.rocks_trees) do + if type(tree) == "string" then + buf = buf.." "..fs.absolute_name(tree) + else + local name = tree.name and " (\""..tree.name.."\")" or "" + buf = buf.." "..fs.absolute_name(tree.root)..name + end + end + + return buf.."\n" +end + +local function get_parser(program_name, description, cmd_modules) + local epilog = [[ +Variables: + Variables from the "variables" table of the configuration file can be + overridden with VAR=VALUE assignments. + +]]..get_config_text() + + local parser = argparse( + program_name, "LuaRocks "..cfg.program_version..", the Lua package manager\n\n".. + program.." - "..description, epilog) + :help_max_width(80) + :add_help("--help") + :add_help_command({add_help = false}) + :command_target("command") + :require_command(false) + + parser:flag("--version", "Show version info and exit.") + :action(function() + util.printout(program.." "..cfg.program_version) + util.printout(description) + util.printout() + os.exit(cmd.errorcodes.OK) + end) + parser:flag("--dev", "Enable the sub-repositories in rocks servers for ".. + "rockspecs of in-development versions.") + parser:option("--server", "Fetch rocks/rockspecs from this server ".. + "(takes priority over config file).") + parser:option("--only-server", "Fetch rocks/rockspecs from this server only ".. + "(overrides any entries in the config file).") + :argname("") + parser:option("--only-sources", "Restrict downloads to paths matching the given URL.") + :argname("") + parser:option("--lua-dir", "Which Lua installation to use.") + :argname("") + parser:option("--lua-version", "Which Lua version to use.") + :argname("") + parser:option("--tree", "Which tree to operate on.") + parser:option("--project-tree"):hidden(true) -- TODO: Description? + parser:flag("--local", "Use the tree in the user's home directory.\n".. + "To enable it, see '"..program.." help path'.") + parser:flag("--global", "Use the system tree when `local_by_default` is `true`.") + parser:flag("--verbose", "Display verbose output of commands executed.") + parser:option("--timeout", "Timeout on network operations, in seconds.\n".. + "0 means no timeout (wait forever). Default is ".. + tostring(cfg.connection_timeout)..".") + :argname("") + :convert(tonumber) + + -- Compatibility for old names of some options + parser:option("--to"):target("tree"):hidden(true) + parser:option("--from"):target("server"):hidden(true) + parser:option("--only-from"):target("only_server"):hidden(true) + parser:option("--only-sources-from"):target("only_sources"):hidden(true) + + for _, module in util.sortedpairs(cmd_modules) do + if module.add_to_parser then -- TODO: Remove this check. + module.add_to_parser(parser) + end + end + + return parser +end + --- Main command-line processor. -- Parses input arguments and calls the appropriate driver function -- to execute the action requested on the command-line, forwarding @@ -314,11 +409,24 @@ end -- @param commands table: contains the loaded modules representing commands. -- @param external_namespace string: where to look for external commands. -- @param ... string: Arguments given on the command-line. -function cmd.run_command(description, commands, external_namespace, ...) +function cmd.run_command(program_name, description, commands, external_namespace, ...) check_popen() - local function process_arguments(...) + fs.init() + + for _, module_name in ipairs(fs.modules(external_namespace)) do + if not commands[module_name] then + commands[module_name] = external_namespace.."."..module_name + end + end + + local cmd_modules = {} + for name, module in pairs(commands) do + cmd_modules[name] = require(module) + end + + local function process_cmdline_vars(...) local args = {...} local cmdline_vars = {} local last = #args @@ -340,69 +448,38 @@ function cmd.run_command(description, commands, external_namespace, ...) end end end - local nonflags = { util.parse_flags(unpack(args)) } - local flags = table.remove(nonflags, 1) - if flags.ERROR then - die(flags.ERROR.." See --help.") - end - -- Compatibility for old names of some flags - if flags["to"] then flags["tree"] = flags["to"] end - if flags["from"] then flags["server"] = flags["from"] end - if flags["nodeps"] then flags["deps-mode"] = "none" end - if flags["only-from"] then flags["only-server"] = flags["only-from"] end - if flags["only-sources-from"] then flags["only-sources"] = flags["only-sources-from"] end - - return flags, nonflags, cmdline_vars + return args, cmdline_vars end - local flags, nonflags, cmdline_vars = process_arguments(...) + local args, cmdline_vars = process_cmdline_vars(...) + local parser = get_parser(program_name, description, cmd_modules) + args = parser:parse(args) - if flags["timeout"] then -- setting it in the config file will kick-in earlier in the process - local timeout = tonumber(flags["timeout"]) - if timeout then - cfg.connection_timeout = timeout - else - die "Argument error: --timeout expects a numeric argument." - end + if not args.command then + util.printout(parser:get_help()) + os.exit(cmd.errorcodes.OK) end - local command - if flags["help"] or #nonflags == 0 then - command = "help" - else - command = table.remove(nonflags, 1) + if args.timeout then -- setting it in the config file will kick-in earlier in the process + cfg.connection_timeout = args.timeout end - command = command:gsub("-", "_") - if command == "config" then - if nonflags[1] == "lua_version" and nonflags[2] then - flags["lua-version"] = nonflags[2] - elseif nonflags[1] == "lua_dir" and nonflags[2] then - flags["lua-dir"] = nonflags[2] + if args.command == "config" then + if args.key == "lua_version" and args.value then + args.lua_version = args.value + elseif args.key == "lua_dir" and args.value then + args.lua_dir = args.value end end - - if flags["deps-mode"] and not deps.check_deps_mode_flag(flags["deps-mode"]) then - die("Invalid entry for --deps-mode.") - end ----------------------------------------------------------------------------- - local lua_found, err = init_config(flags) + local lua_found, err = init_config(args) if err then die(err) end ----------------------------------------------------------------------------- - if flags["version"] then - util.printout(program.." "..cfg.program_version) - util.printout(description) - util.printout() - os.exit(cmd.errorcodes.OK) - end - - fs.init() - -- if the Lua interpreter wasn't explicitly found before cfg.init, -- try again now. if not lua_found then @@ -423,13 +500,7 @@ function cmd.run_command(description, commands, external_namespace, ...) cfg.project_dir = fs.absolute_name(cfg.project_dir) end - for _, module_name in ipairs(fs.modules(external_namespace)) do - if not commands[module_name] then - commands[module_name] = external_namespace.."."..module_name - end - end - - if flags["verbose"] then + if args.verbose then cfg.verbose = true fs.verbose() end @@ -438,24 +509,22 @@ function cmd.run_command(description, commands, external_namespace, ...) die("Current directory does not exist. Please run LuaRocks from an existing directory.") end - ok, err = process_tree_flags(flags, cfg.project_dir) + local ok, err = process_tree_flags(args, cfg.project_dir) if not ok then die(err) end - ok, err = process_server_flags(flags) + ok, err = process_server_flags(args) if not ok then die(err) end - if flags["only-sources"] then - cfg.only_sources_from = flags["only-sources"] + if args.only_sources then + cfg.only_sources_from = args.only_sources end - if command ~= "help" then - for k, v in pairs(cmdline_vars) do - cfg.variables[k] = v - end + for k, v in pairs(cmdline_vars) do + cfg.variables[k] = v end -- if running as superuser, use system cache dir @@ -463,22 +532,15 @@ function cmd.run_command(description, commands, external_namespace, ...) cfg.local_cache = dir.path(fs.system_cache_dir(), "luarocks") end - if commands[command] then - local cmd_mod = require(commands[command]) - local call_ok, ok, err, exitcode = xpcall(function() - if command == "help" then - return cmd_mod.command(description, commands, unpack(nonflags)) - else - return cmd_mod.command(flags, unpack(nonflags)) - end - end, error_handler) - if not call_ok then - die(ok, cmd.errorcodes.CRASH) - elseif not ok then - die(err, exitcode) - end - else - die("Unknown command: "..command) + local cmd_mod = cmd_modules[args.command] + local call_ok, ok, err, exitcode = xpcall(function() + return cmd_mod.command(args) + end, error_handler) + + if not call_ok then + die(ok, cmd.errorcodes.CRASH) + elseif not ok then + die(err, exitcode) end util.run_scheduled_functions() end diff --git a/src/luarocks/cmd/help.lua b/src/luarocks/cmd/help.lua deleted file mode 100644 index b3d937e1..00000000 --- a/src/luarocks/cmd/help.lua +++ /dev/null @@ -1,139 +0,0 @@ - ---- Module implementing the LuaRocks "help" command. --- This is a generic help display module, which --- uses a global table called "commands" to find commands --- to show help for; each command should be represented by a --- table containing "help" and "help_summary" fields. -local help = {} - -local util = require("luarocks.util") -local cfg = require("luarocks.core.cfg") -local dir = require("luarocks.dir") -local fs = require("luarocks.fs") - -local program = util.this_program("luarocks") - -help.help_summary = "Help on commands. Type '"..program.." help ' for more." - -help.help_arguments = "[]" -help.help = [[ - is the command to show help for. -]] - -local function print_banner() - util.printout("\nLuaRocks "..cfg.program_version..", the Lua package manager") -end - -local function print_section(section) - util.printout("\n"..section) -end - -local function get_status(status) - if status then - return "ok" - else - return "not found" - end -end - ---- Driver function for the "help" command. --- @param command string or nil: command to show help for; if not --- given, help summaries for all commands are shown. --- @return boolean or (nil, string): true if there were no errors --- or nil and an error message if an invalid command was requested. -function help.command(description, commands, command) - assert(type(description) == "string") - assert(type(commands) == "table") - - if not command then - print_banner() - print_section("NAME") - util.printout("\t"..program..[[ - ]]..description) - print_section("SYNOPSIS") - util.printout("\t"..program..[[ [] [VAR=VALUE]... [] ]]) - print_section("GENERAL OPTIONS") - util.printout([[ - These apply to all commands, as appropriate: - - --dev Enable the sub-repositories in rocks servers - for rockspecs of in-development versions - --server= Fetch rocks/rockspecs from this server - (takes priority over config file) - --only-server= Fetch rocks/rockspecs from this server only - (overrides any entries in the config file) - --only-sources= Restrict downloads to paths matching the - given URL. - --lua-dir= Which Lua installation to use. - --lua-version= Which Lua version to use. - --tree= Which tree to operate on. - --local Use the tree in the user's home directory. - To enable it, see ']]..program..[[ help path'. - --global Use the system tree when `local_by_default` is `true`. - --verbose Display verbose output of commands executed. - --timeout= Timeout on network operations, in seconds. - 0 means no timeout (wait forever). - Default is ]]..tostring(cfg.connection_timeout)..[[.]]) - print_section("VARIABLES") - util.printout([[ - Variables from the "variables" table of the configuration file - can be overridden with VAR=VALUE assignments.]]) - print_section("COMMANDS") - for name, modname in util.sortedpairs(commands) do - local cmd = require(modname) - util.printout("", name) - util.printout("\t", cmd.help_summary) - end - print_section("CONFIGURATION") - util.printout("\tLua version: " .. cfg.lua_version) - local ljv = util.get_luajit_version() - if ljv then - util.printout("\tLuaJIT version: " .. ljv) - end - util.printout() - util.printout("\tConfiguration files:") - local conf = cfg.config_files - util.printout("\t\tSystem : ".. fs.absolute_name(conf.system.file) .. " (" .. get_status(conf.system.found) ..")") - if conf.user.file then - util.printout("\t\tUser : ".. fs.absolute_name(conf.user.file) .. " (" .. get_status(conf.user.found) ..")") - else - util.printout("\t\tUser : disabled in this LuaRocks installation.") - end - if conf.project then - util.printout("\t\tProject : ".. fs.absolute_name(conf.project.file) .. " (" .. get_status(conf.project.found) ..")") - end - util.printout() - util.printout("\tRocks trees in use: ") - for _, tree in ipairs(cfg.rocks_trees) do - if type(tree) == "string" then - util.printout("\t\t"..fs.absolute_name(tree)) - else - local name = tree.name and " (\""..tree.name.."\")" or "" - util.printout("\t\t"..fs.absolute_name(tree.root)..name) - end - end - util.printout() - else - command = command:gsub("-", "_") - local cmd = commands[command] and require(commands[command]) - if cmd then - local arguments = cmd.help_arguments or "" - print_banner() - print_section("NAME") - util.printout("\t"..program.." "..command.." - "..cmd.help_summary) - print_section("SYNOPSIS") - util.printout("\t"..program.." "..command.." "..arguments) - print_section("DESCRIPTION") - util.printout("",(cmd.help:gsub("\n","\n\t"):gsub("\n\t$",""))) - print_section("SEE ALSO") - if cmd.help_see_also then - util.printout(cmd.help_see_also) - end - util.printout("","'"..program.." help' for general options and configuration.\n") - else - return nil, "Unknown command: "..command - end - end - return true -end - -return help diff --git a/src/luarocks/cmd/init.lua b/src/luarocks/cmd/init.lua index 60aa4f82..fc14baf6 100644 --- a/src/luarocks/cmd/init.lua +++ b/src/luarocks/cmd/init.lua @@ -10,27 +10,30 @@ local util = require("luarocks.util") local persist = require("luarocks.persist") local write_rockspec = require("luarocks.cmd.write_rockspec") -init.help_summary = "Initialize a directory for a Lua project using LuaRocks." -init.help_arguments = "[ []]" -init.help = [[ - is the project name. - is an optional project version. - ---reset Delete .luarocks/config-5.x.lua and ./lua - and generate new ones. - -Options for specifying rockspec data: - ---license="" A license string, such as "MIT/X11" or "GNU GPL v3". ---summary="" A short one-line description summary. ---detailed="" A longer description string. ---homepage= Project homepage. ---lua-versions= Supported Lua versions. Accepted values are "5.1", "5.2", - "5.3", "5.1,5.2", "5.2,5.3", or "5.1,5.2,5.3". ---rockspec-format= Rockspec format version, such as "1.0" or "1.1". ---lib=[,] A comma-separated list of libraries that C files need to - link to. -]] +function init.add_to_parser(parser) + local cmd = parser:command("init", "Initialize a directory for a Lua project using LuaRocks.", util.see_also()) + :add_help(false) + + cmd:argument("name", "The project name."):args("?") + cmd:argument("version", "An optional project version."):args("?") + cmd:flag("--reset", "Delete .luarocks/config-5.x.lua and ./lua and generate new ones.") + + cmd:group("Options for specifying rockspec data", + cmd:option("--license", 'A license string, such as "MIT/X11" or "GNU GPL v3".') + :argname(""), + cmd:option("--summary", "A short one-line description summary.") + :argname(""), + cmd:option("--detailed", "A longer description string.") + :argname(""), + cmd:option("--homepage", "Project homepage.") + :argname(""), + cmd:option("--lua-versions", "Supported Lua versions. Accepted values are ".. + '"5.1", "5.2", "5.3", "5.1,5.2", "5.2,5.3", or "5.1,5.2,5.3".'), + cmd:option("--rockspec-format", 'Rockspec format version, such as "1.0" or "1.1".') + :argname(""), + cmd:option("--lib", "A comma-separated list of libraries that C files need to link to.") + :argname("")) +end local function write_gitignore(entries) local gitignore = "" @@ -53,10 +56,11 @@ end --- Driver function for "init" command. -- @return boolean: True if succeeded, nil on errors. -function init.command(flags, name, version) +function init.command(args) local pwd = fs.current_dir() + local name = args.name if not name then name = dir.base_name(pwd) if name == "/" then @@ -84,7 +88,7 @@ function init.command(flags, name, version) end if not has_rockspec then - local ok, err = write_rockspec.command(flags, name, version or "dev", pwd) + local ok, err = write_rockspec.command(args, name, args.version or "dev", pwd) if not ok then util.printerr(err) end @@ -101,7 +105,7 @@ function init.command(flags, name, version) fs.make_dir(".luarocks") local config_file = ".luarocks/config-" .. cfg.lua_version .. ".lua" - if flags["reset"] then + if args.reset then fs.delete(lua_wrapper) fs.delete(config_file) end diff --git a/src/luarocks/cmd/lint.lua b/src/luarocks/cmd/lint.lua index c9ea45ea..433eed84 100644 --- a/src/luarocks/cmd/lint.lua +++ b/src/luarocks/cmd/lint.lua @@ -7,24 +7,22 @@ local util = require("luarocks.util") local download = require("luarocks.download") local fetch = require("luarocks.fetch") -lint.help_summary = "Check syntax of a rockspec." -lint.help_arguments = "" -lint.help = [[ -This is a utility function that checks the syntax of a rockspec. - -It returns success or failure if the text of a rockspec is -syntactically correct. -]] - -function lint.command(flags, input) - if not input then - return nil, "Argument missing. "..util.see_help("lint") - end - - local filename = input - if not input:match(".rockspec$") then +function lint.add_to_parser(parser) + local cmd = parser:command("lint", "Check syntax of a rockspec.\n\n".. + "Returns success if the text of the rockspec is syntactically correct, else failure.", + util.see_also()) + :summary("Check syntax of a rockspec.") + :add_help(false) + + cmd:argument("rockspec", "The rockspec to check.") +end + +function lint.command(args) + + local filename = args.rockspec + if not filename:match(".rockspec$") then local err - filename, err = download.download("rockspec", input:lower()) + filename, err = download.download("rockspec", filename:lower()) if not filename then return nil, err end diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua index 6caba8cd..60cfb3d8 100644 --- a/src/luarocks/util.lua +++ b/src/luarocks/util.lua @@ -77,162 +77,6 @@ function util.matchquote(s) return (s:gsub("[?%-+*%[%].%%()$^]","%%%1")) end ---- List of supported arguments. --- Arguments that take no parameters are marked with the boolean true. --- Arguments that take a parameter are marked with a descriptive string. --- Arguments that may take an empty string are described in quotes, --- (as in the value for --detailed=""). --- For all other string values, it means the parameter is mandatory. -local supported_flags = { - ["all"] = true, - ["api-key"] = "", - ["append"] = true, - ["arch"] = "", - ["bin"] = true, - ["binary"] = true, - ["branch"] = "", - ["build-deps"] = true, - ["debug"] = true, - ["deps"] = true, - ["deps-mode"] = "", - ["detailed"] = "\"\"", - ["dev"] = true, - ["dir"] = "", - ["force"] = true, - ["force-fast"] = true, - ["from"] = "", - ["global"] = true, - ["help"] = true, - ["home"] = true, - ["homepage"] = "\"\"", - ["index"] = true, - ["issues"] = true, - ["json"] = true, - ["keep"] = true, - ["labels"] = true, - ["lib"] = "", - ["license"] = "\"\"", - ["list"] = true, - ["local"] = true, - ["local-tree"] = true, - ["lr-bin"] = true, - ["lr-cpath"] = true, - ["lr-path"] = true, - ["lua-dir"] = "", - ["lua-version"] = "", - ["lua-versions"] = "", - ["lua-ver"] = true, - ["lua-incdir"] = true, - ["lua-libdir"] = true, - ["modules"] = true, - ["mversion"] = true, - ["namespace"] = "", - ["no-bin"] = true, - ["no-doc"] = true, - ["no-refresh"] = true, - ["nodeps"] = true, - ["old-versions"] = true, - ["only-deps"] = true, - ["only-from"] = "", - ["only-server"] = "", - ["only-sources"] = "", - ["only-sources-from"] = "", - ["outdated"] = true, - ["output"] = "", - ["pack-binary-rock"] = true, - ["porcelain"] = true, - ["project-tree"] = "", - ["quick"] = true, - ["reset"] = true, - ["rock-dir"] = true, - ["rock-license"] = true, - ["rock-namespace"] = true, - ["rock-tree"] = true, - ["rock-trees"] = true, - ["rockspec"] = true, - ["rockspec-format"] = "", - ["scope"] = "", - ["server"] = "", - ["sign"] = true, - ["skip-pack"] = true, - ["source"] = true, - ["summary"] = "\"\"", - ["system-config"] = true, - ["tag"] = "", - ["test-type"] = "", - ["temp-key"] = "", - ["timeout"] = "", - ["to"] = "", - ["tree"] = "", - ["unset"] = true, - ["user-config"] = true, - ["verbose"] = true, - ["verify"] = true, - ["version"] = true, -} - ---- Extract flags from an arguments list. --- Given string arguments, extract flag arguments into a flags set. --- For example, given "foo", "--tux=beep", "--bla", "bar", "--baz", --- it would return the following: --- {["bla"] = true, ["tux"] = "beep", ["baz"] = true}, "foo", "bar". -function util.parse_flags(...) - local args = {...} - local flags = {} - local i = 1 - local out = {} - local state = "initial" - while i <= #args do - local flag = args[i]:match("^%-%-(.*)") - if state == "initial" and flag == "" then - state = "ignore_flags" - elseif state == "initial" and flag then - local var,val = flag:match("([a-z_%-]*)=(.*)") - if val then - local vartype = supported_flags[var] - if type(vartype) == "string" then - if val == "" and vartype:sub(1,1) ~= '"' then - return { ERROR = "Invalid argument: parameter to flag --"..var.."="..vartype.." cannot be empty." } - end - flags[var] = val - else - if vartype then - return { ERROR = "Invalid argument: flag --"..var.." does not take an parameter." } - else - return { ERROR = "Invalid argument: unknown flag --"..var.."." } - end - end - else - local var = flag - local vartype = supported_flags[var] - if type(vartype) == "string" then - i = i + 1 - local val = args[i] - if not val then - return { ERROR = "Invalid argument: flag --"..var.."="..vartype.." expects a parameter." } - end - if val:match("^%-%-.*") then - return { ERROR = "Invalid argument: flag --"..var.."="..vartype.." expects a parameter (if you really want to pass "..val.." as an argument to --"..var..", use --"..var.."="..val..")." } - else - if val == "" and vartype:sub(1,1) ~= '"' then - return { ERROR = "Invalid argument: parameter to flag --"..var.."="..vartype.." cannot be empty." } - end - flags[var] = val - end - elseif vartype == true then - flags[var] = true - else - return { ERROR = "Invalid argument: unknown flag --"..var.."." } - end - end - elseif state == "ignore_flags" or (state == "initial" and not flag) then - table.insert(out, args[i]) - end - i = i + 1 - end - return flags, unpack(out) -end - local var_format_pattern = "%$%((%a[%a%d_]+)%)" -- Check if a set of needed variables are referenced @@ -394,6 +238,14 @@ function util.see_help(command, program) return "See '"..util.this_program(program or "luarocks")..' help'..(command and " "..command or "").."'." end +function util.see_also(text) + local see_also = "See also:\n" + if text then + see_also = see_also..text.."\n" + end + return see_also.." '"..util.this_program("luarocks").." help' for general options and configuration." +end + function util.announce_install(rockspec) local cfg = require("luarocks.core.cfg") local path = require("luarocks.path") -- cgit v1.2.3-55-g6feb