summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOpportunity <[email protected]>2020-01-15 14:58:36 +0800
committerOpportunity <[email protected]>2020-01-15 14:58:36 +0800
commitd7662a8916400389fca579772bfdaedadd5e640e (patch)
treedf62285c16883e1ac98101507cf90178b7c78941
parentf4e30b5e7879d4dbfbe4424f5f9156cb6cfdaf50 (diff)
Improve basic parse
-rw-r--r--xmake/core/base/option.lua64
-rw-r--r--xmake/core/base/task.lua56
-rw-r--r--xmake/core/main.lua44
3 files changed, 95 insertions, 69 deletions
diff --git a/xmake/core/base/option.lua b/xmake/core/base/option.lua
index 8e5377667..c02a29659 100644
--- a/xmake/core/base/option.lua
+++ b/xmake/core/base/option.lua
@@ -183,40 +183,35 @@ function option.init(menu)
local context = option.save()
assert(context)
- -- parse _ARGV
- local argv = table.copy(xmake._ARGV)
- local task_arg = "build"
- if argv[1] and not argv[1]:startswith('-') then
- -- regard it as command name
- task_arg = argv[1]
- table.remove(argv, 1)
- end
+ -- check command
+ if xmake._COMMAND then
- -- find the current task
- for taskname, taskinfo in pairs(main.tasks) do
+ -- find the current task
+ for taskname, taskinfo in pairs(main.tasks) do
- -- ok?
- if taskname == task_arg or taskinfo.shortname == task_arg then
- -- save this task
- context.taskname = taskname
- break
+ -- ok?
+ if taskname == xmake._COMMAND or taskinfo.shortname == xmake._COMMAND then
+ -- save this task
+ context.taskname = taskname
+ break
+ end
end
- end
- -- not found?
- if not context.taskname or not menu[context.taskname] then
+ -- not found?
+ if not context.taskname or not menu[context.taskname] then
- -- print the main menu
- option.show_main()
+ -- print the main menu
+ option.show_main()
- -- invalid task
- return false, "invalid task: " .. task_arg
+ -- invalid task
+ return false, "invalid task: " .. xmake._COMMAND
+ end
end
local options = table.wrap(option.taskmenu().options)
-- parse remain parts
- local results, err = option.parse(argv, options, {populate_defaults = false})
+ local results, err = option.parse(xmake._COMMAND_ARGV, options, { populate_defaults = false })
if not results then
option.show_menu(context.taskname)
return false, err
@@ -281,7 +276,11 @@ function option.parse(argv, options, opt)
if match_opt and ((arg.type == "option" and match_opt[3] ~= "k") or (arg.type == "flag" and match_opt[3] == "k")) then
results[match_opt[2] or match_opt[1]] = option.boolean(arg.value)
else
- return nil, string.format("Invalid %s: %s", arg.type, arg)
+ if opt.allow_unknown then
+ results[arg.key] = option.boolean(arg.value)
+ else
+ return nil, string.format("Invalid %s: %s", arg.type, arg)
+ end
end
elseif arg.type == "arg" then
@@ -333,6 +332,23 @@ function option.parse(argv, options, opt)
else
-- failed
+ if opt.allow_unknown then
+ if arg.key then
+ results[arg.key] = arg.value
+ else
+ -- the option
+ local o = results["$ARGS"]
+ if not o then
+ results["$ARGS"] = {}
+ o = results["$ARGS"]
+ end
+
+ -- append value
+ table.insert(o, arg.value)
+ end
+ else
+ return nil, string.format("Invalid %s: %s", arg.type, arg)
+ end
return nil, "invalid argument: " .. arg.value
end
end
diff --git a/xmake/core/base/task.lua b/xmake/core/base/task.lua
index 03b87982d..97c8cec25 100644
--- a/xmake/core/base/task.lua
+++ b/xmake/core/base/task.lua
@@ -32,6 +32,37 @@ local sandbox = require("sandbox/sandbox")
local config = require("project/config")
local sandbox_os = require("sandbox/modules/os")
+function task.common_options()
+ if not task._COMMON_OPTIONS then
+ task._COMMON_OPTIONS =
+ {
+ {'q', "quiet", "k", nil, "Quiet operation." }
+ , {'y', "yes", "k", nil, "Input yes by default if need user confirm." }
+ , {nil, "confirm", "kv", nil, "Input the given result if need user confirm.",
+ " - y|yes",
+ " - n|no",
+ " - d|def"}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information for users." }
+ , {nil, "root", "k", nil, "Allow to run xmake as root." }
+ , {'D', "diagnosis", "k", nil, "Print lots of diagnosis information (backtrace, check info ..) only for developers."
+ , "And we can append -v to get more whole information."
+ , " e.g. $ xmake -v -D"}
+ , {nil, "profile", "k", nil, "Print performance data only for developers." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+ , {}
+ , {'F', "file", "kv", nil, "Read a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Change to the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+ , {category = "action"}
+ }
+ end
+ return task._COMMON_OPTIONS
+end
+
-- the directories of tasks
function task._directories()
@@ -127,28 +158,9 @@ function task._translate_menu(menu)
-- add common options, we need avoid repeat because the main/build task will be inserted twice
if not menu._common_options then
- table.insert(options, 1, {'q', "quiet", "k", nil, "Quiet operation." })
- table.insert(options, 2, {'y', "yes", "k", nil, "Input yes by default if need user confirm." })
- table.insert(options, 3, {nil, "confirm", "kv", nil, "Input the given result if need user confirm.",
- " - y|yes",
- " - n|no",
- " - d|def"})
- table.insert(options, 4, {'v', "verbose", "k", nil, "Print lots of verbose information for users." })
- table.insert(options, 5, {nil, "root", "k", nil, "Allow to run xmake as root." })
- table.insert(options, 6, {'D', "diagnosis", "k", nil, "Print lots of diagnosis information (backtrace, check info ..) only for developers."
- , "And we can append -v to get more whole information."
- , " e.g. $ xmake -v -D"})
- table.insert(options, 7, {nil, "profile", "k", nil, "Print performance data only for developers." })
- table.insert(options, 8, {nil, "version", "k", nil, "Print the version number and exit." })
- table.insert(options, 9, {'h', "help", "k", nil, "Print this help message and exit." })
- table.insert(options, 10, {})
- table.insert(options, 11, {'F', "file", "kv", nil, "Read a given xmake.lua file." })
- table.insert(options, 12, {'P', "project", "kv", nil, "Change to the given project directory."
- , "Search priority:"
- , " 1. The Given Command Argument"
- , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
- , " 3. The Current Directory" })
- table.insert(options, 13, {category = "action"})
+ for i, v in ipairs(task.common_options()) do
+ table.insert(options, i, v)
+ end
menu._common_options = true
end
end
diff --git a/xmake/core/main.lua b/xmake/core/main.lua
index a4517d0ca..e0504a376 100644
--- a/xmake/core/main.lua
+++ b/xmake/core/main.lua
@@ -118,34 +118,32 @@ function main._find_root(projectfile)
return projectfile
end
--- the init function for main
-function main._init()
+function main._basicparse()
- local argv = table.copy(xmake._ARGV)
- if argv[1] and not argv[1]:startswith('-') then
+ -- check command
+ if xmake._ARGV[1] and not xmake._ARGV[1]:startswith('-') then
-- regard it as command name
- table.remove(argv, 1)
+ xmake._COMMAND = xmake._ARGV[1]
+ xmake._COMMAND_ARGV = table.move(xmake._ARGV, 2, -1, 1, {})
+ else
+ xmake._COMMAND_ARGV = xmake._ARGV
end
- local pargv = cli.parsev(argv)
- -- get project directory and project file from the argument option
- local opt_projectdir, opt_projectfile
- for _, arg in ipairs(pargv) do
- if arg.type == 'option' then
- if (arg.short and arg.key == 'P') or arg.key == 'project' then
- if opt_projectdir then
- return nil, "Duplicate arguments for PROJECT"
- end
- opt_projectdir = arg.value
- elseif (arg.short and arg.key == 'F') or arg.key == 'file' then
- if opt_projectfile then
- return nil, "Duplicate arguments for FILE"
- end
- opt_projectfile = arg.value
- end
- end
+ -- parse options
+ local options, err = option.parse(xmake._COMMAND_ARGV, task.common_options(), { allow_unknown = true })
+ if not options then
+ utils.error(err)
end
+ return options.project, options.file
+end
+
+-- the init function for main
+function main._init()
+
+ -- get project directory and project file from the argument option
+ local opt_projectdir, opt_projectfile = main._basicparse()
+
-- init the project directory
local projectdir = opt_projectdir or xmake._PROJECT_DIR
if projectdir and not path.is_absolute(projectdir) then
@@ -166,7 +164,7 @@ function main._init()
-- find the root project file
if not os.isfile(projectfile) or (not opt_projectdir and not opt_projectfile) then
- projectfile = main._find_root(projectfile)
+ projectfile = main._find_root(projectfile)
end
-- update and enter project