summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOpportunityLiu <[email protected]>2020-01-21 19:30:02 +0800
committerOpportunityLiu <[email protected]>2020-01-21 19:30:02 +0800
commit19e11d5150fd2496a74f2e461673698e591be008 (patch)
tree5630de74f6ce520740bdc370432bef142a4ccdde
parent504f92e23ac9d6615879ec3037c50d24cccd7bd0 (diff)
fix bash complete
-rw-r--r--scripts/register-completions.sh8
-rw-r--r--xmake/modules/private/utils/complete.lua143
2 files changed, 90 insertions, 61 deletions
diff --git a/scripts/register-completions.sh b/scripts/register-completions.sh
index 9b00e715b..e274605b2 100644
--- a/scripts/register-completions.sh
+++ b/scripts/register-completions.sh
@@ -5,21 +5,21 @@ if [[ "$SHELL" = */zsh ]]; then
# zsh parameter completion for xmake
_xmake_zsh_complete()
{
- local completions=("$(XMAKE_SKIP_HISTORY=1 xmake lua --root private.utils.complete 0 nospace "$words")")
+ local completions=("$(XMAKE_SKIP_HISTORY=1 XMAKE_ROOT=y xmake lua private.utils.complete 0 nospace "$words")")
reply=( "${(ps:\n:)completions}" )
}
compctl -f -S "" -K _xmake_zsh_complete xmake
elif [[ "$SHELL" = */bash ]]; then
- # bash parameter completion for xmake
+ # bash parameter completion for xmake
_xmake_bash_complete()
{
local word=${COMP_WORDS[COMP_CWORD]}
local completions
- completions="$(XMAKE_SKIP_HISTORY=1 xmake lua --root private.utils.complete "${COMP_POINT}" "nospace-nokey" "${COMP_LINE}" 2>/dev/null)"
+ completions="$(XMAKE_SKIP_HISTORY=1 XMAKE_ROOT=y xmake lua private.utils.complete "${COMP_POINT}" "nospace-nokey" "${COMP_LINE}")"
if [ $? -ne 0 ]; then
completions=""
fi
- COMPREPLY=( $(compgen -W "$completions" -- "$word") )
+ COMPREPLY=( $(compgen -W "$completions") )
}
complete -o default -o nospace -F _xmake_bash_complete xmake
fi
diff --git a/xmake/modules/private/utils/complete.lua b/xmake/modules/private/utils/complete.lua
index 8b8da395a..d06aef29a 100644
--- a/xmake/modules/private/utils/complete.lua
+++ b/xmake/modules/private/utils/complete.lua
@@ -44,6 +44,8 @@ end
function _complete_task(tasks, name)
local has_candidate = false
+
+ -- match tasks starts with name first
for k, _ in pairs(tasks) do
if k:startswith(name) then
_print_candidate(true, "%s", k)
@@ -51,13 +53,11 @@ function _complete_task(tasks, name)
end
end
- if name == "" then
- return has_candidate
- end
+ if has_candidate then return true end
+ -- not found? keep searching
for k, _ in pairs(tasks) do
- -- not startswith
- if k:find(name, 2, true) then
+ if k:find(name, 1, true) then
_print_candidate(true, "%s", k)
has_candidate = true
end
@@ -65,81 +65,84 @@ function _complete_task(tasks, name)
return has_candidate
end
-function _complete_option_kv(options, current, completing)
+-- complete values of kv
+function _complete_option_kv_v(options, current, completing, name, value)
- local name, value
- if completing == "-" or completing == "--" then
- name = ""
- elseif completing:startswith("--") then
- local parg = cli.parsev({completing})[1]
- if parg.type == "option" then
- name, value = parg.key, parg.value
- elseif parg.type == "flag" then
- name = parg.key
+ -- find completion option
+ local opt
+ for _, v in ipairs(options) do
+ if v[3] == "kv" and (v[1] == name or v[2] == name) then
+ opt = v
+ break
end
- elseif completing:startswith("-") then
- -- search full names only
- return true
+ end
+ if not opt then
+ return false
end
- if value then
- -- complete values
+ -- show candidates of values
+ local values = opt.values
+ if type(values) == "function" then
+ values = values(value, current)
+ end
+ if values == nil and type(opt[4]) == "boolean" then
+ values = { "yes", "no" }
+ -- ignore existing input
+ value = ""
+ end
- -- find completion option
- local opt
- for _, v in ipairs(options) do
- if v[3] == "kv" and (v[1] == name or v[2] == name) then
- opt = v
- break
+ local has_candidate = false
+ -- match values starts with value first
+ for _, v in ipairs(values) do
+ if tostring(v):startswith(value) then
+ has_candidate = true
+ if no_key then
+ _print_candidate(true, "%s", v)
+ else
+ _print_candidate(true, "--%s=%s", name, v)
end
end
- if not opt then
- return false
- end
+ end
+ if has_candidate then return true end
- -- show candidates of values
- local values = opt.values
- if type(values) == "function" then
- values = values(value, current)
- end
- if values == nil and type(opt[4]) == "boolean" then
- values = { "yes", "no" }
- -- ignore existing input
- value = ""
- end
- for _, v in ipairs(values) do
- if tostring(v):startswith(value) then
- if no_key then
- _print_candidate(true, "%s", v)
- else
- _print_candidate(true, "--%s=%s", name, v)
- end
+ -- not found? keep searching
+ for _, v in ipairs(values) do
+ if tostring(v):find(value, 1 , true) then
+ if no_key then
+ _print_candidate(true, "%s", v)
+ else
+ _print_candidate(true, "--%s=%s", name, v)
end
end
- return true
end
+ -- whether any candidates has been found, finish complete since we don't have more info
+ return true
+end
+
+-- complete keys of kv
+function _complete_option_kv_k(options, current, completing, name)
+
local opcandi = table.new(10, 0)
for _, v in ipairs(options) do
if current[v[2]] == nil then
- if v[3] == "kv" or v[3] == "k" then table.insert(opcandi, v) end
+ if (v[3] == "kv" or v[3] == "k") and v[2] then table.insert(opcandi, v) end
end
end
+ local has_candidate = false
+ -- match keys starts with name first
for _, v in ipairs(opcandi) do
- -- startswith
if v[2]:startswith(name) then
_print_candidate((v[3] == "k"), (v[3] == "k") and "--%s" or "--%s=", v[2])
end
end
- if name == "" then
- return true
- end
+ if has_candidate then return true end
+ -- not found? keep searching
for _, v in ipairs(opcandi) do
- -- not startswith
- if v[2]:find(name, 2, true) then
+ if v[2]:find(name, 1, true) then
_print_candidate((v[3] == "k"), (v[3] == "k") and "--%s" or "--%s=", v[2])
end
end
@@ -147,6 +150,32 @@ function _complete_option_kv(options, current, completing)
return true
end
+function _complete_option_kv(options, current, completing)
+
+ local name, value
+ if completing == "-" or completing == "--" then
+ name = ""
+ elseif completing:startswith("--") then
+ local parg = cli.parsev({completing})[1]
+ if parg.type == "option" then
+ name, value = parg.key, parg.value
+ elseif parg.type == "flag" then
+ name = parg.key
+ end
+ elseif completing:startswith("-") then
+ -- search full names only
+ return true
+ end
+
+ if value then
+ -- complete values
+ return _complete_option_kv_v(options, current, completing, name, value)
+ else
+ -- complete keys
+ return _complete_option_kv_k(options, current, completing, name)
+ end
+end
+
function _complete_option_v(options, current, completing)
-- find completion option
local opt
@@ -204,12 +233,12 @@ function _complete_option(options, segs, completing)
-- current context is wrong
if not reenter and (current_options.file or current_options.project) then
- local args = {"lua", "--root", "private.utils.complete", tostring(position), raw_config .. "-reenter", table.unpack(raw_words) }
+ local args = {"lua", "private.utils.complete", tostring(position), raw_config .. "-reenter", table.unpack(raw_words) }
if current_options.file then
- table.insert(args, 3, "--file=" .. current_options.file)
+ table.insert(args, 2, "--file=" .. current_options.file)
end
if current_options.project then
- table.insert(args, 3, "--project=" .. current_options.project)
+ table.insert(args, 2, "--project=" .. current_options.project)
end
os.execv("xmake", args)
return true