summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Scogland <scogland1@llnl.gov>2020-12-18 17:26:15 -0800
committerGitHub <noreply@github.com>2020-12-18 17:26:15 -0800
commit71c77fa8fa351f7ed94f914175456da5f432bc31 (patch)
tree4071960c79446cb8b7c874210f8fa54988d831c4
parent517413c1252304474b1b4629c70e26bbc4b7e1bb (diff)
downloadspack-71c77fa8fa351f7ed94f914175456da5f432bc31.tar.gz
spack-71c77fa8fa351f7ed94f914175456da5f432bc31.tar.bz2
spack-71c77fa8fa351f7ed94f914175456da5f432bc31.tar.xz
spack-71c77fa8fa351f7ed94f914175456da5f432bc31.zip
minimal zsh completion (#20253)
Since zsh can load bash completion files natively, seems reasonable to just turn this on. The only changes are to switch from `type -t` which zsh doesn't support to using `type` with a regex and adding a new arm to the sourcing of the completions to allow it to work for zsh as well as bash. Could use more bash/dash/etc testing probably, but everything I've thought to try has worked so far. Notes: * unit-test zsh support, fix issues Specifically fixed word splitting in completion-test, use a different method to apply sh emulation to zsh loaded bash completion, and fixed an incompatibility in regex operator quoting requirements. * compinit now ignores insecure directories Completion isn't meant to be enabled in non-interactive environments, so by default compinit will ask the user if they want to ignore insecure directories or load them anyway. To pass the spack unit tests in GH actions, this prompt must be disabled, so ignore explicitly until a better solution can be found. * debug functions test also requires bash emulation COMP_WORDS is a bash-ism that zsh doesn't natively support, turn on emulation for just that section of tests to allow the comparison to work. Does not change the behavior of the functions themselves since they are already pinned to sh emulation elsewhere. * propagate change to .in file * fix comment and update script based on .in
-rwxr-xr-xshare/spack/bash/spack-completion.in15
-rwxr-xr-xshare/spack/qa/completion-test.sh76
-rwxr-xr-xshare/spack/qa/run-shell-tests1
-rwxr-xr-xshare/spack/setup-env.sh2
-rwxr-xr-xshare/spack/spack-completion.bash15
5 files changed, 74 insertions, 35 deletions
diff --git a/share/spack/bash/spack-completion.in b/share/spack/bash/spack-completion.in
index 80ba94ed87..9aa890ed02 100755
--- a/share/spack/bash/spack-completion.in
+++ b/share/spack/bash/spack-completion.in
@@ -37,6 +37,17 @@
#
# See `man bash` for more details.
+if test -n "${ZSH_VERSION:-}" ; then
+ if [[ "$(emulate)" = zsh ]] ; then
+ # ensure base completion support is enabled, ignore insecure directories
+ autoload -U +X compinit && compinit -i
+ # ensure bash compatible completion support is enabled
+ autoload -U +X bashcompinit && bashcompinit
+ emulate sh -c "source '$0:A'"
+ return # stop interpreting file
+ fi
+fi
+
# Bash programmable completion for Spack
_bash_completion_spack() {
# In all following examples, let the cursor be denoted by brackets, i.e. []
@@ -117,7 +128,9 @@ _bash_completion_spack() {
#_test_vars >> temp
# Make sure function exists before calling it
- if [[ "$(type -t $subfunction)" == "function" ]]
+ local rgx #this dance is necessary to cover bash and zsh regex
+ rgx="$subfunction.*function.* "
+ if [[ "$(type $subfunction 2>&1)" =~ $rgx ]]
then
$subfunction
COMPREPLY=($(compgen -W "$SPACK_COMPREPLY" -- "$cur"))
diff --git a/share/spack/qa/completion-test.sh b/share/spack/qa/completion-test.sh
index 59a5181b98..64f07f69c4 100755
--- a/share/spack/qa/completion-test.sh
+++ b/share/spack/qa/completion-test.sh
@@ -31,13 +31,18 @@ title "Testing spack-completion.$_sp_shell with $_sp_shell"
succeeds which spack
title 'Testing all subcommands'
-while IFS= read -r line
+# read line into an array portably
+READ="read -ra line"
+if [ -n "${ZSH_VERSION:-}" ]; then
+ READ=(read -rA line)
+fi
+while IFS=' ' $READ
do
# Test that completion with no args works
- succeeds _spack_completions ${line[*]} ''
+ succeeds _spack_completions "${line[@]}" ''
# Test that completion with flags works
- contains '-h --help' _spack_completions ${line[*]} -
+ contains '-h --help' _spack_completions "${line[@]}" -
done <<- EOF
$(spack commands --aliases --format=subcommands)
EOF
@@ -58,32 +63,39 @@ contains 'hdf5' _spack_completions spack install -v ''
# XFAIL: Fails for Python 2.6 because pkg_resources not found?
#contains 'compilers.py' _spack_completions spack unit-test ''
-title 'Testing debugging functions'
-
-# This is a particularly tricky case that involves the following situation:
-# `spack -d [] install `
-# Here, [] represents the cursor, which is in the middle of the line.
-# We should tab-complete optional flags for `spack`, not optional flags for
-# `spack install` or package names.
-COMP_LINE='spack -d install '
-COMP_POINT=9
-COMP_WORDS=(spack -d install)
-COMP_CWORD=2
-COMP_KEY=9
-COMP_TYPE=64
-
-_bash_completion_spack
-contains "--all-help" echo "${COMPREPLY[@]}"
-
-contains "['spack', '-d', 'install', '']" _pretty_print COMP_WORDS[@]
-
-# Set the rest of the intermediate variables manually
-COMP_WORDS_NO_FLAGS=(spack install)
-COMP_CWORD_NO_FLAGS=1
-subfunction=_spack
-cur=
-
-list_options=true
-contains "'True'" _test_vars
-list_options=false
-contains "'False'" _test_vars
+_test_debug_functions() {
+ title 'Testing debugging functions'
+
+ if [ -n "${ZSH_VERSION:-}" ]; then
+ emulate -L sh
+ fi
+
+ # This is a particularly tricky case that involves the following situation:
+ # `spack -d [] install `
+ # Here, [] represents the cursor, which is in the middle of the line.
+ # We should tab-complete optional flags for `spack`, not optional flags for
+ # `spack install` or package names.
+ COMP_LINE='spack -d install '
+ COMP_POINT=9
+ COMP_WORDS=(spack -d install)
+ COMP_CWORD=2
+ COMP_KEY=9
+ COMP_TYPE=64
+
+ _bash_completion_spack
+ contains "--all-help" echo "${COMPREPLY[@]}"
+
+ contains "['spack', '-d', 'install', '']" _pretty_print COMP_WORDS[@]
+
+ # Set the rest of the intermediate variables manually
+ COMP_WORDS_NO_FLAGS=(spack install)
+ COMP_CWORD_NO_FLAGS=1
+ subfunction=_spack
+ cur=
+
+ list_options=true
+ contains "'True'" _test_vars
+ list_options=false
+ contains "'False'" _test_vars
+}
+_test_debug_functions
diff --git a/share/spack/qa/run-shell-tests b/share/spack/qa/run-shell-tests
index 9c5302ec89..310a824e42 100755
--- a/share/spack/qa/run-shell-tests
+++ b/share/spack/qa/run-shell-tests
@@ -43,6 +43,7 @@ fi
# Run the test scripts for their output (these will print nicely)
zsh "$QA_DIR/setup-env-test.sh"
+zsh "$QA_DIR/completion-test.sh"
dash "$QA_DIR/setup-env-test.sh"
# Run fish tests
diff --git a/share/spack/setup-env.sh b/share/spack/setup-env.sh
index 5761d16362..7f648207e4 100755
--- a/share/spack/setup-env.sh
+++ b/share/spack/setup-env.sh
@@ -371,7 +371,7 @@ _sp_multi_pathadd MODULEPATH "$_sp_tcl_roots"
# Add programmable tab completion for Bash
#
-if [ "$_sp_shell" = bash ]; then
+if test "$_sp_shell" = bash || test -n "${ZSH_VERSION:-}"; then
source $_sp_share_dir/spack-completion.bash
fi
diff --git a/share/spack/spack-completion.bash b/share/spack/spack-completion.bash
index 1761fcb60d..0143d305ca 100755
--- a/share/spack/spack-completion.bash
+++ b/share/spack/spack-completion.bash
@@ -37,6 +37,17 @@
#
# See `man bash` for more details.
+if test -n "${ZSH_VERSION:-}" ; then
+ if [[ "$(emulate)" = zsh ]] ; then
+ # ensure base completion support is enabled, ignore insecure directories
+ autoload -U +X compinit && compinit -i
+ # ensure bash compatible completion support is enabled
+ autoload -U +X bashcompinit && bashcompinit
+ emulate sh -c "source '$0:A'"
+ return # stop interpreting file
+ fi
+fi
+
# Bash programmable completion for Spack
_bash_completion_spack() {
# In all following examples, let the cursor be denoted by brackets, i.e. []
@@ -117,7 +128,9 @@ _bash_completion_spack() {
#_test_vars >> temp
# Make sure function exists before calling it
- if [[ "$(type -t $subfunction)" == "function" ]]
+ local rgx #this dance is necessary to cover bash and zsh regex
+ rgx="$subfunction.*function.* "
+ if [[ "$(type $subfunction 2>&1)" =~ $rgx ]]
then
$subfunction
COMPREPLY=($(compgen -W "$SPACK_COMPREPLY" -- "$cur"))