diff options
Diffstat (limited to 'Completion/Unix/Command/_gradle')
-rw-r--r-- | Completion/Unix/Command/_gradle | 96 |
1 files changed, 63 insertions, 33 deletions
diff --git a/Completion/Unix/Command/_gradle b/Completion/Unix/Command/_gradle index adf5e9aa8..280aa243f 100644 --- a/Completion/Unix/Command/_gradle +++ b/Completion/Unix/Command/_gradle @@ -1,13 +1,24 @@ #compdef gradle gradlew -local curcontext="$curcontext" ret=1 state state_descr line -local gradle_inspect=yes cache_policy tag_order -local -A opt_args -local -a gradle_group_tasks gradle_all_tasks +local -i ret=1 +local curcontext="$curcontext" state state_descr outputline +local gradle_inspect=yes gradle_buildfile cache_policy cache_name tag_order filter +local -A opt_args task_map +local -aU gradle_subprojects gradle_tasks tasks +local -a match mbegin mend -# Set the caching policy to invalidate cache if the build file is newer than the cache. _gradle_caching_policy() { - [[ $gradle_buildfile -nt $1 ]] + # Invalidate the cache if it cannot be read. + [[ -r "$1" ]] || + return 0 + + # Invalidate the cache if it's older than the build file. + [[ $gradle_buildfile -nt $1 ]] && + return + + # Invalidate the cache if it doesn't contain the required arrays. + local cache="$( < $1 )" + [[ "$cache" != *'gradle_subprojects=('*')'* || "$cache" != *'gradle_tasks=('*')'* ]] } zstyle -s ":completion:*:*:$service:*" cache-policy cache_policy || \ @@ -59,54 +70,73 @@ _arguments -C \ '(-)--stop[Stops the Gradle daemon if it is running.]' \ {-u,--no-search-upward}"[Don't search in parent folders for a settings.gradle file.]" \ '(-)'{-v,--version}'[Print version info.]' \ - {-x,--exclude-task}'[Specify a task to be excluded from execution.]:task to exclude:->alltask' \ + {-x,--exclude-task}'[Specify a task to be excluded from execution.]:task to exclude:->task' \ '*:task:->task' \ && ret=0 -if [[ $words[CURRENT] != -* ]]; then +if [[ $state == task && ! -prefix - ]]; then + # :<task> runs <task> in the root project only. + # :<subproject>:<task> is the same as <subproject>:<task> (without the leading colon). + compset -P \: + if [[ $gradle_inspect == yes ]]; then # If a build file is specified after '-b' or '--build-file', use this file. Otherwise, # default is the file 'build.gradle' in the current directory. - local gradle_buildfile=${${(v)opt_args[(i)-b|--build-file]}:-build.gradle} + gradle_buildfile=${${(v)opt_args[(i)-b|--build-file]}:-build.gradle} if [[ -f $gradle_buildfile ]]; then # Cache name is constructed from the absolute path of the build file. - local cache_name=${${gradle_buildfile:a}//[^[:alnum:]]/_} + cache_name=${${gradle_buildfile:a}//[^[:alnum:]]/_} + if _cache_invalid $cache_name || ! _retrieve_cache $cache_name; then zle -R "Generating cache from $gradle_buildfile" - local outputline - local -a match mbegin mend + # Run gradle/gradlew and retrieve possible tasks. - for outputline in ${(f)"$($service --build-file $gradle_buildfile -q tasks --all)"}; do - if [[ $outputline == [[:blank:]]#(#b)([[:alnum:]]##)' - '(*) ]]; then - # The descriptions of main tasks start at beginning of line, descriptions of - # secondary tasks are indented. - if [[ $outputline == [[:alnum:]]* ]]; then - gradle_group_tasks+=( "$match[1]:$match[2]" ) + for outputline in ${(f)"$($words[1] --build-file $gradle_buildfile -q tasks --all)"}; do + + # Tasks and subprojects each start with a lowercase letter, but whereas tasks are in camelCase, each + # subproject consists of one or more sections of kebab-case, with each section ending in a ':'. + # A subproject task is a task prefixed with a subproject and runs in that project only. + # Specifying a task without a subproject prefix runs the task in all subprojects where it exists. + # Tasks prefixed by whitespace are dependencies of the task above them and should be ignored. + if [[ $outputline == (#b)([[:lower:]][-[:lower:][:digit:]]#\:)#([[:lower:]][[:alnum:]]#)(|' - '*) ]] + then + task=$match[-2] + task_descr=${match[-1]# - } + shift -p 2 match + subproject=${(j::)match//:/'\:'} + + if [[ -n $subproject ]]; then + gradle_subprojects+=( ${subproject%'\:'} ) + task_map[$subproject$task]=$task_descr + + # We cannot count on the description of a subproject task to be representative of the task + # in general. + : ${task_map[$task]=} else - gradle_all_tasks+=( "$match[1]:$match[2]" ) + task_map[$task]=$task_descr fi fi done - _store_cache $cache_name gradle_group_tasks gradle_all_tasks + printf -v gradle_tasks '%s:%s' "${(kv@)task_map}" + _store_cache $cache_name gradle_subprojects gradle_tasks fi - if [[ $state == task ]]; then - _tags gradle_group gradle_all - while _tags; do - # Offer main tasks and secondary tasks in different tags. - _requested gradle_group && _describe 'group task' gradle_group_tasks && ret=0 - _requested gradle_all && _describe 'secondary task' gradle_all_tasks && ret=0 - (( ret )) || break - done - elif [[ $state == alltask ]]; then - # After '--exclude-task', we don't make a distinction between main tasks and - # secondary tasks. - _describe 'task' gradle_group_tasks -- gradle_all_tasks && ret=0 + if [[ $IPREFIX == *: ]] || ! zstyle -T ":completion:${curcontext}:subprojects" prefix-needed; then + _describe -t subprojects 'gradle subproject' gradle_subprojects -S \: && + ret=0 + fi + if [[ $PREFIX == *:* ]] || ! zstyle -T ":completion:${curcontext}:tasks" prefix-needed; then + tasks=( $gradle_tasks[@] ) + else + # If no subproject is specified, then filter out all subproject tasks. + tasks=( ${gradle_tasks[@]:#*'\:'*} ) fi + _describe -t tasks 'gradle task' tasks && + ret=0 fi else - _describe 'built-in task' '( + _describe -t tasks 'built-in task' '( "dependencies:Displays all dependencies declared in root project." "dependencyInsight:Displays the insight into a specific dependency in root project." "help:Displays a help message." |