#!/bin/bash # # bash completion file for core atomic commands # copied from the docker bash completion # # # This script provides completion of: # - commands and their options # - container ids and names # - image repos and tags # - filepaths # # To enable the completions either: # - place this file in /etc/bash_completion.d # or # - copy this file to e.g. ~/.atomic-completion.sh and add the line # below to your .bashrc after bash completion features are loaded # . ~/.atomic-completion.sh # # Note: # Currently, the completions will not work if the atomic daemon is not # bound to the default communication port/socket # If the atomic daemon is using a unix socket for communication your user # must have access to the socket for the completions to function correctly # # Note for developers: # Please arrange options sorted alphabetically by long name with the short # options immediately following their corresponding long form. # This order should be applied to lists, alternatives and code blocks. __atomic_previous_extglob_setting=$(shopt -p extglob) shopt -s extglob __docker_q() { docker=$(awk -F ": " '/^default_docker/ {print $2}' /etc/atomic.conf 2>/dev/null || echo docker) docker 2>/dev/null "$@" } _atomic_atomic() { local boolean_options=" --help -h --version -v --debug --assumeyes -y " case "$prev" in $main_options_with_args_glob ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$boolean_options $main_options_with_args" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) ) ;; esac } __atomic_containers_all() { local IFS=$'\n' local containers=( $(__docker_q ps -aq --no-trunc) ) if [ "$1" ]; then containers=( $(__docker_q inspect --format "{{if $1}}{{.Id}}{{end}}" "${containers[@]}") ) fi local names=( $(__docker_q inspect --format '{{.Name}}' "${containers[@]}") ) names=( "${names[@]#/}" ) # trim off the leading "/" from the container names unset IFS COMPREPLY=( $(compgen -W "${names[*]} ${containers[*]}" -- "$cur") ) } __atomic_containers_running() { __atomic_containers_all '.State.Running' } __atomic_containers_stopped() { __atomic_containers_all 'not .State.Running' } __atomic_containers_pauseable() { __atomic_containers_all 'and .State.Running (not .State.Paused)' } __atomic_containers_unpauseable() { __atomic_containers_all '.State.Paused' } __atomic_image_repos() { local repos="$(__docker_q images | awk 'NR>1 && $1 != "" { print $1 }')" COMPREPLY=( $(compgen -W "$repos" -- "$cur") ) } __atomic_image_repos_and_tags() { local reposAndTags="$(__docker_q images | awk 'NR>1 && $1 != "" { print $1; print $1":"$2 }')" COMPREPLY=( $(compgen -W "$reposAndTags" -- "$cur") ) __ltrim_colon_completions "$cur" } __atomic_system_containers_images() { local images="$(atomic images list --no-trunc -f type=system | awk 'NR>1 { if ($1 == ">" || $1 == "*") print $2; else print $1; }')" COMPREPLY+=( $(compgen -W "$images" -- "$cur") ) } __atomic_system_containers_containers() { local containers CHECKOUT_DIR=`test -e /etc/atomic.conf && grep "^checkout_path:" /etc/atomic.conf | cut -d' ' -f2` CHECKOUT_DIR=${CHECKOUT_DIR:-/var/lib/containers/atomic/} test -e ${CHECKOUT_DIR} && containers="$(ls -1 ${CHECKOUT_DIR} | grep -v \.[01]$)" || containers="" COMPREPLY+=( $(compgen -W "$containers" -- "$cur") ) } __atomic_system_containers_containers_running() { local containers=( $(atomic containers list --no-trunc -q -f runtime=runc) ) COMPREPLY+=( $(compgen -W "${containers[*]}" -- "$cur") ) } __atomic_image_repos_and_tags_and_ids() { local images if test $_system == "0"; then images="$(__docker_q images -a --no-trunc | awk 'NR>1 { print $3; if ($1 != "") { print $1; print $1":"$2 } }')" COMPREPLY=( $(compgen -W "$images" -- "$cur") ) else __atomic_system_containers_images fi __ltrim_colon_completions "$cur" } __atomic_containers_and_images() { __atomic_containers_all local containers=( "${COMPREPLY[@]}" ) __atomic_image_repos_and_tags_and_ids COMPREPLY+=( "${containers[@]}" ) __atomic_system_containers_images __atomic_system_containers_containers } __atomic_pos_first_nonflag() { local argument_flags=$1 local counter=$cpos while [ $counter -le $cword ]; do if [ -n "$argument_flags" ] && eval "case '${words[$counter]}' in $argument_flags) true ;; *) false ;; esac"; then (( counter++ )) else case "${words[$counter]}" in -*) ;; *) break ;; esac fi (( counter++ )) done echo $counter } # Transforms a multiline list of strings into a single line string # with the words separated by "|". # This is used to prepare arguments to __atomic_pos_first_nonflag(). __atomic_to_alternatives() { local parts=( $1 ) local IFS='|' echo "${parts[*]}" } # Transforms a multiline list of options into an extglob pattern # suitable for use in case statements. __atomic_to_extglob() { local extglob=$( __atomic_to_alternatives "$1" ) echo "@($extglob)" } _atomic_images_help() { local counter=$(__atomic_pos_first_nonflag) if [ $cword -eq $counter ]; then COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) fi } _atomic_images_info() { local options_with_args=" --storage " local all_options="$options_with_args -h --help " case "$prev" in --storage) COMPREPLY=( $( compgen -W "docker ostree" -- "$cur" ) ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) __atomic_image_repos_and_tags ;; esac } # Subcommand processing. # Locates the first occurrence of any of the subcommands contained in the # first argument. In case of a match, calls the corresponding completion # function and returns 0. # If no match is found, 1 is returned. The calling function can then # continue processing its completion. # # TODO if the preceding command has options that accept arguments and an # argument is equal ot one of the subcommands, this is falsely detected as # a match. __atomic_subcommands() { local subcommands="$1" local counter=$(($command_pos + 1)) while [ $counter -lt $cword ]; do case "${words[$counter]}" in $(__atomic_to_extglob "$subcommands") ) subcommand_pos=$counter local subcommand=${words[$counter]} local completions_func=_atomic_${command}_${subcommand} declare -F $completions_func >/dev/null && $completions_func return 0 ;; esac (( counter++ )) done return 1 } _atomic_scan() { local options_with_args=" --fetch_cves " local all_options="$options_with_args --help -h --all --images --containers --rootfs --list --scanner --scan_type --verbose " [ "$command" = "scan" ] && all_options="$all_options" local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in $options_with_args_glob ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __atomic_pos_first_nonflag $( __atomic_to_alternatives "$options_with_args" ) ) if [ $cword -eq $counter ]; then __atomic_containers_and_images return 0 fi COMPREPLY=( $( compgen -d "$cur" ) ) return 0 ;; esac return 0 } _atomic_top() { local options_with_args=" --optional -o -d -n " local all_options="$options_with_args" [ "$command" = "top" ] && all_options="$all_options" local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) __atomic_containers_running ;; esac return 0 } _atomic_images_verify() { local options_with_args=" --storage " local all_options="$options_with_args -h --help --no-validate " case "$prev" in --storage) COMPREPLY=( $( compgen -W "docker ostree" -- "$cur" ) ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) __atomic_image_repos_and_tags ;; esac } _atomic_images_version() { local options_with_args=" --storage " local all_options="$options_with_args -r --recurse -h --help " case "$prev" in --storage) COMPREPLY=( $( compgen -W "docker ostree" -- "$cur" ) ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) __atomic_image_repos_and_tags __atomic_system_containers_images ;; esac } _atomic_pull() { local options_with_args=" -t --type --storage " local all_options="$options_with_args -h --help " case "$prev" in --storage) COMPREPLY=( $( compgen -W "docker ostree" -- "$cur" ) ) ;; -t | --type) COMPREPLY=( $( compgen -W "atomic docker" -- "$cur" ) ) ;; $options_with_args_glob ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; esac } _atomic_push() { local options_with_args=" -U --url -u --username -p --password -a --activation_key -r --repository_id --sign-by -t --type " local all_options="$options_with_args -h --help --pulp --satellite --verify_ssl --debug --all -a --force -f --help " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in -t | --type) COMPREPLY=( $( compgen -W "atomic docker" -- "$cur" ) ) ;; $options_with_args_glob ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) __atomic_image_repos_and_tags ;; esac } _atomic_containers() { local subcommands=" delete list trim " __atomic_subcommands "$subcommands" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac return 0 } _atomic_containers_delete() { local all_options="$options_with_args --all -a --force -f --help " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) __atomic_containers_all ;; esac } _atomic_containers_list() { local options_with_args=" --filter -f " local all_options="$options_with_args --all -a --help --json --noheading -n --no-trunc --quiet -q " local filterables=" id container image command created status runtime " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in $options_with_args_glob ) compopt -o nospace COMPREPLY=( $( compgen -S\= -W "$filterables" "$cur" ) ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; esac } _atomic_containers_trim() { local all_options=" --help " case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; esac } _atomic_update() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--force -f --set --container" -- "$cur" ) ) ;; *) if test $_container == "0"; then __atomic_image_repos_and_tags else __atomic_system_containers_containers fi ;; esac } _atomic_uninstall() { case "$cur" in -*) COMPREPLY=( $( compgen -W -- "$cur" ) ) ;; *) __atomic_containers_all __atomic_system_containers_containers ;; esac } _atomic_diff() { local all_options="$options_with_args --help --json --display --names-only --no-files -n --rpms -r --verbose -v " [ "$command" = "diff" ] && all_options="$all_options" case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __atomic_pos_first_nonflag $( __atomic_to_alternatives "$options_with_args" ) ) if [ $cword -eq $counter ]; then __atomic_image_repos_and_tags_and_ids fi ;; esac } _atomic_run() { local options_with_args=" --name -n " local all_options="$options_with_args --help --spc --display --quiet " [ "$command" = "run" ] && all_options="$all_options" local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in $options_with_args_glob ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __atomic_pos_first_nonflag $( __atomic_to_alternatives "$options_with_args" ) ) if [ $cword -eq $counter ]; then __atomic_containers_and_images fi ;; esac } _atomic_install() { local options_with_args=" --name -n " local all_options="$options_with_args --help --display --rootfs --system --set --user " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in $options_with_args_glob ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) if test $_system == "0"; then __atomic_image_repos_and_tags_and_ids else __atomic_system_containers_images fi ;; esac } _atomic_images() { local subcommands=" delete generate help info list prune version verify " __atomic_subcommands "$subcommands" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac return 0 } _atomic_images_list() { local options_with_args=" --filter -f " local all_options="$options_with_args --all -a --help -h --noheading -n --no-trunc --quiet -q --json " local filterables=" repo tag id image created size type " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in $options_with_args_glob ) compopt -o nospace COMPREPLY=( $( compgen -S\= -W "$filterables" "$cur" ) ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; esac } _atomic_images_delete() { local options_with_args=" --storage " local all_options="$options_with_args --force -f --help -h --remote " case "$prev" in --storage) COMPREPLY=( $( compgen -W "docker ostree" -- "$cur" ) ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) __atomic_image_repos_and_tags __atomic_system_containers_images ;; esac } _atomic_sign() { local options_with_args=" --sign-by -d --directory -g, --gnupghome " local all_options="$options_with_args --help -h " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in "-d"|"--directory") COMPREPLY=( $( compgen -d "$cur" ) ) return 0 ;; "-g"|"--gnupghome") COMPREPLY=( $( compgen -d "$cur" ) ) return 0 ;; $options_with_args_glob ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __atomic_pos_first_nonflag $( __atomic_to_alternatives "$options_with_args" ) ) if [ $cword -eq $counter ]; then __atomic_containers_and_images return 0 fi COMPREPLY=( $( compgen -d "$cur" ) ) return 0 ;; esac return 0 } _atomic_trust() { local subcommands=" add delete default show " __atomic_subcommands "$subcommands" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac return 0 } _atomic_trust_default() { local subcommands=" accept reject " local all_options="$options_with_args --help -h " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac } _atomic_trust_add() { local options_with_args=" --pubkeys -k --sigstoretype --type -t --keytype --sigstore -s " local all_options="$options_with_args --help -h " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in --keytype) COMPREPLY=( $( compgen -W "GPGKeys" -- "$cur" ) ) ;; --sigstoretype) COMPREPLY=( $( compgen -W "atomic local web" -- "$cur" ) ) ;; --type|-t) COMPREPLY=( $( compgen -W "signedBy insecureAcceptAnything reject" -- "$cur" ) ) ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __atomic_pos_first_nonflag $( __atomic_to_alternatives "$options_with_args" ) ) ;; esac } _atomic_trust_show() { local all_options="$options_with_args -j --json --raw " case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; esac } _atomic_trust_delete() { local options_with_args=" --sigstoretype " local all_options="$options_with_args --help -h --sigstore " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in --sigstoretype) COMPREPLY=( $( compgen -W "atomic local web" -- "$cur" ) ) ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __atomic_pos_first_nonflag $( __atomic_to_alternatives "$options_with_args" ) ) ;; esac } _atomic_mount() { local options_with_args=" --options -o --storage " local all_options="$options_with_args --help -h --live --shared " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in --storage) COMPREPLY=( $( compgen -W "docker ostree" -- "$cur" ) ) return 0 ;; $options_with_args_glob ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __atomic_pos_first_nonflag $( __atomic_to_alternatives "$options_with_args" ) ) if [ $cword -eq $counter ]; then __atomic_containers_and_images return 0 fi COMPREPLY=( $( compgen -d "$cur" ) ) return 0 ;; esac return 0 } _atomic_upload() { local options_with_args=" --URL -U --username -u --password -p --repo_id --repository_id --activation_key -a " local all_options="$options_with_args --help -h --pulp --satellite --verify_ssl --debug " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in $options_with_args_glob ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __atomic_pos_first_nonflag $( __atomic_to_alternatives "$options_with_args" ) ) if [ $cword -eq $counter ]; then __atomic_containers_and_images return 0 fi COMPREPLY=( $( compgen -d "$cur" ) ) return 0 ;; esac return 0 } _atomic_unmount() { case "$prev" in "unmount") COMPREPLY=( $( compgen -d "$cur" ) ) return 0 ;; esac return 0 } _atomic_stop() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--name -n" -- "$cur" ) ) ;; *) __atomic_containers_running __atomic_system_containers_containers_running ;; esac } _atomic_host_deploy() { case "$cur" in -*) COMPREPLY=( $( compgen -W "-r --reboot --os --preview -h --help" -- "$cur" ) ) ;; *) ;; esac } _atomic_host_rollback() { case "$cur" in -*) COMPREPLY=( $( compgen -W "-r --reboot -h --help" -- "$cur" ) ) ;; *) ;; esac } _atomic_host_status() { case "$cur" in -*) COMPREPLY=( $( compgen -W "-j --json -p --pretty -h --help" -- "$cur" ) ) ;; *) ;; esac } _atomic_host_upgrade() { case "$cur" in -*) COMPREPLY=( $( compgen -W "-r --reboot --os --allow-downgrade --check-diff -h --help" -- "$cur" ) ) ;; *) ;; esac } _atomic_host_unlock() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--hotfix -h --help" -- "$cur" ) ) ;; *) ;; esac } _atomic_host_host() { local boolean_options=" --help -h " case "$prev" in $main_options_with_args_glob ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$boolean_options $main_options_with_args" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) ) ;; esac } _atomic_images_help() { case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __atomic_pos_first_nonflag $( __atomic_to_alternatives "$options_with_args" ) ) if [ $cword -eq $counter ]; then __atomic_containers_and_images return 0 fi COMPREPLY=( $( compgen -d "$cur" ) ) return 0 ;; esac return 0 } _atomic_host() { local commands=( deploy rollback status upgrade unlock ) local completions_func=_atomic_host_${prev} declare -F $completions_func >/dev/null && $completions_func return 0 } _atomic_storage() { local subcommands=" export import reset modify " __atomic_subcommands "$subcommands" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac return 0 } _atomic_storage_modify() { local options_with_args=" --driver --add-device " local all_options="$options_with_args --help -h " local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") case "$prev" in --add-device) COMPREPLY=( $( compgen -f "/dev/" ) ) return 0 ;; --driver) COMPREPLY=( $( compgen -W "devicemapper overlay" -- "$cur" ) ) return 0 ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; esac } _atomic_storage_storage() { local boolean_options=" --help -h " case "$prev" in $main_options_with_args_glob ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$boolean_options $main_options_with_args" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) ) ;; esac } _atomic_storage_export() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--graph --dir -h --help" -- "$cur" ) ) ;; *) ;; esac } _atomic_storage_import() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--graph --dir -h --help" -- "$cur" ) ) ;; *) ;; esac } _atomic_no_opts() { case "$cur" in -*) COMPREPLY=( $( compgen -W "$main_options_with_args" -- "$cur" ) ) ;; *) ;; esac } _atomic_cluster_create() { _atomic_no_opts } _atomic_cluster_delete() { _atomic_no_opts } _atomic_cluster_get() { _atomic_no_opts } _atomic_cluster_list() { _atomic_no_opts } _atomic_cluster_deploy_start() { _atomic_no_opts } _atomic_cluster_deploy_status() { _atomic_no_opts } _atomic_cluster_restart_start() { _atomic_no_opts } _atomic_cluster_restart_status() { _atomic_no_opts } _atomic_cluster_upgrade_start() { _atomic_no_opts } _atomic_cluster_upgrade_status() { _atomic_no_opts } _atomic_cluster() { local commands=() local completions_func=_atomic_cluster_${prev} case "$prev" in cluster) commands=(create delete get list deploy restart upgrade) ;; deploy) commands=(start status) ;; restart) commands=(start status) ;; upgrade) commands=(start status) ;; start|status) if [ $cword -gt 2 ]; then local completions_func=_atomic_cluster_${words[$cword-2]}_${prev} fi ;; esac case "$cur" in -*) declare -F $completions_func >/dev/null && $completions_func ;; *) COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) ;; esac } _atomic_rhost_create() { case "$cur" in -*) COMPREPLY=( $( compgen -W "-c --cluster $main_options_with_args" -- "$cur" ) ) ;; *) ;; esac } _atomic_rhost_delete() { _atomic_no_opts } _atomic_rhost_get() { _atomic_no_opts } _atomic_rhost_list() { _atomic_no_opts } _atomic_rhost() { local commands=() local completions_func=_atomic_rhost_${prev} case "$prev" in rhost) commands=(create delete get list) ;; esac case "$cur" in -*) declare -F $completions_func >/dev/null && $completions_func ;; *) COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) ;; esac } _atomic() { local previous_extglob_setting=$(shopt -p extglob) shopt -s extglob local commands=( cluster containers host diff install images storage mount pull push rhost run scan sign stop top trust uninstall unmount update upload ) local main_options_with_args=" --help " local main_options_with_args_glob=$(__atomic_to_extglob "$main_options_with_args") COMPREPLY=() local cur prev words cword _get_comp_words_by_ref -n : cur prev words cword local command='atomic' cpos=0 local counter=1 _system=0 _container=0 while [ $counter -lt $cword ]; do if test "${words[$counter]}" == "--system"; then _system=1 break fi if test "${words[$counter]}" == "--container"; then _container=1 break fi (( counter++ )) done counter=1 while [ $counter -lt $cword ]; do case "${words[$counter]}" in $main_options_with_args_glob ) (( counter++ )) ;; "--system") _system=1;; -*) ;; *) command="${words[$counter]}" cpos=$counter (( cpos++ )) break ;; esac (( counter++ )) done local completions_func=_atomic_${command} declare -F $completions_func >/dev/null && $completions_func eval "$previous_extglob_setting" return 0 } complete -F _atomic atomic