diff options
| author | OpportunityLiu <[email protected]> | 2020-01-21 19:30:02 +0800 |
|---|---|---|
| committer | OpportunityLiu <[email protected]> | 2020-01-21 19:30:02 +0800 |
| commit | 19e11d5150fd2496a74f2e461673698e591be008 (patch) | |
| tree | 5630de74f6ce520740bdc370432bef142a4ccdde | |
| parent | 504f92e23ac9d6615879ec3037c50d24cccd7bd0 (diff) | |
fix bash complete
| -rw-r--r-- | scripts/register-completions.sh | 8 | ||||
| -rw-r--r-- | xmake/modules/private/utils/complete.lua | 143 |
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 |
