This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch backport/zsh-completion-1.x in repository https://gitbox.apache.org/repos/asf/maven-mvnd.git
commit 28b8fa87ca5a4923a51bc576a2615cec5cc956aa Author: Guillaume Nodet <[email protected]> AuthorDate: Tue Mar 17 09:02:45 2026 +0100 Add zsh support to completion script Make the existing bash completion script work in both bash and zsh by auto-detecting the shell and adapting behavior accordingly: - Add shell detection via $ZSH_VERSION / $BASH_VERSION - Load bashcompinit in zsh for bash-style completion compatibility - Use typeset instead of declare/compgen for zsh - Use ${(P)var} instead of ${!var} for indirect expansion in zsh - Accept 'zsh' as valid --completion argument in Completion.java - Update README.adoc with zsh instructions Based on the approach from PR #1514 by janweinschenker, consolidated into the single existing script to avoid duplication. Co-Authored-By: Jan Weinschenker <[email protected]> Co-Authored-By: Claude Opus 4.6 <[email protected]> --- README.adoc | 8 +++-- .../java/org/mvndaemon/mvnd/client/Completion.java | 7 ++-- .../completion-templates/mvnd-bash-completion.bash | 37 +++++++++++++++++++--- dist/src/main/distro/bin/mvnd-bash-completion.bash | 37 +++++++++++++++++++--- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/README.adoc b/README.adoc index f0935afb..a935066d 100644 --- a/README.adoc +++ b/README.adoc @@ -105,13 +105,15 @@ $ asdf install mvnd latest === Set up completion -Optionally, you can set up completion as follows: +Optionally, you can set up completion in bash or zsh as follows: [source,shell] ---- -# ensure that MVND_HOME points to your mvnd distribution, note that sdkman does it for you +# bash: ensure that MVND_HOME points to your mvnd distribution, note that sdkman does it for you $ echo 'source $MVND_HOME/bin/mvnd-bash-completion.bash' >> ~/.bashrc + +# zsh: same script works in zsh (it auto-detects the shell) +$ echo 'source $MVND_HOME/bin/mvnd-bash-completion.bash' >> ~/.zshrc ---- -`bash` is the only shell supported at this time. === Note for oh-my-zsh users === diff --git a/client/src/main/java/org/mvndaemon/mvnd/client/Completion.java b/client/src/main/java/org/mvndaemon/mvnd/client/Completion.java index f971f82a..40241f1e 100644 --- a/client/src/main/java/org/mvndaemon/mvnd/client/Completion.java +++ b/client/src/main/java/org/mvndaemon/mvnd/client/Completion.java @@ -27,12 +27,13 @@ import java.nio.file.Path; public class Completion { public static String getCompletion(String shell, DaemonParameters daemonParameters) { - if (!"bash".equals(shell)) { - throw new IllegalArgumentException("Unexpected --completion value: '" + shell + "'; expected: 'bash'"); + if (!"bash".equals(shell) && !"zsh".equals(shell)) { + throw new IllegalArgumentException( + "Unexpected --completion value: '" + shell + "'; expected: 'bash' or 'zsh'"); } final Path bashCompletionPath = daemonParameters.mvndHome().resolve("bin/mvnd-bash-completion.bash"); if (!Files.isRegularFile(bashCompletionPath)) { - throw new IllegalStateException("Bash completion file does not exist: " + bashCompletionPath); + throw new IllegalStateException("Completion file does not exist: " + bashCompletionPath); } try { return new String(Files.readAllBytes(bashCompletionPath), StandardCharsets.UTF_8); diff --git a/client/src/test/resources/completion-templates/mvnd-bash-completion.bash b/client/src/test/resources/completion-templates/mvnd-bash-completion.bash index 95eea34f..5cc83b7e 100644 --- a/client/src/test/resources/completion-templates/mvnd-bash-completion.bash +++ b/client/src/test/resources/completion-templates/mvnd-bash-completion.bash @@ -17,10 +17,26 @@ # Adapted from https://github.com/juven/maven-bash-completion/blob/master/bash_completion.bash by Juven Xu and others # under Apache License Version 2.0 +# Detect shell type and set up zsh compatibility if needed +if [ -n "$ZSH_VERSION" ]; then + __MVND_SHELL="zsh" + # Load bashcompinit for bash-style completions in zsh + autoload -Uz bashcompinit 2>/dev/null && bashcompinit + # Define COMP_WORDBREAKS if not set (bash sets this automatically) + [[ -z "$COMP_WORDBREAKS" ]] && COMP_WORDBREAKS=$' \t\n"\'><=;|&(:' +else + __MVND_SHELL="bash" +fi + function_exists() { - declare -F $1 > /dev/null - return $? + if [ "$__MVND_SHELL" = "zsh" ]; then + typeset -f $1 > /dev/null 2>&1 + return $? + else + declare -F $1 > /dev/null + return $? + fi } # This function can be used to access a tokenized list of words @@ -288,7 +304,12 @@ _mvnd() local plugin_goals_formatter="formatter:format|formatter:help|formatter:validate" ## some plugin (like jboss-as) has '-' which is not allowed in shell var name, to use '_' then replace - local common_plugins=`compgen -v | grep "^plugin_goals_.*" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|'` + local common_plugins + if [ "$__MVND_SHELL" = "zsh" ]; then + common_plugins=$(typeset + | grep "^plugin_goals_" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|') + else + common_plugins=`compgen -v | grep "^plugin_goals_.*" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|'` + fi local options="-Dmaven.test.skip=true|-DskipTests|-DskipITs|-Dtest|-Dit.test|-DfailIfNoTests|-Dmaven.surefire.debug|-DenableCiProfile|-Dpmd.skip=true|-Dcheckstyle.skip=true|-Dtycho.mode=maven|-Dmaven.javadoc.skip=true|-Dgwt.compiler.skip|-Dcobertura.skip=true|-Dfindbugs.skip=true||-DperformRelease=true|-Dgpg.skip=true|-DforkCount|${mvnd_properties}" @@ -334,8 +355,14 @@ _mvnd() for plugin in $common_plugins; do if [[ ${cur} == ${plugin}:* ]]; then ## note that here is an 'unreplace', see the comment at common_plugins - var_name="plugin_goals_${plugin//-/_}" - COMPREPLY=( $(compgen -W "${!var_name}" -S ' ' -- ${cur}) ) + local var_name="plugin_goals_${plugin//-/_}" + local var_value + if [ "$__MVND_SHELL" = "zsh" ]; then + var_value="${(P)var_name}" + else + var_value="${!var_name}" + fi + COMPREPLY=( $(compgen -W "${var_value}" -S ' ' -- ${cur}) ) fi done diff --git a/dist/src/main/distro/bin/mvnd-bash-completion.bash b/dist/src/main/distro/bin/mvnd-bash-completion.bash index 692534a0..570adddb 100755 --- a/dist/src/main/distro/bin/mvnd-bash-completion.bash +++ b/dist/src/main/distro/bin/mvnd-bash-completion.bash @@ -17,10 +17,26 @@ # Adapted from https://github.com/juven/maven-bash-completion/blob/master/bash_completion.bash by Juven Xu and others # under Apache License Version 2.0 +# Detect shell type and set up zsh compatibility if needed +if [ -n "$ZSH_VERSION" ]; then + __MVND_SHELL="zsh" + # Load bashcompinit for bash-style completions in zsh + autoload -Uz bashcompinit 2>/dev/null && bashcompinit + # Define COMP_WORDBREAKS if not set (bash sets this automatically) + [[ -z "$COMP_WORDBREAKS" ]] && COMP_WORDBREAKS=$' \t\n"\'><=;|&(:' +else + __MVND_SHELL="bash" +fi + function_exists() { - declare -F $1 > /dev/null - return $? + if [ "$__MVND_SHELL" = "zsh" ]; then + typeset -f $1 > /dev/null 2>&1 + return $? + else + declare -F $1 > /dev/null + return $? + fi } # This function can be used to access a tokenized list of words @@ -288,7 +304,12 @@ _mvnd() local plugin_goals_formatter="formatter:format|formatter:help|formatter:validate" ## some plugin (like jboss-as) has '-' which is not allowed in shell var name, to use '_' then replace - local common_plugins=`compgen -v | grep "^plugin_goals_.*" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|'` + local common_plugins + if [ "$__MVND_SHELL" = "zsh" ]; then + common_plugins=$(typeset + | grep "^plugin_goals_" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|') + else + common_plugins=`compgen -v | grep "^plugin_goals_.*" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|'` + fi local options="-Dmaven.test.skip=true|-DskipTests|-DskipITs|-Dtest|-Dit.test|-DfailIfNoTests|-Dmaven.surefire.debug|-DenableCiProfile|-Dpmd.skip=true|-Dcheckstyle.skip=true|-Dtycho.mode=maven|-Dmaven.javadoc.skip=true|-Dgwt.compiler.skip|-Dcobertura.skip=true|-Dfindbugs.skip=true||-DperformRelease=true|-Dgpg.skip=true|-DforkCount|${mvnd_properties}" @@ -334,8 +355,14 @@ _mvnd() for plugin in $common_plugins; do if [[ ${cur} == ${plugin}:* ]]; then ## note that here is an 'unreplace', see the comment at common_plugins - var_name="plugin_goals_${plugin//-/_}" - COMPREPLY=( $(compgen -W "${!var_name}" -S ' ' -- ${cur}) ) + local var_name="plugin_goals_${plugin//-/_}" + local var_value + if [ "$__MVND_SHELL" = "zsh" ]; then + var_value="${(P)var_name}" + else + var_value="${!var_name}" + fi + COMPREPLY=( $(compgen -W "${var_value}" -S ' ' -- ${cur}) ) fi done
