+# Alexherbo2 2020, plug.kak, require-module, ModuleLoaded, viewed 04 March 2021, https://github.com/alexherbo2/plug.kak/blob/master/rc/plug.kak
+# Gradle 2020, Always define a settings file, Organizing Gradle Projects, Authoring Gradle Builds, Gradle User Manual, v6.8.3, p.378, viewed 04 March 2021,
+# Gradle-Completion 2020, _gradle-set-project-root-dir, _gradle, viewed 04 March 2021, https://github.com/gradle/gradle-completion/blob/master/_gradle#L3
+# Kakoune 2020, git.kak, mawww/kakaoune/rc/tools, viewed 04 March 2021, https://github.com/mawww/kakoune/blob/master/rc/tools/git.kak
+# Kakoune 2020, Writing Plugins, Kakoune Wiki, viewed 07 March 2021, https://github.com/mawww/kakoune/wiki/Writing-Plugins
+# Lenormand, F 2021, kakmerge, lenormf/kakmerge, viewed 07 Marck 2021, https://github.com/lenormf/kakmerge/blob/master/kakmerge
+# JDugan6240 2021, kak-gradle, rc/kak-gradle.kak, viewed 04 March 2021, https://github.com/jdugan6240/kak-gradle
+# git clone https://KJ_Duncan@bitbucket.org/snippets/KJ_Duncan/kxpAbn/jdugan6240-kak-gradle-wipkak.git
+# ================================================================================================== #
+# ================================================================================================== #
+# [The] main API you use to interact with Gradle from your build file. From a
+# Project, you have programmatic access to all of Gradle's features.
+# There is a one-to-one relationship between a Project and a "build.gradle" file.
+# During build initialisation, Gradle assembles a Project object for each project
+# which is to participate in the build, as follows:
+# + Create a Settings instance for the build.
+# + Evaluate the "settings.gradle" script, if present, against the Settings object to configure it.
+# + Use the configured Settings object to create the hierarchy of Project instances.
+# + Finally, evaluate each Project by executing its "build.gradle" file, if present,
+# against the project. The projects are evaluated in breadth-wise order, such that
+# a project is evaluated before its child projects. This order can be overridden
+# by calling evaluationDependsOnChildren() or by adding an explicit evaluation
+# dependency using evaluationDependsOn(String).
+# A project is essentially a collection of Task objects. Each task performs some
+# basic piece of work, such as compiling classes, or running unit tests, or
+# zipping up a WAR file. You add tasks to a project using one of the create()
+# methods on TaskContainer, such as TaskContainer.create(String). You can locate
+# existing tasks using one of the lookup methods on TaskContainer, such as
+# TaskCollection.getByName(String).
+# A project generally has a number of dependencies it needs in order to do its
+# work. Also, a project generally produces a number of artifacts, which other
+# projects can use. Those dependencies are grouped in configurations, and can be
+# retrieved and uploaded from repositories. You use the ConfigurationContainer
+# returned by getConfigurations() method to manage the configurations. The
+# DependencyHandler returned by getDependencies() method to manage the
+# dependencies. The ArtifactHandler returned by getArtifacts() method to manage
+# the artifacts. The RepositoryHandler returned by getRepositories() method to
+# manage the repositories.
+# Projects are arranged into a hierarchy of projects. A project has a name, and a
+# fully qualified path which uniquely identifies it in the hierarchy.
+# Gradle 2021, Interface Project, org.gradle.api, version 6.8.3, viewed 07 March 2021,
+# https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html
+# NOTE: Separation of business from domain logic will allow greater user flexibility and customisation.
+# *.sh spawns independent kak session to run Custom Gradle Tasks (business logic, ref: lenormf/kakmerge)
+# *.kak spawns a kak session to run build.gradle[.kts] tasks (domain logic, ref: kak-gradle)
+# ------------------------------------------------------------------------------------------------- #
+# Business Logic (*.sh):
+# $ java -XX:ErrorFile=/var/log/java/java_error%p.log gCustomTask
+# $ java -XX:OnError="gdb - %p" gCustomTask
+# $ java -XX:ShowMessageBoxOnError="yes" gCustomTask
+# The following example shows a fatal error on a Linux system.
+# ==============================================================================
+# ------------------------------------------------------------------------------
+# SIGSEGV (0xb) at pc=0x2000000001164db1, pid=10791, tid=1026
+# Do you want to debug the problem?
+# To debug, run 'gdb /proc/10791/exe 10791'; then switch to thread 1026
+# Enter 'yes' to launch gdb automatically (PATH must include gdb)
+# Otherwise, press RETURN to abort...
+# ==============================================================================
+# GNU 2021, Debugging with GDB: the GNU Source-Level Debugger for GDB (GDB), Version 11.0.50.20210306-git,
+# viewed 07 March 2021, https://sourceware.org/gdb/current/onlinedocs/gdb/
+# Oracle 2020, Java HotSpot VM Command-Line Options, Appendix D, Java SE 15 Troubleshooting Guide,
+# viewed 07 March 2021, Error 404--Not Found, troubleshoot with local pdf.
+# ================================================================================================== #
+# ================================================================================================== #
+hook global ModuleLoaded gradle-build-tool %{
+ # Modules are plug and play (any/all module(s) can be loaded in a context for its side-effects)
+ # When you require the side-effects of the module, you want to use the shared
+ # highlighters it defines, or read the value of the option it sets, etc. use the
+ # require-module command (kakoune wiki).
+ # The first time Kakoune executes a require-module command, it looks up the
+ # contents of the corresponding module and executes them, then marks that module
+ # as loaded (kakoune wiki).
+ # kakoune 2020, Put slow dependencies in modules, Writing Plugins, kakoune wiki, viewed 11 March 2021,
+ # https://github.com/mawww/kakoune/wiki/Writing-Plugins#put-slow-dependencies-in-modules
+ require-module gradle-build-tool
+ # ------------------------------------------------------------------------------------------------- #
+ # TEST: check for issues with dirname
+ declare-option str gradle_plugin_path %sh{ dirname "$kak_source" }
+ declare-option str gradlew_wrapper %sh{ printf "%s/src/gradle_system.sh %s" "$kak_opt_gradle_plugin_path" "$@" }
+ declare-option str gradle_system %sh{ printf "%s/src/gradlew_wrapper.sh %s" "$kak_opt_gradle_plugin_path" "$@" }
+ declare-option str gradle_project_root_dir "nay"
+ declare-option str gradle_package_root_dir "nay"
+ # The Secure Coding Guidelines for Java SE, Guideline 5-1/INPUT-1: Validate inputs
+ # states: A malicious file who's name includes "../" opens the door for 'Directory
+ # Traversal Attacks' and reinforces that the design of such 'Ease-Of-Use' features
+ # should be separated from programmatic interfaces.
+ # _gradle-set-project-root-dir() {
+ # project_root_dir=`pwd`
+ # while [[ $dir != '/' ]]; do
+ # if [[ -f "$dir/settings.gradle" || -f "$dir/settings.gradle.kts" || -f "$dir/gradlew" ]]; then
+ # project_root_dir=$dir
+ # dir="$(dirname "$dir")"
+ # NOTE: If your understanding of the aforementioned is in contrast to mine please educate me further.
+ # Gradle-completion 2017, _gradle, gradle-completion/, gradle/gradle-completion is licensed under the MIT License,
+ # viewed 10 March 2021, https://github.com/gradle/gradle-completion/blob/master/_gradle#L3
+ # Secure Coding Guidelines for Java SE 2020, Guideline 5-1 / INPUT-1: Validate inputs, 5 Input Validation,
+ # viewed 12 March 2021, https://www.oracle.com/java/technologies/javase/seccodeguide.html
+ # ------------------------------------------------------------------------------------------------ #
+ # USER MODE/MENU FOR PROJECT PATH OR NEW PROJECT
+ # Andrey does: fzf_project_file "%val{config}/.fzf-projects"
+ # As a user knows best solution for quick and clean: -kak-cmd change-directory
+ # Listopadov, A 2021, fzf-save-path-as-project, fzf-project.kak, fzf.kak/rc/modules/, viewed 06 March 2021,
+ # https://github.com/andreyorst/fzf.kak/blob/master/rc/modules/fzf-project.kak#L36
+ # PROBLEM: (P)roject, (P)ackage
+ # REASON: (P)andemonium
+ # SOLUTION: (P)roject, (M)odule
+ # SOLUTION: (S)ettings, (B)uild
+ map global gradle 'p' '<esc>: gradle-project<ret>' -docstring "open gradle project"
+ map global gradle '<a-p>' '<esc>: enter-user-mode gradle-project<ret>' -docstring "gradle project menu"
+ try %{ declare-user-mode gradle-project }
+ try %{ declare-user-mode gradle-package }
+ # ------------------------------------------------------------------------------------------------- #
+ declare-option str gradle_project_path ""
+ declare-option str gradle_package_path ""
+ declare-option str gradle_command ""
+ declare-option str gradle_wrapper_command ""
+ # ------------------------------------------------------------------------------------------------- #
+ declare-option -docstring %{
+ Determines whether to use the project's gradle
+ wrapper or the system wide gradle installation
+ } bool use_gradlew false
+# ------------------------------------------------------------------------------------------------- #
+# TODO: match up highlighters/groups/hooks
+# Enable the highlighters for the gradle-tasks filetype
+hook -group gradle-tasks-syntax global WinSetOption filetype=gradle-tasks %{
+ add-highlighter window/gradle_tasks_buffer ref gradle_tasks_buffer
+ hook -always -once window WinSetOption filetype=.* %{ remove-highlighter window/gradle_tasks_buffer }
+# ------------------------------------------------------------------------------------------------- #
+# Enable the highlighters for the gradle-deps filetype
+hook -group gradle-deps-syntax global WinSetOption filetype=gradle-deps %{
+ add-highlighter window/gradle_buffer ref gradle_buffer
+ hook -always -once window WinSetOption filetype=.* %{ remove-highlighter window/gradle_buffer }
+# -------------------------------------------------------------------------------------------------- #
+# MODULE ------------------------------------------------------------------------------------------- #
+provide-module gradle-build-tool %§
+ # ...regular commands go in here...
+ # Declare highlighters for the dependencies buffer
+ add-highlighter shared/gradle_buffer regions
+ add-highlighter shared/gradle_buffer/deps default-region group
+ add-highlighter shared/gradle_buffer/deps/category regex "(^[a-zA-Z0-9]*)( - [^\n]*)" 0:string 1:type
+ add-highlighter shared/gradle_buffer/deps/dependency regex "([+\\]---)( [^\n]*)" 0:keyword 1:string
+ add-highlighter shared/gradle_buffer/deps/symbol regex "(\|)" 0:string
+ add-highlighter shared/gradle_buffer/deps/no_deps regex "^No dependencies$" 0:keyword
+ add-highlighter shared/gradle_buffer/deps/legend regex "(\([*n]\))( [^\n]*)" 0:string 1:type
+ # Declare highlighters for the tasks buffer
+ add-highlighter shared/gradle_buffer/task group
+ add-highlighter shared/gradle_buffer/task/tasks regex "(^[a-zA-Z0-9]*)( - [^\n]*)" 0:string 1:type
+ # ------------------------------------------------------------------------------------------------ #
+ # Determine if we need to use the gradle wrapper, or use the systemwide gradle command
+ # THIS WILL TRANSITION TO AUTOMATION FOR TESTING
+ # Bomanson, J 2021, kak-spec.kak, github.com, viewed 09 March 2021,
+ # https://github.com/jbomanson/kak-spec.kak
+ define-command -hidden -docstring "variable initialisation on ModuleLoad" \
+ gradle-module-initialisation %{ try %{
+ evaluate-commands %opt{gradle-build-root-dir}
+ evaluate-commands %opt{use_gradlew}
+ set-option global gradle_wrapper_command %opt{gradle_build_root_dir}
+ set-option -add global gradle_wrapper_command "/gradlew"
+ set-option global gradle_command "gradlew"
+ set-option global gradle_command "gradle"
+ fail "No build.gradle(.kts) file found in working directory"
+ # ------------------------------------------------------------------------------------------------ #
+ # ARE WE ACTUALLY IN A GRADLE PROJECT?
+ # OR ARE WE CALLING GRADLE INIT?
+ # CONFIRM CURRENT DIRECTORY, WITH ABSOLUTE NOT RELATIVE PATH.
+ # ASK THE HUMAN, WHAT DO YOU WANT TO DO.
+ # GRADLE EVENTS: INIT OR OTHER-TASK
+ # INIT DOES NOT IMPLY GRADLE OR GRADLEW FOR THE PROJECT/PACKAGE
+ # NEED HUMAN HERE: GRADLE OR GRADLEW
+ # 1) GRADLE INIT OR OTHER-TASK
+ # ├── gradle.properties
+ # ---------------------------------------------------------------------------------------------- #
+ # THE GRADLE(W) WRAPPER UNIVERSE
+ # $PWD/gradle/wrapper/gradle-wrapper.jar
+ # gng 2021, install.sh, gdubw/gng/, github.com, viewed 11 March 2021,
+ # https://github.com/gdubw/gng/blob/master/install.sh#L114
+ # ---------------------------------------------------------------------------------------------- #
+ # SETTINGS.GRADLE RESIDES IN TOP LEVEL PROJECT ROOT
+ # If we found a (build|settings).gradle file, then we found the gradle root directory
+ # both the gradle build and settings file can reside in the top level project root
+ define-command -hidden gradle-project-root-dir %{ evaluate-commands %sh{
+ project_root_dir=$(find -P -mount -maxdepth 1 -mindepth 1 -type f -regex '^.*/settings.gradle[.kts]*?' | sed 's/^.\///')
+ if [[ "$project_root_dir" == *"settings.gradle"* ]]; then
+ cur_dir=$(realpath $(dirname "$kak_source"))
+ printf "set-option global gradle_project_root_dir %s \n" "$cur_dir"
+ # ------------------------------------------------------------------------------------------------ #
+ # BUILD.GRADLE RESIDES IN TOP LEVEL PACKAGE/MODULE ROOT
+ define-command -hidden gradle-package-root-dir %{ evaluate-commands %sh{
+ package_root_dir=$(find -P -mount -maxdepth 1 -mindepth 1 -type f -regex '^.*/build.gradle[.kts]*?' | sed 's/^.\///')
+ if [[ "$package_root_dir" == *"build.gradle"* ]]; then
+ cur_dir=$(realpath $(dirname "$kak_source"))
+ printf "set-option global gradle_package_root_dir %s \n" "$cur_dir"
+ # ------------------------------------------------------------------------------------------------ #
+ # Determine if we need to use the gradle wrapper, or use the systemwide gradle command
+ # The Open Group 2018, 2.2 Quoting, Shell & Utilities, Issue 7, 2018 edition, viewed 08 March 2021,
+ # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02
+ define-command -docstring "Execute arbitrary gradle command" \
+ -params .. gradle %{ evaluate-commands %sh{
+ if [[ "$kak_opt_use_gradlew" = "true" ]]; then
+ printf "terminal %s %s %s" "${kak_opt_gradlew_wrapper}" "$kak_opt_gradle_package_root_dir" "$@"
+ printf "terminal %s %s" "${kak_opt_gradle_system}" "$@"
+ # ------------------------------------------------------------------------------------------------ #
+ define-command --params 1.. gradle-commands %{ evaluate-commands %sh{
+ # ---------------------------------------------------------------------------------------------- #
+ # HELPER FUNCTION ------------------------------------------------------------------------------ #
+ function make_named_pipe() {
+ # TEE UTILITY FOR A PERPETUAL LOG
+ # USER WILL NEED TO SET A FILE SIZE LIMIT
+ # $ (command) | tee --append \
+ # --ignore-interrupts \
+ # --output-error=exit-nopipe "$FILE" | (command)
+ # refs: https://www.freedesktop.org/software/systemd/man/journalctl.html
+ # https://linux.die.net/man/8/logrotate
+ # https://wiki.manjaro.org/index.php/Limit_the_size_of_.log_files_%26_the_journal
+ # -------------------------------------------------------------------------------------------- #
+ # HOT SWAP BUFFER IO INSTEAD OF GENERATING OUTPUT FROM MULTIPLE GRADLE TASKS
+ # AS KAKOUNE MAINTAINS THE BUFFER LIST WITHOUT USER INTERACTION
+ # HOT SWAP BUFFER IO IDEA:
+ # mkfifo "$workdir/input"
+ # mkfifo "$workdir/output"
+ # ( "$kak_opt_repl_buffer_source/repl-buffer-input" "$workdir/input" |
+ # "$@" >"$workdir/output" 2>&1 &
+ # ) </dev/null >/dev/null 2>&1
+ # Screwtape 2021, repl-buffer.kak, kakoune-repl-buffer, viewed 06 March 2021,
+ # https://gitlab.com/Screwtapello/kakoune-repl-buffer/-/blob/master/repl-buffer.kak#L45
+ # -------------------------------------------------------------------------------------------- #
+ # SECURITY POLICY 101: IF NOT ME, THEN WHO?
+ # Portable scripts should not rely on requests to set or clear these bits on
+ # directories, as POSIX allows implementations to ignore these requests. The GNU
+ # behaviour with numeric modes of four or fewer digits is intended for scripts
+ # portable to systems that preserve these bits; the behaviour with numeric modes of
+ # five or more digits is for scripts portable to systems that do not preserve the
+ # GNU Coreutils 2021, 27.5 Directories and the Set-User-ID and Set-Group-ID Bits, viewed 09 March 2021,
+ # https://www.gnu.org/software/coreutils/manual/html_node/Directory-Setuid-and-Setgid.html#Directory-Setuid-and-Setgid
+ # GNU Coreutils 2021, 27.3 Numeric Modes, File Permissions, viewed 09 March 2021,
+ # https://www.gnu.org/software/coreutils/manual/html_node/Numeric-Modes.html#Numeric-Modes
+ # NOTE: last minute thought `mknod` 12.5 mknod: Make block or character special files,
+ # https://www.gnu.org/software/coreutils/manual/html_node/mknod-invocation.html#mknod-invocation
+ # directory creation MODE: 00700
+ if ! tmp=$(mktemp --directory "${TMPDIR:-/tmp}"/kak-gradle.XXXXXXXX); then
+ printf "mktemp directory failed, now exiting...\n"
+ # -------------------------------------------------------------------------------------------- #
+ # MODE: rw-r-00640, rw-r-r-00644, rw-rw-00660, rw-rw-r-00664
+ if ! fifo=$tmp/fifo && mkfifo --mode 00640 ${fifo}; then
+ printf "mkfifo named pipe failed, now exiting...\n"
+ # -------------------------------------------------------------------------------------------- #
+ # TEST: does this work? .* glob, regex or literal
+ printf 'evaluate-commands -client "$kak_client" %%{
+ hook -always -once buffer BufCloseFifo .* %%{ nop %%sh{ rm -rf "${tmp}" } }
+ # -------------------------------------------------------------------------------------------- #
+ # ---------------------------------------------------------------------------------------------- #
+ # CONSUMER FUNCTIONS --------------------------------------------------------------------------- #
+ function consume_gradle_init() {
+ # +----------------------+----------------------------------------------------+
+ # | Type | Description |
+ # +----------------------+----------------------------------------------------+
+ # | pom | Converts an existing Apache Maven build to Gradle |
+ # | basic | Basic, empty, Gradle build |
+ # | cpp-application | Command-line application implemented in C++ |
+ # | cpp-library | C++ library |
+ # | groovy-application | Command-line application implemented in Groovy |
+ # | groovy-gradle-plugin | Gradle plugin implemented in Groovy |
+ # | groovy-library | Groovy library |
+ # | java-application | Command-line application implemented in Java |
+ # | java-gradle-plugin | Gradle plugin implemented in Java |
+ # | java-library | Java library |
+ # | kotlin-application | Command-line application implemented in Kotlin/JVM |
+ # | kotlin-gradle-plugin | Gradle plugin implemented in Kotlin/JVM |
+ # | kotlin-library | Kotlin/JVM library |
+ # | scala-application | Scala application |
+ # | scala-library | Scala library |
+ # +----------------------+----------------------------------------------------+
+ # Starting a Gradle Daemon (subsequent builds will be faster)
+ # Select type of project to generate:
+ # Enter selection (default: basic) [1..4] 1
+ # Select build script DSL:
+ # Enter selection (default: Groovy) [1..2] 2
+ # Project name (default: init-generic):
+ # Get more help with your project: Learn more about Gradle by exploring our samples at https://docs.gradle.org/6.8.3/samples
+ # BUILD SUCCESSFUL in 1m 53s
+ # 2 actionable tasks: 2 executed
+ # -------------------------------------------------------------------------------------------- #
+ # │ ├── gradle-wrapper.jar
+ # │ └── gradle-wrapper.properties
+ # └── settings.gradle.kts
+ # 2 directories, 6 files
+ # ---------------------------------------------------------------------------------------------- #
+ # +-------------------------------------------+
+ # +----------+---------+---------+------------+
+ # | Constant | Version | Type | Extension |
+ # +----------+---------+---------+------------+
+ # | gradle 6.8.3 wrapper jar.sha256 |
+ # | gradle 6.8.3 docs zip |
+ # | gradle 6.8.3 docs zip.sha256 |
+ # | gradle 6.8.3 src zip |
+ # | gradle 6.8.3 src zip.sha256 |
+ # | gradle 6.8.3 bin zip |
+ # | gradle 6.8.3 bin zip.sha256 |
+ # | gradle 6.8.3 all zip |
+ # | gradle 6.8.3 all zip.sha256 |
+ # +-------------------------------------------+
+ # TODO: curl or wget, build the use-case in accordance with the gradle manual
+ # no-redirects, we are either at the location or NOT.
+ # If don't then tell me why.
+ # curl --fail \ # fail silently on server errors
+ # --location \ # redirections the default is 50 see --max-redirs
+ # --no-progress-meter \ # switch off progress without muting stdout stderr
+ # --show-error \ # makes curl show error messages
+ # --parallel \ # multiple url requests (zip|zip.sha256)
+ # --output "$FILE" \ # write to file not stdout see man-page
+ function consume_gradle_wrapper() {
+ # TODO: make it work with positional arguments
+ # func() -b 6.8.3 -- args
+ while getopts abdsw: opt; do
+ (a) type="all"; version=$OPTARG;;
+ (b) type="bin"; version=$OPTARG;;
+ (d) type="doc"; version=$OPTARG;;
+ (s) type="src"; version=$OPTARG;;
+ (w) type="wrapper"; version=$OPTARG;;
+ (( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
+ printf "Remaining arguments are: %s" "$*" # where args = [curl|wget|sha256|...]
+ # The last piece of the 'getopts' jigsaw is the [last] line, which tests if $OPTIND
+ # is larger than 1, i.e. an option was found and $OPTIND was advanced - it is
+ # automatically set to 1 at the start of every function or script. If it was, the
+ # 'shift' builtin with a numeric argument, but no array name, moves the positional
+ # parameters, i.e. the function’s arguments, to shift away the options that have
+ # been processed...[You] can just start using the remaining arguments from
+ # Stephensen, P 2003, 3.2.13 Handling options to functions and scripts, A User's Guide to the Z-Shell,
+ # viewed 11 March 2021, http://zsh.sourceforge.net/Guide/zshguide03.html#l44
+ # -------------------------------------------------------------------------------------------- #
+ # DISTRIBUTION URL --------------------------------------------------------------------------- #
+ # https://services.gradle.org/distributions/
+ # host: downloads.gradle-dn.com
+ # filename: /distributions/gradle-6.8.3-docs.zip[.sha256]*?
+ # Address: 104.17.160.20:443
+ # Accept: (browser dev-tools: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8)
+ # Accept-Encoding: gzip, deflate, br
+ # Accept-Language: en-US,en;q=0.5
+ # Connection: keep-alive
+ # Cookie: __cfduid=XXXXXXXX
+ # Host: downloads.gradle-dn.com
+ # Referer: https://services.gradle.org/distributions/
+ # content-type: application/zip
+ # content-type: application/octet-stream
+ distributionUrlZip="https://services.gradle.org/distributions/gradle-${version}-${type}.zip"
+ distributionUrlZipSha256="https://services.gradle.org/distributions/gradle-${version}-${type}.zip.sha256"
+ distributionUrlJarSha256="https://services.gradle.org/distributions/gradle-${version}-${type}.jar.sha256"
+ # Could do an alternation between the two utilities and content-type(s) as per the jbang script
+ if [ -x "$(command -v curl)" ]; then
+ curl -sLf -H "Accept: application/gzip, application/octet-stream" -o "$2" $1
+ elif [ -x "$(command -v wget)" ]; then
+ wget -q --header="Accept: application/gzip, application/octet-stream" -O "$2" $1
+ echo "Error: curl or wget not found, please make sure one of them is installed" 1>&2
+ # jbang 2021, jbang, jbang/src/main/scripts/, viewed 11 March 2021,
+ # https://github.com/jbangdev/jbang/blob/master/src/main/scripts/jbang#L29
+ # ---------------------------------------------------------------------------------------------- #
+ # PRODUCER FUNCTIONS --------------------------------------------------------------------------- #
+ function show_gradle_task_custom() {
+ # ---------------------------------------------------------------------------------------------- #
+ function show_gradle_test() {
+ # ---------------------------------------------------------------------------------------------- #
+ function show_gradle_projects() {
+ # TEST: info -style modal
+ projects=$($kak_opt_gradle_command projects | grep -E "Root project[^\n]+|Project")
+ printf "info -title %s %s" "$title" "${projects}"
+ # ---------------------------------------------------------------------------------------------- #
+ # CAN WE JUST BG AND FG THE TMP/FILE(S), FIFO IS A TOPIC DISCUSSION (ANALYSIS)
+ # DOES THE FIFO APPEND >> OR REWRITE LOG >|
+ # lhs is always a file description, i.e., a number:
+ # Either we want to open, duplicate, move or we want to close. If the op is < then
+ # there is an implicit 0, if it's > or >>, there is an implicit 1.
+ # op is <, >, >>, >|, or <>:
+ # < if the file descriptor in lhs will be read, > if it will be written, >> if data
+ # is to be appended to the file, >| to overwrite an existing file or <> if it will
+ # be both read and written.
+ # rhs is the thing that the file descriptor will describe:
+ # It can be the name of a file, the place where another descriptor goes (&1), or,
+ # &-, which will close the file descriptor.
+ # The Bash Hackers Wiki 2019, Syntax, Illustrated Redirection Tutorial, viewed 09 March 2021,
+ # https://wiki.bash-hackers.org/howto/redirection_tutorial#syntax
+ # The Open Group 2018, 2.7.3 Appending Redirected Output, Shell & Utilities, Issue 7, 2018 edition, viewed 09 March 2021,
+ # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07
+ # ---------------------------------------------------------------------------------------------- #
+ # SET MARKERS IN FIFO FOR GRADLE CACHED ACTIVITY/EVENT, NEED TO MAINTAIN GLOBAL FIFO STATE
+ # ^TOKEN:COMMAND:TIMESTAMP
+ # GRADLE CACHED ACTIVITIES FAIL SILENTLY
+ # USER OPTION: SHOW PREVIOUS STATE?
+ # ---------------------------------------------------------------------------------------------- #
+ # DIFF UTILITY SHOWS A SIDE-BY-SIDE VIEW (FIFO OLD STATE, FIFO NEW STATE)
+ # FILES are 'FILE1 FILE2' or 'DIR1 DIR2' or 'DIR FILE' or 'FILE DIR'
+ # If a FILE is '-', read standard input.
+ # Exit status is 0 if inputs are the same,
+ # 1 if different, 2 if trouble.
+ # $ diff --side-by-side \
+ # --suppress-common-lines \
+ # --[no]-ignore-file-name-case \
+ # --ignore-blank-lines \
+ # --speed-large-files \
+ # --color=always "$FILE1" "$FILE2"
+ # ---------------------------------------------------------------------------------------------- #
+ # Run "gradle help --task <taskname>" in the background and extract strictly the task help
+ function show_gradle_task_help() {
+ pipe=$(make_named_pipe)
+ # -------------------------------------------------------------------------------------------- #
+ # TEST: target>&source, (command >> file 2>&1 </dev/null &)
+ ( $kak_opt_gradle_command help --task "$@" | grep '^[a-zA-Z0-9]* -' >> ${pipe} 2>&1 </dev/null & )
+ # TEST: (command &>> file &) 2>/dev/null, is this ok for shell?
+ # append standard output and error of command to fifo in a subshell as a background process
+ ( $kak_opt_gradle_command help --task "$@" | grep '^[a-zA-Z0-9]* -' &>> ${pipe} & ) 2>/dev/null
+ # ------------------------------------------------------------------^^^---------^------------- #
+ # NOTE: NEED TO SEE IT IN ACTION (docsclient)
+ # Kakoune 2020, doc.(asciidoc|kak), kakoune/rc/tools/, viewed 08 March 2021,
+ # https://github.com/mawww/kakoune/blob/master/rc/tools/doc.asciidoc,
+ # https://github.com/mawww/kakoune/blob/master/rc/tools/doc.kak
+ # TEST: literal or glog '*gradle*' between single quotes
+ printf 'evaluate-commands -try-client "$kak_opt_docsclient" %%{
+ edit! -fifo "${pipe}" *gradle*
+ set-option buffer filetype gradle-task-help
+ # ---------------------------------------------------------------------------------------------- #
+ function show_gradle_tasks() {
+ pipe=$(make_named_pipe)
+ # -------------------------------------------------------------------------------------------- #
+ # Run "gradle tasks" in the background and extract strictly the task names
+ ( $kak_opt_gradle_command tasks | grep '^[a-zA-Z0-9]* -' >> ${pipe} 2>&1 </dev/null & )
+ # -------------------------------------------------------------------------------------------- #
+ printf 'evaluate-commands -try-client "$kak_opt_docsclient" %%{
+ edit! -fifo "${pipe}" *gradle*
+ set-option buffer filetype gradle-tasks
+ map buffer normal <ret> ":<space>gradle-fifo-operate<ret>"
+ # ---------------------------------------------------------------------------------------------- #
+ function show_gradle_dependencies() {
+ pipe=$(make_named_pipe)
+ # -------------------------------------------------------------------------------------------- #
+ # Run "gradle dependencies" in the background and extract the dependencies and "legend"
+ ( $kak_opt_gradle_command dependencies |
+ grep -E '^[a-zA-Z0-9]* -|[+\]--- |No dependencies|\([*n]\)|^$' >> ${pipe} 2>&1 </dev/null &
+ # -------------------------------------------------------------------------------------------- #
+ printf 'evaluate-commands -try-client "$kak_opt_docsclient" %%{
+ edit! -fifo "${pipe}" *gradle*
+ set-option buffer filetype gradle-deps
+ # ---------------------------------------------------------------------------------------------- #
+ # +--------+------------+------------+------------------------------------------+
+ # | | | Word | Number of arguments if $* contains... |
+ # | Shell | Expression | Splitting | (two words) | ’one word’ | empty string |
+ # +--------+------------+------------+-------------+------------+---------------+
+ # | zsh | "$*" n 1 1 1 |
+ # | zsh | "$@" n 2 1 1 |
+ # +--------+--------------------------------------------------------------------+
+ # | sh/ksh | $* y 2 2 0 |
+ # | sh/ksh | $@ y 2 2 0 |
+ # | sh/ksh | "$*" y 1 1 1 |
+ # | sh/ksh | "$@" y 2 1 1 |
+ # +--------+--------------------------------------------------------------------+
+ # | | "${=*}" n 2 2 1 |
+ # | | "${=@}" n 2 2 1 |
+ # +--------+--------------------------------------------------------------------+
+ # [What] the function will get if the positional parameters are set to an array of
+ # two words, a single word with a space in the middle, or a single word which is
+ # an empty string (the effect of `set -- ''`) respectively. The second column
+ # shows whether word splitting is in effect, i.e. whether the SH_WORD_SPLIT option
+ # is set. The first four lines show the normal zsh behaviour; the second four show
+ # the normal sh/ksh behaviour, with word splitting turned on --- only the case
+ # where a word has a space in it changes, and then only when no quotes are
+ # supplied. The final four show what happens when you use the `${=..}' method to
+ # turn on word splitting.
+ # Stephensen, P 2003, 3.3.2: Function parameters, A User's Guide to the Z-Shell, viewed 09 March 2021,
+ # http://zsh.sourceforge.net/Guide/zshguide03.html#l50
+ # GRADLE CONSTANTS DECISION TREE --------------------------------------------------------------- #
+ # gradle-completion 2017, gradle-completion/LICENSE, gradle/gradle-completion is licensed under the MIT License,
+ # viewed 10 March 2021, https://github.com/gradle/gradle-completion/blob/master/LICENSE
+ # NOTE: Business/Domain logic could source this files functions or alternately
+ # migrate and refactor some gradle-completion functions in accordance with
+ # their license agreement.
+ # ref: https://github.com/gradle/gradle-completion/blob/master/_gradle#L192
+ init) consume_gradle_init "$@" ;;
+ wrapper) consume_gradle_wrapper "$@" ;;
+ dependencies) show_gradle_dependencies "$@" ;;
+ custom) show_gradle_task_custom "$@" ;;
+ help) show_gradle_task_help "$@" ;;
+ tasks) show_gradle_tasks "$@" ;;
+ test) show_gradle_test "$@" ;;
+ # ------------------------------------------------------------------------------------------------ #
+ define-command -hidden gradle-fifo-operate %{ evaluate-commands -save-regs t %{
+ execute-keys -save-regs '' "ghw"
+ set-register t %val{selection}
+ printf "terminal %s %s" "${kak_opt_gradle_system}" "$task"
+# -------------------------------------------------------------------------------------------------- #
+# THE END ------------------------------------------------------------------------------------------ #