Unify Bash's and zsh's programmable completion (#1002)

* Unify Bash's and zsh's programmable completion

* Perform autocompletion for short options

* Use SDKMAN_CANDIDATES for resolving candidates

* Handle `read` edge case
This commit is contained in:
Oliver Weiler
2021-10-25 13:35:30 +02:00
committed by GitHub
parent 4bf5b70f8a
commit bc7fd662dc
4 changed files with 21 additions and 87 deletions

View File

@@ -1,11 +1,11 @@
#!/usr/bin/bash
_sdk() {
local -r previous_word="${COMP_WORDS[COMP_CWORD - 1]}"
local -r current_word="${COMP_WORDS[COMP_CWORD]}"
local -r previous_word=${COMP_WORDS[COMP_CWORD - 1]}
local -r current_word=${COMP_WORDS[COMP_CWORD]}
if ((COMP_CWORD == 3)); then
local -r before_previous_word="${COMP_WORDS[COMP_CWORD - 2]}"
local -r before_previous_word=${COMP_WORDS[COMP_CWORD - 2]}
__sdkman_complete_candidate_version "$before_previous_word" "$previous_word" "$current_word"
@@ -25,19 +25,18 @@ __sdkman_complete_command() {
sdk)
candidates=("install" "uninstall" "list" "use" "config" "default" "home" "env" "current" "upgrade" "version" "broadcast" "help" "offline" "selfupdate" "update" "flush")
;;
current|default|home|uninstall|upgrade|use)
current|c|default|d|home|h|uninstall|rm|upgrade|ug|use|u)
local -r candidate_paths=("${SDKMAN_CANDIDATES_DIR}"/*)
for candidate_path in "${candidate_paths[@]}"; do
candidates+=(${candidate_path##*/})
candidates+=("${candidate_path##*/}")
done
;;
install|list)
local -r all_candidates=$(curl --silent "${SDKMAN_CANDIDATES_API}/candidates/all")
IFS=',' read -r -a candidates <<< "$all_candidates"
install|i|list|ls)
candidates=${SDKMAN_CANDIDATES[@]}
;;
env)
candidates=("init install clear")
env|e)
candidates=("init" "install" "clear")
;;
offline)
candidates=("enable" "disable")
@@ -61,18 +60,19 @@ __sdkman_complete_candidate_version() {
local -a candidates
case $command in
use|default|home|uninstall)
default|d|home|h|uninstall|rm|use|u)
local -r version_paths=("${SDKMAN_CANDIDATES_DIR}/${candidate}"/*)
for version_path in "${version_paths[@]}"; do
[[ $version_path = *current ]] && continue
candidates+=(${version_path##*/})
candidates+=("${version_path##*/}")
done
;;
install)
local -r all_candidate_versions=$(curl --silent "${SDKMAN_CANDIDATES_API}/candidates/$candidate/${SDKMAN_PLATFORM}/versions/all")
IFS=',' read -r -a candidates <<< "$all_candidate_versions"
install|i)
while IFS= read -r -d, version || [[ -n "$version" ]]; do
candidates+=("$version")
done <<< "$(curl --silent "${SDKMAN_CANDIDATES_API}/candidates/$candidate/${SDKMAN_PLATFORM}/versions/all")"
;;
esac

View File

