zsh-workers
 help / color / mirror / code / Atom feed
* [PATCH][RFC] Improve completion of Gradle tasks
@ 2022-04-01  6:19 Marlon Richert
  2022-05-06  5:51 ` Marlon Richert
  0 siblings, 1 reply; 5+ messages in thread
From: Marlon Richert @ 2022-04-01  6:19 UTC (permalink / raw)
  To: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 16 bytes --]

See attachment.

[-- Attachment #2: 0001-Improve-completion-of-Gradle-tasks.txt --]
[-- Type: text/plain, Size: 8875 bytes --]

From 54f9073959d2dcc78f92ccb49082fb862fc76256 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlonrichert@users.noreply.github.com>
Date: Fri, 1 Apr 2022 09:15:28 +0300
Subject: [PATCH] Improve completion of Gradle tasks

* Adjust the pattern for matching tasks. The old one was too strict,
  causing it to filter out perfectly valid tasks.
* Add completion of subproject names.
* Prevent subproject tasks from overwriting the main task description.
* Require `:` prefix for showing subprojects.
* Require a subproject prefix before showing subproject tasks.
* Standardize the use of completion tags.
* Rebuild the cache if it can't be read or doesn't contain the required
  arrays.
---
 Completion/Unix/Command/_gradle | 114 +++++++++++++++++---------------
 1 file changed, 61 insertions(+), 53 deletions(-)

diff --git a/Completion/Unix/Command/_gradle b/Completion/Unix/Command/_gradle
index a1d9381cb..c1f7c05ee 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 filter=
-local -A opt_args
-local -aU gradle_group_tasks gradle_all_tasks 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,76 +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
-                    # Subproject tasks are prefixed with one or more instances of [[:alnum:]]##\:
-                    # Leaving out the prefix runs the task in all subprojects where it exists.
-                    if [[ $outputline ==
-                            [[:blank:]]#(#b)([[:alnum:]]##\:)#([[: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[-2]:$match[-1]"
-                                    "${${(j::)match[1,-2]}//:/\:}:$match[-1]"
-                            )
+
+                    # 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+=(
-                                    "${${(j::)match[1,-2]}//:/\:}:$match[-1]"
-                            )
+                            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
 
-            filter=
-            zstyle -T ":completion:${curcontext}:tasks" prefix-needed &&
-                    [[ $PREFIX != ([[:alnum:]]##\:)## ]] &&
-                            filter+="*\:*"
-            if [[ $state == task ]]; then
-                _tags gradle_group gradle_all
-                while _tags; do
-                    # Offer main tasks and secondary tasks in different tags.
-                    if _requested gradle_group; then
-                        tasks=( ${gradle_group_tasks:#$~filter} )
-                        _describe -t tasks 'group task' tasks &&
-                                ret=0
-                    fi
-                    if _requested gradle_all; then
-                        tasks=( ${gradle_all_tasks:#$~filter} )
-                        _describe -t tasks 'secondary task' tasks &&
-                                ret=0
-                    fi
-                    (( ret )) || break
-                done
-            elif [[ $state == alltask ]]; then
-                # After '--exclude-task', we don't make a distinction between main tasks and
-                # secondary tasks.
-                tasks=( ${gradle_group_tasks:#$~filter} ${gradle_all_tasks:#$~filter} )
-                _describe -t tasks 'task' tasks &&
+            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."
-- 
2.35.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH][RFC] Improve completion of Gradle tasks
  2022-04-01  6:19 [PATCH][RFC] Improve completion of Gradle tasks Marlon Richert
@ 2022-05-06  5:51 ` Marlon Richert
  2022-05-07  2:57   ` Bart Schaefer
  0 siblings, 1 reply; 5+ messages in thread
From: Marlon Richert @ 2022-05-06  5:51 UTC (permalink / raw)
  To: Zsh hackers list

Hi, committers! I submitted this patch over a month ago. Can it be
reviewed or applied, please? :)

On Fri, Apr 1, 2022 at 9:19 AM Marlon Richert <marlon.richert@gmail.com> wrote:
>
> See attachment.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH][RFC] Improve completion of Gradle tasks
  2022-05-06  5:51 ` Marlon Richert
@ 2022-05-07  2:57   ` Bart Schaefer
  2022-05-07  4:24     ` dana
  0 siblings, 1 reply; 5+ messages in thread
From: Bart Schaefer @ 2022-05-07  2:57 UTC (permalink / raw)
  To: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 260 bytes --]

On Thu, May 5, 2022 at 10:52 PM Marlon Richert <marlon.richert@gmail.com>
wrote:

> Hi, committers! I submitted this patch over a month ago. Can it be
> reviewed or applied, please? :)
>

Any objections to this sneaking into 5.9, despite .3-test already spun?

[-- Attachment #2: Type: text/html, Size: 580 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH][RFC] Improve completion of Gradle tasks
  2022-05-07  2:57   ` Bart Schaefer
@ 2022-05-07  4:24     ` dana
  2022-05-07  6:03       ` Marlon Richert
  0 siblings, 1 reply; 5+ messages in thread
From: dana @ 2022-05-07  4:24 UTC (permalink / raw)
  To: Bart Schaefer, Zsh hackers list; +Cc: Marlon Richert

On Fri 6 May 2022, at 21:57, Bart Schaefer wrote:
> Any objections to this sneaking into 5.9, despite .3-test already spun?

I don't know anything about Gradle, so i'm not sure if the way it handles
task completion is desirable. But i didn't see anything obviously wrong
with the patch, and it's not a critical component, so i don't object in
principle

I did note these pre-existing issues which might be fixed in a future
revision:

* _gradle_caching_policy is redefined every time the function executes

* possibly _arguments should have -s and/or -S?

* several of the options seem to be missing exclusion information

* none of the option descriptions use the conventional capitalisation,
  punctuation, or mood for completion functions

* there seems to be some confusion over whether short options that take
  arguments need + in the spec, and possibly the long options need =

* completion for -x just fails silently if there's no build file

dana


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH][RFC] Improve completion of Gradle tasks
  2022-05-07  4:24     ` dana
@ 2022-05-07  6:03       ` Marlon Richert
  0 siblings, 0 replies; 5+ messages in thread
From: Marlon Richert @ 2022-05-07  6:03 UTC (permalink / raw)
  To: dana; +Cc: Bart Schaefer, Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 902 bytes --]



> On 7 May 2022, at 07:24, dana <dana@dana.is> wrote:
> 
> On Fri 6 May 2022, at 21:57, Bart Schaefer wrote:
>> Any objections to this sneaking into 5.9, despite .3-test already spun?
> 
> I don't know anything about Gradle, so i'm not sure if the way it handles
> task completion is desirable.

The old task completion logic was too strict: There were many real-world task names that it did not complete. Also, the logic was actually incorrect: There were some forms of names that it did not allow, but which are explicitly allowed in Gradle’s spec.

> But i didn't see anything obviously wrong
> with the patch, and it's not a critical component, so i don't object in
> principle

Great! :)

> I did note these pre-existing issues which might be fixed in a future
> revision:

Yes, I noticed these, too. I will have a look at fixings them sometime in a future patch.



[-- Attachment #2: Type: text/html, Size: 1708 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-05-07  6:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-01  6:19 [PATCH][RFC] Improve completion of Gradle tasks Marlon Richert
2022-05-06  5:51 ` Marlon Richert
2022-05-07  2:57   ` Bart Schaefer
2022-05-07  4:24     ` dana
2022-05-07  6:03       ` Marlon Richert

Code repositories for project(s) associated with this inbox:

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).