# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other # Spack Project Developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) # NOTE: spack-completion.bash is auto-generated by: # # $ spack commands --aliases --format=bash # --header=bash/spack-completion.in --update=spack-completion.bash # # Please do not manually modify this file. # The following global variables are set by Bash programmable completion: # # COMP_CWORD: An index into ${COMP_WORDS} of the word containing the # current cursor position # COMP_KEY: The key (or final key of a key sequence) used to invoke # the current completion function # COMP_LINE: The current command line # COMP_POINT: The index of the current cursor position relative to the # beginning of the current command # COMP_TYPE: Set to an integer value corresponding to the type of # completion attempted that caused a completion function # to be called # COMP_WORDBREAKS: The set of characters that the readline library treats # as word separators when performing word completion # COMP_WORDS: An array variable consisting of the individual words in # the current command line # # The following global variable is used by Bash programmable completion: # # COMPREPLY: An array variable from which bash reads the possible # completions generated by a shell function invoked by the # programmable completion facility # # See `man bash` for more details. # Bash programmable completion for Spack _bash_completion_spack() { # In all following examples, let the cursor be denoted by brackets, i.e. [] # For our purposes, flags should not affect tab completion. For instance, # `spack install []` and `spack -d install --jobs 8 []` should both give the same # possible completions. Therefore, we need to ignore any flags in COMP_WORDS. local COMP_WORDS_NO_FLAGS=() local index=0 while [[ "$index" -lt "$COMP_CWORD" ]] do if [[ "${COMP_WORDS[$index]}" == [a-z]* ]] then COMP_WORDS_NO_FLAGS+=("${COMP_WORDS[$index]}") fi let index++ done # Options will be listed by a subfunction named after non-flag arguments. # For example, `spack -d install []` will call _spack_install # and `spack compiler add []` will call _spack_compiler_add local subfunction=$(IFS='_'; echo "_${COMP_WORDS_NO_FLAGS[*]}") # Translate dashes to underscores, as dashes are not permitted in # compatibility mode. See https://github.com/spack/spack/pull/4079 subfunction=${subfunction//-/_} # However, the word containing the current cursor position needs to be # added regardless of whether or not it is a flag. This allows us to # complete something like `spack install --keep-st[]` COMP_WORDS_NO_FLAGS+=("${COMP_WORDS[$COMP_CWORD]}") # Since we have removed all words after COMP_CWORD, we can safely assume # that COMP_CWORD_NO_FLAGS is simply the index of the last element local COMP_CWORD_NO_FLAGS=$((${#COMP_WORDS_NO_FLAGS[@]} - 1)) # There is no guarantee that the cursor is at the end of the command line # when tab completion is envoked. For example, in the following situation: # `spack -d [] install` # if the user presses the TAB key, a list of valid flags should be listed. # Note that we cannot simply ignore everything after the cursor. In the # previous scenario, the user should expect to see a list of flags, but # not of other subcommands. Obviously, `spack -d list install` would be # invalid syntax. To accomplish this, we use the variable list_options # which is true if the current word starts with '-' or if the cursor is # not at the end of the line. local list_options=false if [[ "${COMP_WORDS[$COMP_CWORD]}" == -* || "$COMP_POINT" -ne "${#COMP_LINE}" ]] then list_options=true fi # In general, when envoking tab completion, the user is not expecting to # see optional flags mixed in with subcommands or package names. Tab # completion is used by those who are either lazy or just bad at spelling. # If someone doesn't remember what flag to use, seeing single letter flags # in their results won't help them, and they should instead consult the # documentation. However, if the user explicitly declares that they are # looking for a flag, we can certainly help them out. # `spack install -[]` # and # `spack install --[]` # should list all flags and long flags, respectively. Furthermore, if a # subcommand has no non-flag completions, such as `spack arch []`, it # should list flag completions. local cur=${COMP_WORDS_NO_FLAGS[$COMP_CWORD_NO_FLAGS]} # If the cursor is in the middle of the line, like: # `spack -d [] install` # COMP_WORDS will not contain the empty character, so we have to add it. if [[ "${COMP_LINE:$COMP_POINT:1}" == " " ]] then cur="" fi # Uncomment this line to enable logging #_test_vars >> temp # Make sure function exists before calling it if [[ "$(type -t $subfunction)" == "function" ]] then $subfunction COMPREPLY=($(compgen -W "$SPACK_COMPREPLY" -- "$cur")) fi } # Helper functions for subcommands # Results of each query are cached via environment variables _subcommands() { if [[ -z "${SPACK_SUBCOMMANDS:-}" ]] then SPACK_SUBCOMMANDS="$(spack commands)" fi SPACK_COMPREPLY="$SPACK_SUBCOMMANDS" } _all_packages() { if [[ -z "${SPACK_ALL_PACKAGES:-}" ]] then SPACK_ALL_PACKAGES="$(spack list)" fi SPACK_COMPREPLY="$SPACK_ALL_PACKAGES" } _all_resource_hashes() { if [[ -z "${SPACK_ALL_RESOURCES_HASHES:-}" ]] then SPACK_ALL_RESOURCE_HASHES="$(spack resource list --only-hashes)" fi SPACK_COMPREPLY="$SPACK_ALL_RESOURCE_HASHES" } _installed_packages() { if [[ -z "${SPACK_INSTALLED_PACKAGES:-}" ]] then SPACK_INSTALLED_PACKAGES="$(spack --color=never find --no-groups)" fi SPACK_COMPREPLY="$SPACK_INSTALLED_PACKAGES" } _installed_compilers() { if [[ -z "${SPACK_INSTALLED_COMPILERS:-}" ]] then SPACK_INSTALLED_COMPILERS="$(spack compilers | egrep -v "^(-|=)")" fi SPACK_COMPREPLY="$SPACK_INSTALLED_COMPILERS" } _providers() { if [[ -z "${SPACK_PROVIDERS:-}" ]] then SPACK_PROVIDERS="$(spack providers)" fi SPACK_COMPREPLY="$SPACK_PROVIDERS" } _mirrors() { if [[ -z "${SPACK_MIRRORS:-}" ]] then SPACK_MIRRORS="$(spack mirror list | awk '{print $1}')" fi SPACK_COMPREPLY="$SPACK_MIRRORS" } _repos() { if [[ -z "${SPACK_REPOS:-}" ]] then SPACK_REPOS="$(spack repo list | awk '{print $1}')" fi SPACK_COMPREPLY="$SPACK_REPOS" } _tests() { if [[ -z "${SPACK_TESTS:-}" ]] then SPACK_TESTS="$(spack test -l)" fi SPACK_COMPREPLY="$SPACK_TESTS" } _environments() { if [[ -z "${SPACK_ENVIRONMENTS:-}" ]] then SPACK_ENVIRONMENTS="$(spack env list)" fi SPACK_COMPREPLY="$SPACK_ENVIRONMENTS" } _keys() { if [[ -z "${SPACK_KEYS:-}" ]] then SPACK_KEYS="$(spack gpg list)" fi SPACK_COMPREPLY="$SPACK_KEYS" } _config_sections() { if [[ -z "${SPACK_CONFIG_SECTIONS:-}" ]] then SPACK_CONFIG_SECTIONS="compilers mirrors repos packages modules config upstreams" fi SPACK_COMPREPLY="$SPACK_CONFIG_SECTIONS" } _extensions() { if [[ -z "${SPACK_EXTENSIONS:-}" ]] then SPACK_EXTENSIONS="aspell go-bootstrap go icedtea jdk kim-api lua matlab mofem-cephas octave openjdk perl python r ruby rust tcl yorick" fi SPACK_COMPREPLY="$SPACK_EXTENSIONS" } # Testing functions # Function for unit testing tab completion # Syntax: _spack_completions spack install py- _spack_completions() { local COMP_CWORD COMP_KEY COMP_LINE COMP_POINT COMP_TYPE COMP_WORDS COMPREPLY # Set each variable the way bash would COMP_LINE="$*" COMP_POINT=${#COMP_LINE} COMP_WORDS=("$@") if [[ ${COMP_LINE: -1} == ' ' ]] then COMP_WORDS+=('') fi COMP_CWORD=$((${#COMP_WORDS[@]} - 1)) COMP_KEY=9 # ASCII 09: Horizontal Tab COMP_TYPE=64 # ASCII 64: '@', to list completions if the word is not unmodified # Run Spack's tab completion function _bash_completion_spack # Return the result echo "${COMPREPLY[@]:-}" } # Log the environment variables used # Syntax: _test_vars >> temp _test_vars() { echo "-----------------------------------------------------" echo "Variables set by bash:" echo echo "COMP_LINE: '$COMP_LINE'" echo "# COMP_LINE: '${#COMP_LINE}'" echo "COMP_WORDS: $(_pretty_print COMP_WORDS[@])" echo "# COMP_WORDS: '${#COMP_WORDS[@]}'" echo "COMP_CWORD: '$COMP_CWORD'" echo "COMP_KEY: '$COMP_KEY'" echo "COMP_POINT: '$COMP_POINT'" echo "COMP_TYPE: '$COMP_TYPE'" echo "COMP_WORDBREAKS: '$COMP_WORDBREAKS'" echo echo "Intermediate variables:" echo echo "COMP_WORDS_NO_FLAGS: $(_pretty_print COMP_WORDS_NO_FLAGS[@])" echo "# COMP_WORDS_NO_FLAGS: '${#COMP_WORDS_NO_FLAGS[@]}'" echo "COMP_CWORD_NO_FLAGS: '$COMP_CWORD_NO_FLAGS'" echo echo "Subfunction: '$subfunction'" if $list_options then echo "List options: 'True'" else echo "List options: 'False'" fi echo "Current word: '$cur'" } # Pretty-prints one or more arrays # Syntax: _pretty_print array1[@] ... _pretty_print() { for arg in $@ do local array=("${!arg}") printf "$arg: [" printf "'%s'" "${array[0]}" printf ", '%s'" "${array[@]:1}" echo "]" done } complete -o bashdefault -o default -F _bash_completion_spack spack # Spack commands # # Everything below here is auto-generated.