123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846 |
- # Bash auto-completion for west subcommands and flags. To initialize, run
- #
- # source west-completion.bash
- #
- # To make it persistent, add it to e.g. your .bashrc.
- __west_previous_extglob_setting=$(shopt -p extglob)
- shopt -s extglob
- # The following function is based on code from:
- #
- # bash_completion - programmable completion functions for bash 3.2+
- #
- # Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
- # © 2009-2010, Bash Completion Maintainers
- # <bash-completion-devel@lists.alioth.debian.org>
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2, or (at your option)
- # any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, see <http://www.gnu.org/licenses/>.
- #
- # The latest version of this software can be obtained here:
- #
- # http://bash-completion.alioth.debian.org/
- #
- # RELEASE: 2.x
- # This function can be used to access a tokenized list of words
- # on the command line:
- #
- # __git_reassemble_comp_words_by_ref '=:'
- # if test "${words_[cword_-1]}" = -w
- # then
- # ...
- # fi
- #
- # The argument should be a collection of characters from the list of
- # word completion separators (COMP_WORDBREAKS) to treat as ordinary
- # characters.
- #
- # This is roughly equivalent to going back in time and setting
- # COMP_WORDBREAKS to exclude those characters. The intent is to
- # make option types like --date=<type> and <rev>:<path> easy to
- # recognize by treating each shell word as a single token.
- #
- # It is best not to set COMP_WORDBREAKS directly because the value is
- # shared with other completion scripts. By the time the completion
- # function gets called, COMP_WORDS has already been populated so local
- # changes to COMP_WORDBREAKS have no effect.
- #
- # Output: words_, cword_, cur_.
- __west_reassemble_comp_words_by_ref()
- {
- local exclude i j first
- # Which word separators to exclude?
- exclude="${1//[^$COMP_WORDBREAKS]}"
- cword_=$COMP_CWORD
- if [ -z "$exclude" ]; then
- words_=("${COMP_WORDS[@]}")
- return
- fi
- # List of word completion separators has shrunk;
- # re-assemble words to complete.
- for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
- # Append each nonempty word consisting of just
- # word separator characters to the current word.
- first=t
- while
- [ $i -gt 0 ] &&
- [ -n "${COMP_WORDS[$i]}" ] &&
- # word consists of excluded word separators
- [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
- do
- # Attach to the previous token,
- # unless the previous token is the command name.
- if [ $j -ge 2 ] && [ -n "$first" ]; then
- ((j--))
- fi
- first=
- words_[$j]=${words_[j]}${COMP_WORDS[i]}
- if [ $i = $COMP_CWORD ]; then
- cword_=$j
- fi
- if (($i < ${#COMP_WORDS[@]} - 1)); then
- ((i++))
- else
- # Done.
- return
- fi
- done
- words_[$j]=${words_[j]}${COMP_WORDS[i]}
- if [ $i = $COMP_CWORD ]; then
- cword_=$j
- fi
- done
- }
- if ! type _get_comp_words_by_ref >/dev/null 2>&1; then
- _get_comp_words_by_ref ()
- {
- local exclude cur_ words_ cword_
- if [ "$1" = "-n" ]; then
- exclude=$2
- shift 2
- fi
- __west_reassemble_comp_words_by_ref "$exclude"
- cur_=${words_[cword_]}
- while [ $# -gt 0 ]; do
- case "$1" in
- cur)
- cur=$cur_
- ;;
- prev)
- prev=${words_[$cword_-1]}
- ;;
- words)
- words=("${words_[@]}")
- ;;
- cword)
- cword=$cword_
- ;;
- esac
- shift
- done
- }
- fi
- if ! type _tilde >/dev/null 2>&1; then
- # Perform tilde (~) completion
- # @return True (0) if completion needs further processing,
- # False (> 0) if tilde is followed by a valid username, completions
- # are put in COMPREPLY and no further processing is necessary.
- _tilde()
- {
- local result=0
- if [[ $1 == \~* && $1 != */* ]]; then
- # Try generate ~username completions
- COMPREPLY=( $( compgen -P '~' -u -- "${1#\~}" ) )
- result=${#COMPREPLY[@]}
- # 2>/dev/null for direct invocation, e.g. in the _tilde unit test
- [[ $result -gt 0 ]] && compopt -o filenames 2>/dev/null
- fi
- return $result
- }
- fi
- if ! type _quote_readline_by_ref >/dev/null 2>&1; then
- # This function quotes the argument in a way so that readline dequoting
- # results in the original argument. This is necessary for at least
- # `compgen' which requires its arguments quoted/escaped:
- #
- # $ ls "a'b/"
- # c
- # $ compgen -f "a'b/" # Wrong, doesn't return output
- # $ compgen -f "a\'b/" # Good
- # a\'b/c
- #
- # See also:
- # - http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
- # - http://www.mail-archive.com/bash-completion-devel@lists.alioth.\
- # debian.org/msg01944.html
- # @param $1 Argument to quote
- # @param $2 Name of variable to return result to
- _quote_readline_by_ref()
- {
- if [ -z "$1" ]; then
- # avoid quoting if empty
- printf -v $2 %s "$1"
- elif [[ $1 == \'* ]]; then
- # Leave out first character
- printf -v $2 %s "${1:1}"
- elif [[ $1 == \~* ]]; then
- # avoid escaping first ~
- printf -v $2 \~%q "${1:1}"
- else
- printf -v $2 %q "$1"
- fi
- # Replace double escaping ( \\ ) by single ( \ )
- # This happens always when argument is already escaped at cmdline,
- # and passed to this function as e.g.: file\ with\ spaces
- [[ ${!2} == *\\* ]] && printf -v $2 %s "${1//\\\\/\\}"
- # If result becomes quoted like this: $'string', re-evaluate in order to
- # drop the additional quoting. See also: http://www.mail-archive.com/
- # bash-completion-devel@lists.alioth.debian.org/msg01942.html
- [[ ${!2} == \$* ]] && eval $2=${!2}
- } # _quote_readline_by_ref()
- fi
- # This function turns on "-o filenames" behavior dynamically. It is present
- # for bash < 4 reasons. See http://bugs.debian.org/272660#64 for info about
- # the bash < 4 compgen hack.
- _compopt_o_filenames()
- {
- # We test for compopt availability first because directly invoking it on
- # bash < 4 at this point may cause terminal echo to be turned off for some
- # reason, see https://bugzilla.redhat.com/653669 for more info.
- type compopt &>/dev/null && compopt -o filenames 2>/dev/null || \
- compgen -f /non-existing-dir/ >/dev/null
- }
- if ! type _filedir >/dev/null 2>&1; then
- # This function performs file and directory completion. It's better than
- # simply using 'compgen -f', because it honours spaces in filenames.
- # @param $1 If `-d', complete only on directories. Otherwise filter/pick only
- # completions with `.$1' and the uppercase version of it as file
- # extension.
- #
- _filedir()
- {
- local IFS=$'\n'
- _tilde "$cur" || return
- local -a toks
- local x tmp
- x=$( compgen -d -- "$cur" ) &&
- while read -r tmp; do
- toks+=( "$tmp" )
- done <<< "$x"
- if [[ "$1" != -d ]]; then
- local quoted
- _quote_readline_by_ref "$cur" quoted
- # Munge xspec to contain uppercase version too
- # http://thread.gmane.org/gmane.comp.shells.bash.bugs/15294/focus=15306
- local xspec=${1:+"!*.@($1|${1^^})"}
- x=$( compgen -f -X "$xspec" -- $quoted ) &&
- while read -r tmp; do
- toks+=( "$tmp" )
- done <<< "$x"
- # Try without filter if it failed to produce anything and configured to
- [[ -n ${COMP_FILEDIR_FALLBACK:-} && -n "$1" && ${#toks[@]} -lt 1 ]] && \
- x=$( compgen -f -- $quoted ) &&
- while read -r tmp; do
- toks+=( "$tmp" )
- done <<< "$x"
- fi
- if [[ ${#toks[@]} -ne 0 ]]; then
- # 2>/dev/null for direct invocation, e.g. in the _filedir unit test
- _compopt_o_filenames
- COMPREPLY+=( "${toks[@]}" )
- fi
- } # _filedir()
- fi
- # Misc helpers taken from Docker:
- # https://github.com/docker/docker-ce/blob/master/components/cli/contrib/completion/bash/docker
- # __west_pos_first_nonflag finds the position of the first word that is neither
- # option nor an option's argument. If there are options that require arguments,
- # you should pass a glob describing those options, e.g. "--option1|-o|--option2"
- # Use this function to restrict completions to exact positions after the argument list.
- __west_pos_first_nonflag()
- {
- local argument_flags=$1
- local counter=$((${subcommand_pos:-${command_pos}} + 1))
- while [ "$counter" -le "$cword" ]; do
- if [ -n "$argument_flags" ] && eval "case '${words[$counter]}' in $argument_flags) true ;; *) false ;; esac"; then
- (( counter++ ))
- # eat "=" in case of --option=arg syntax
- [ "${words[$counter]}" = "=" ] && (( counter++ ))
- else
- case "${words[$counter]}" in
- -*)
- ;;
- *)
- break
- ;;
- esac
- fi
- # Bash splits words at "=", retaining "=" as a word, examples:
- # "--debug=false" => 3 words, "--log-opt syslog-facility=daemon" => 4 words
- while [ "${words[$counter + 1]}" = "=" ] ; do
- counter=$(( counter + 2))
- done
- (( counter++ ))
- done
- echo $counter
- }
- # __west_map_key_of_current_option returns `key` if we are currently completing the
- # value of a map option (`key=value`) which matches the extglob given as an argument.
- # This function is needed for key-specific completions.
- __west_map_key_of_current_option()
- {
- local glob="$1"
- local key glob_pos
- if [ "$cur" = "=" ] ; then # key= case
- key="$prev"
- glob_pos=$((cword - 2))
- elif [[ $cur == *=* ]] ; then # key=value case (OSX)
- key=${cur%=*}
- glob_pos=$((cword - 1))
- elif [ "$prev" = "=" ] ; then
- key=${words[$cword - 2]} # key=value case
- glob_pos=$((cword - 3))
- else
- return
- fi
- [ "${words[$glob_pos]}" = "=" ] && ((glob_pos--)) # --option=key=value syntax
- [[ ${words[$glob_pos]} == @($glob) ]] && echo "$key"
- }
- # __west_value_of_option returns the value of the first option matching `option_glob`.
- # Valid values for `option_glob` are option names like `--log-level` and globs like
- # `--log-level|-l`
- # Only positions between the command and the current word are considered.
- __west_value_of_option()
- {
- local option_extglob=$(__west_to_extglob "$1")
- local counter=$((command_pos + 1))
- while [ "$counter" -lt "$cword" ]; do
- case ${words[$counter]} in
- $option_extglob )
- echo "${words[$counter + 1]}"
- break
- ;;
- esac
- (( counter++ ))
- done
- }
- # __west_to_alternatives transforms a multiline list of strings into a single line
- # string with the words separated by `|`.
- # This is used to prepare arguments to __west_pos_first_nonflag().
- __west_to_alternatives()
- {
- local parts=( $1 )
- local IFS='|'
- echo "${parts[*]}"
- }
- # __west_to_extglob transforms a multiline list of options into an extglob pattern
- # suitable for use in case statements.
- __west_to_extglob()
- {
- local extglob=$( __west_to_alternatives "$1" )
- echo "@($extglob)"
- }
- __set_comp_dirs()
- {
- _filedir -d
- }
- __set_comp_files()
- {
- _filedir
- }
- # Sets completions for $cur, from the possibilities in $1..n
- __set_comp()
- {
- # "${*:1}" gives a single argument with arguments $1..n
- COMPREPLY=($(compgen -W "${*:1}" -- "$cur"))
- }
- __west_x()
- {
- west 2>/dev/null "$@"
- }
- __set_comp_west_projs()
- {
- __set_comp "$(__west_x list --format={name} "$@")"
- }
- __set_comp_west_boards()
- {
- __set_comp "$(__west_x boards --format={name} "$@")"
- }
- __comp_west_west()
- {
- case "$prev" in
- --zephyr-base|-z)
- __set_comp_dirs
- return
- ;;
- # We don't know how to autocomplete any others
- $(__west_to_extglob "$global_args_opts") )
- return
- ;;
- esac
- case "$cur" in
- -*)
- __set_comp $global_bool_opts $global_args_opts
- ;;
- *)
- local counter=$( __west_pos_first_nonflag "$(__west_to_extglob "$global_args_opts")" )
- if [ "$cword" -eq "$counter" ]; then
- __set_comp ${cmds[*]}
- fi
- ;;
- esac
- }
- __comp_west_init()
- {
- local init_args_opts="
- --manifest -m
- --manifest-rev --mr
- --local -l
- "
- case "$prev" in
- --local|-l)
- __set_comp_dirs
- return
- ;;
- esac
- case "$cur" in
- -*)
- __set_comp $init_args_opts
- ;;
- esac
- }
- __comp_west_update()
- {
- local update_bool_opts="
- --keep-descendants -k
- --rebase -r
- "
- case "$cur" in
- -*)
- __set_comp $update_bool_opts
- ;;
- *)
- __set_comp_west_projs
- ;;
- esac
- }
- __comp_west_list()
- {
- local list_args_opts="
- --format -f
- "
- case "$prev" in
- # We don't know how to autocomplete those
- $(__west_to_extglob "$list_args_opts") )
- return
- ;;
- esac
- case "$cur" in
- -*)
- __set_comp $list_args_opts
- ;;
- *)
- __set_comp_west_projs
- ;;
- esac
- }
- __comp_west_manifest()
- {
- local manifest_bool_opts="
- --freeze
- "
- local manifest_args_opts="
- --out -o
- "
- case "$prev" in
- --out|-o)
- __set_comp_files
- return
- ;;
- esac
- case "$cur" in
- -*)
- __set_comp $manifest_bool_opts $manifest_args_opts
- ;;
- esac
- }
- __comp_west_diff()
- {
- case "$cur" in
- *)
- __set_comp_west_projs
- ;;
- esac
- }
- __comp_west_status()
- {
- case "$cur" in
- *)
- __set_comp_west_projs
- ;;
- esac
- }
- __comp_west_forall()
- {
- local forall_args_opts="
- -c
- "
- case "$prev" in
- # We don't know how to autocomplete those
- $(__west_to_extglob "$forall_args_opts") )
- return
- ;;
- esac
- case "$cur" in
- -*)
- __set_comp $forall_args_opts
- ;;
- *)
- __set_comp_west_projs
- ;;
- esac
- }
- __comp_west_config()
- {
- local config_bool_opts="
- --global
- --local
- --system
- "
- case "$cur" in
- -*)
- __set_comp $config_bool_opts
- ;;
- esac
- }
- __comp_west_help()
- {
- case "$cur" in
- *)
- local counter=$( __west_pos_first_nonflag "$(__west_to_extglob "$global_args_opts")" )
- if [ "$cword" -eq "$counter" ]; then
- __set_comp ${cmds[*]}
- fi
- ;;
- esac
- }
- # Zephyr extension commands
- __comp_west_completion()
- {
- case "$cur" in
- *)
- local counter=$( __west_pos_first_nonflag "$(__west_to_extglob "$global_args_opts")" )
- if [ "$cword" -eq "$counter" ]; then
- __set_comp "bash"
- fi
- ;;
- esac
- }
- __comp_west_boards()
- {
- local boards_args_opts="
- --format -f --name -n
- --arch-root --board-root
- "
- case "$prev" in
- --format|-f|--name|-n)
- # We don't know how to autocomplete these.
- return
- ;;
- --arch-root)
- __set_comp_dirs
- return
- ;;
- --board-root)
- __set_comp_dirs
- return
- ;;
- esac
- case "$cur" in
- -*)
- __set_comp $boards_args_opts
- ;;
- esac
- }
- __comp_west_build()
- {
- local build_bool_opts="
- --cmake -c
- --cmake-only
- -n --just-print --dry-run --recon
- --force -f
- "
- local build_args_opts="
- --board -b
- --build-dir -d
- --target -t
- --pristine -p
- --build-opt -o
- "
- case "$prev" in
- --board|-b)
- __set_comp_west_boards
- return
- ;;
- --build-dir|-d)
- __set_comp_dirs
- return
- ;;
- --pristine|-p)
- __set_comp "auto always never"
- return
- ;;
- # We don't know how to autocomplete those
- $(__west_to_extglob "$build_args_opts") )
- return
- ;;
- esac
- case "$cur" in
- -*)
- __set_comp $build_bool_opts $build_args_opts
- ;;
- *)
- __set_comp_dirs
- ;;
- esac
- }
- __comp_west_sign()
- {
- local sign_bool_opts="
- --force -f
- --bin --no-bin
- --hex --no-hex
- "
- local sign_args_opts="
- --build-dir -d
- --tool -t
- --tool-path -p
- -B --sbin
- -H --shex
- "
- case "$prev" in
- --build-dir|-d|--tool-path|-p)
- __set_comp_dirs
- return
- ;;
- --tool|-t)
- __set_comp "imgtool"
- return
- ;;
- -B|--sbin|-H|--shex)
- __set_comp_files
- return
- ;;
- esac
- case "$cur" in
- -*)
- __set_comp $sign_bool_opts $sign_args_opts
- ;;
- esac
- }
- __comp_west_runner_cmd()
- {
- # Common arguments for runners
- local runner_bool_opts="
- --context -H
- --skip-rebuild
- "
- local runner_args_opts="
- --build-dir -d
- --cmake-cache -c
- --runner -r
- --board-dir
- --elf-file
- --hex-file
- --bin-file
- --gdb
- --openocd
- --openocd-search
- "
- case "$prev" in
- --build-dir|-d|--cmake-cache|-c|--board-dir|--gdb|--openocd|--openocd-search)
- __set_comp_dirs
- return
- ;;
- --elf-file|--hex-file|--bin-file)
- __set_comp_files
- return
- ;;
- esac
- case "$cur" in
- -*)
- __set_comp $runner_bool_opts $runner_args_opts
- ;;
- esac
- }
- __comp_west_flash()
- {
- __comp_west_runner_cmd
- }
- __comp_west_debug()
- {
- __comp_west_runner_cmd
- }
- __comp_west_debugserver()
- {
- __comp_west_runner_cmd
- }
- __comp_west_attach()
- {
- __comp_west_runner_cmd
- }
- __comp_west()
- {
- local previous_extglob_setting=$(shopt -p extglob)
- shopt -s extglob
- # Reset to default, to make sure compgen works properly
- local IFS=$' \t\n'
- local builtin_cmds=(
- init
- update
- list
- manifest
- diff
- status
- forall
- config
- help
- )
- local zephyr_ext_cmds=(
- completion
- boards
- build
- sign
- flash
- debug
- debugserver
- attach
- zephyr-export
- )
- local cmds=(${builtin_cmds[*]} ${zephyr_ext_cmds[*]})
- # Global options for all commands
- local global_bool_opts="
- --help -h
- --verbose -v
- --version -V
- "
- local global_args_opts="
- --zephyr-base -z
- "
- COMPREPLY=()
- local cur words cword prev
- _get_comp_words_by_ref -n : cur words cword prev
- local command='west' command_pos=0
- local counter=1
- while [ "$counter" -lt "$cword" ]; do
- case "${words[$counter]}" in
- west)
- return 0
- ;;
- $(__west_to_extglob "$global_args_opts") )
- (( counter++ ))
- ;;
- -*)
- ;;
- =)
- (( counter++ ))
- ;;
- *)
- command="${words[$counter]}"
- command_pos=$counter
- break
- ;;
- esac
- (( counter++ ))
- done
- # Construct the function name to be called
- local completions_func=__comp_west_${command//-/_}
- #echo "comp_func: ${completions_func}"
- declare -F $completions_func >/dev/null && $completions_func
- # Restore the user's extglob setting
- eval "$previous_extglob_setting"
- return 0
- }
- eval "$__west_previous_extglob_setting"
- unset __west_previous_extglob_setting
- complete -F __comp_west west
|