Skip to content

Commit 7f7db5e

Browse files
gnodetjanweinschenkerclaude
committed
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 <janweinschenker@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ef147b2 commit 7f7db5e

File tree

4 files changed

+73
-16
lines changed

4 files changed

+73
-16
lines changed

README.adoc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,15 @@ $ asdf install mvnd latest
106106

107107
=== Set up completion
108108

109-
Optionally, you can set up completion as follows:
109+
Optionally, you can set up completion in bash or zsh as follows:
110110
[source,shell]
111111
----
112-
# ensure that MVND_HOME points to your mvnd distribution, note that sdkman does it for you
112+
# bash: ensure that MVND_HOME points to your mvnd distribution, note that sdkman does it for you
113113
$ echo 'source $MVND_HOME/bin/mvnd-bash-completion.bash' >> ~/.bashrc
114+
115+
# zsh: same script works in zsh (it auto-detects the shell)
116+
$ echo 'source $MVND_HOME/bin/mvnd-bash-completion.bash' >> ~/.zshrc
114117
----
115-
`bash` is the only shell supported at this time.
116118

117119
=== Install manually
118120

client/src/main/java/org/mvndaemon/mvnd/client/Completion.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@
2727
public class Completion {
2828

2929
public static String getCompletion(String shell, DaemonParameters daemonParameters) {
30-
if (!"bash".equals(shell)) {
31-
throw new IllegalArgumentException("Unexpected --completion value: '" + shell + "'; expected: 'bash'");
30+
if (!"bash".equals(shell) && !"zsh".equals(shell)) {
31+
throw new IllegalArgumentException(
32+
"Unexpected --completion value: '" + shell + "'; expected: 'bash' or 'zsh'");
3233
}
3334
final Path bashCompletionPath = daemonParameters.mvndHome().resolve("bin/mvnd-bash-completion.bash");
3435
if (!Files.isRegularFile(bashCompletionPath)) {
35-
throw new IllegalStateException("Bash completion file does not exist: " + bashCompletionPath);
36+
throw new IllegalStateException("Completion file does not exist: " + bashCompletionPath);
3637
}
3738
try {
3839
return new String(Files.readAllBytes(bashCompletionPath), StandardCharsets.UTF_8);

client/src/test/resources/completion-templates/mvnd-bash-completion.bash

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,26 @@
1717
# Adapted from https://github.com/juven/maven-bash-completion/blob/master/bash_completion.bash by Juven Xu and others
1818
# under Apache License Version 2.0
1919

20+
# Detect shell type and set up zsh compatibility if needed
21+
if [ -n "$ZSH_VERSION" ]; then
22+
__MVND_SHELL="zsh"
23+
# Load bashcompinit for bash-style completions in zsh
24+
autoload -Uz bashcompinit 2>/dev/null && bashcompinit
25+
# Define COMP_WORDBREAKS if not set (bash sets this automatically)
26+
[[ -z "$COMP_WORDBREAKS" ]] && COMP_WORDBREAKS=$' \t\n"\'><=;|&(:'
27+
else
28+
__MVND_SHELL="bash"
29+
fi
30+
2031
function_exists()
2132
{
22-
declare -F $1 > /dev/null
23-
return $?
33+
if [ "$__MVND_SHELL" = "zsh" ]; then
34+
typeset -f $1 > /dev/null 2>&1
35+
return $?
36+
else
37+
declare -F $1 > /dev/null
38+
return $?
39+
fi
2440
}
2541

2642
# This function can be used to access a tokenized list of words
@@ -288,7 +304,12 @@ _mvnd()
288304
local plugin_goals_formatter="formatter:format|formatter:help|formatter:validate"
289305

290306
## some plugin (like jboss-as) has '-' which is not allowed in shell var name, to use '_' then replace
291-
local common_plugins=`compgen -v | grep "^plugin_goals_.*" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|'`
307+
local common_plugins
308+
if [ "$__MVND_SHELL" = "zsh" ]; then
309+
common_plugins=$(typeset + | grep "^plugin_goals_" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|')
310+
else
311+
common_plugins=`compgen -v | grep "^plugin_goals_.*" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|'`
312+
fi
292313

293314
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}"
294315

@@ -334,8 +355,14 @@ _mvnd()
334355
for plugin in $common_plugins; do
335356
if [[ ${cur} == ${plugin}:* ]]; then
336357
## note that here is an 'unreplace', see the comment at common_plugins
337-
var_name="plugin_goals_${plugin//-/_}"
338-
COMPREPLY=( $(compgen -W "${!var_name}" -S ' ' -- ${cur}) )
358+
local var_name="plugin_goals_${plugin//-/_}"
359+
local var_value
360+
if [ "$__MVND_SHELL" = "zsh" ]; then
361+
var_value="${(P)var_name}"
362+
else
363+
var_value="${!var_name}"
364+
fi
365+
COMPREPLY=( $(compgen -W "${var_value}" -S ' ' -- ${cur}) )
339366
fi
340367
done
341368

dist/src/main/distro/bin/mvnd-bash-completion.bash

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,26 @@
1717
# Adapted from https://github.com/juven/maven-bash-completion/blob/master/bash_completion.bash by Juven Xu and others
1818
# under Apache License Version 2.0
1919

20+
# Detect shell type and set up zsh compatibility if needed
21+
if [ -n "$ZSH_VERSION" ]; then
22+
__MVND_SHELL="zsh"
23+
# Load bashcompinit for bash-style completions in zsh
24+
autoload -Uz bashcompinit 2>/dev/null && bashcompinit
25+
# Define COMP_WORDBREAKS if not set (bash sets this automatically)
26+
[[ -z "$COMP_WORDBREAKS" ]] && COMP_WORDBREAKS=$' \t\n"\'><=;|&(:'
27+
else
28+
__MVND_SHELL="bash"
29+
fi
30+
2031
function_exists()
2132
{
22-
declare -F $1 > /dev/null
23-
return $?
33+
if [ "$__MVND_SHELL" = "zsh" ]; then
34+
typeset -f $1 > /dev/null 2>&1
35+
return $?
36+
else
37+
declare -F $1 > /dev/null
38+
return $?
39+
fi
2440
}
2541

2642
# This function can be used to access a tokenized list of words
@@ -288,7 +304,12 @@ _mvnd()
288304
local plugin_goals_formatter="formatter:format|formatter:help|formatter:validate"
289305

290306
## some plugin (like jboss-as) has '-' which is not allowed in shell var name, to use '_' then replace
291-
local common_plugins=`compgen -v | grep "^plugin_goals_.*" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|'`
307+
local common_plugins
308+
if [ "$__MVND_SHELL" = "zsh" ]; then
309+
common_plugins=$(typeset + | grep "^plugin_goals_" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|')
310+
else
311+
common_plugins=`compgen -v | grep "^plugin_goals_.*" | sed 's/plugin_goals_//g' | tr '_' '-' | tr '\n' '|'`
312+
fi
292313

293314
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}"
294315

@@ -334,8 +355,14 @@ _mvnd()
334355
for plugin in $common_plugins; do
335356
if [[ ${cur} == ${plugin}:* ]]; then
336357
## note that here is an 'unreplace', see the comment at common_plugins
337-
var_name="plugin_goals_${plugin//-/_}"
338-
COMPREPLY=( $(compgen -W "${!var_name}" -S ' ' -- ${cur}) )
358+
local var_name="plugin_goals_${plugin//-/_}"
359+
local var_value
360+
if [ "$__MVND_SHELL" = "zsh" ]; then
361+
var_value="${(P)var_name}"
362+
else
363+
var_value="${!var_name}"
364+
fi
365+
COMPREPLY=( $(compgen -W "${var_value}" -S ' ' -- ${cur}) )
339366
fi
340367
done
341368

0 commit comments

Comments
 (0)