@@ -1,61 +0,0 @@
#!/usr/bin/zsh
_sdk() {
case "${CURRENT}" in
2)
compadd -X $'Commands:\n' -- "${${(Mk)functions[@]:#__sdk_*}[@]#__sdk_}"
compadd -n rm
;;
3)
case "${words[2]}" in
l|ls|list|i|install)
compadd -X $'Candidates:\n' -- "${SDKMAN_CANDIDATES[@]}"
;;
ug|upgrade|h|home|c|current|u|use|d|default|rm|uninstall)
compadd -X $'Installed Candidates:\n' -- "${${(u)${(f)$(find -L -- "${SDKMAN_CANDIDATES_DIR}" -mindepth 2 -maxdepth 2 -type d)}[@]:h}[@]:t}"
;;
e|env)
compadd init install clear
;;
config)
;;
offline)
compadd enable disable
;;
selfupdate)
compadd force
;;
flush)
compadd archives broadcast tmp version
;;
esac
;;
4)
case "${words[2]}" in
i|install)
setopt localoptions kshglob
if [[ "${words[3]}" == 'java' ]]; then
compadd -X $'Installable Versions of java:\n' -- "${${${${${(f)$(__sdkman_list_versions "${words[3]}")}[@]:5:-4}[@]:#* | (local only|installed ) | *}[@]##* | | }[@]%%+( )}"
else
compadd -X "Installable Versions of ${words[3]}:"$'\n' -- "${${(z)${(M)${(f)${$(__sdkman_list_versions "${words[3]}")//[*+>]+( )/-}}[@]:# *}[@]}[@]:#-*}"
fi
;;
h|home|u|use|d|default|rm|uninstall)
compadd -X "Installed Versions of ${words[3]}:"$'\n' -- "${${(f)$(find -L -- "${SDKMAN_CANDIDATES_DIR}/${words[3]}" -mindepth 1 -maxdepth 1 -type d -not -name 'current')}[@]:t}"
;;
esac
;;
5)
case "${words[2]}" in
i|install)
_files -X "Path to Local Installation of ${words[3]} ${words[4]}:"$'\n' -/
;;
esac
;;
esac
}
compdef _sdk sdk
# Set 'sdkman_auto_complete' to 'true' in .sdkman/etc/config to enable completion

View File

@@ -190,7 +190,9 @@ if [[ "$sdkman_auto_complete" == 'true' ]]; then
compinit
fi
fi
source "${SDKMAN_DIR}/contrib/completion/zsh/sdk"
autoload -U bashcompinit
bashcompinit
source "${SDKMAN_DIR}/contrib/completion/bash/sdk"
__sdkman_echo_debug "ZSH completion script loaded..."
elif [[ "$bash_shell" == 'true' ]]; then
source "${SDKMAN_DIR}/contrib/completion/bash/sdk"

View File

@@ -4,14 +4,11 @@ import sdkman.support.SdkmanEnvSpecification
class CompletionSpec extends SdkmanEnvSpecification {
static final String CANDIDATES_API = "http://localhost:8080/2"
static final String BROADCAST_API_LATEST_ID_ENDPOINT = "$CANDIDATES_API/broadcast/latest/id"
static final String CANDIDATES_ALL_ENDPOINT = "$CANDIDATES_API/candidates/all"
def "should complete the list of commands"() {
given:
bash = sdkmanBashEnvBuilder
.withVersionCache("x.y.z")
.withConfiguration("sdkman_auto_complete", "true")
.build()
@@ -28,11 +25,8 @@ class CompletionSpec extends SdkmanEnvSpecification {
def "should complete the list of candidates"() {
given:
curlStub.primeWith(BROADCAST_API_LATEST_ID_ENDPOINT, "echo dbfb025be9f97fda2052b5febcca0155")
.primeWith(CANDIDATES_ALL_ENDPOINT, "echo java,groovy")
bash = sdkmanBashEnvBuilder
.withVersionCache("x.y.z")
.withCandidates(["java", "groovy"])
.withConfiguration("sdkman_auto_complete", "true")
.build()
@@ -41,7 +35,7 @@ class CompletionSpec extends SdkmanEnvSpecification {
when:
bash.execute("COMP_CWORD=2; COMP_WORDS=(sdk install); _sdk")
bash.execute("echo \${COMPREPLY[@]}")
bash.execute('echo "\${COMPREPLY[@]}"')
then:
bash.output.contains("java groovy")
@@ -55,7 +49,6 @@ class CompletionSpec extends SdkmanEnvSpecification {
unameStub.forKernel("Darwin").forMachine("x86_64")
bash = sdkmanBashEnvBuilder
.withVersionCache("x.y.z")
.withConfiguration("sdkman_auto_complete", "true")
.withUnameStub(unameStub)
.build()
@@ -65,7 +58,7 @@ class CompletionSpec extends SdkmanEnvSpecification {
when:
bash.execute("COMP_CWORD=3; COMP_WORDS=(sdk install java); _sdk")
bash.execute("echo \${COMPREPLY[@]}")
bash.execute('echo "\${COMPREPLY[@]}"')
then:
bash.output.contains("16.0.1.hs-adpt 17.0.0-tem")