| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676 | #!/bin/bash## bash completion for docker-compose## This work is based on the completion for the docker command.## This script provides completion of:#  - commands and their options#  - service names#  - filepaths## To enable the completions either:#  - place this file in /etc/bash_completion.d#  or#  - copy this file to e.g. ~/.docker-compose-completion.sh and add the line#    below to your .bashrc after bash completion features are loaded#    . ~/.docker-compose-completion.sh__docker_compose_previous_extglob_setting=$(shopt -p extglob)shopt -s extglob__docker_compose_q() {	docker-compose 2>/dev/null "${top_level_options[@]}" "$@"}# Transforms a multiline list of strings into a single line string# with the words separated by "|".__docker_compose_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.__docker_compose_to_extglob() {	local extglob=$( __docker_compose_to_alternatives "$1" )	echo "@($extglob)"}# Determines whether the option passed as the first argument exist on# the commandline. The option may be a pattern, e.g. `--force|-f`.__docker_compose_has_option() {	local pattern="$1"	for (( i=2; i < $cword; ++i)); do		if [[ ${words[$i]} =~ ^($pattern)$ ]] ; then			return 0		fi	done	return 1}# Returns `key` if we are currently completing the value of a map option (`key=value`)# which matches the extglob passed in as an argument.# This function is needed for key-specific completions.__docker_compose_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"}# suppress trailing whitespace__docker_compose_nospace() {	# compopt is not available in ancient bash versions	type compopt &>/dev/null && compopt -o nospace}# Outputs a list of all defined services, regardless of their running state.# Arguments for `docker-compose ps` may be passed in order to filter the service list,# e.g. `status=running`.__docker_compose_services() {	__docker_compose_q ps --services "$@"}# Applies completion of services based on the current value of `$cur`.# Arguments for `docker-compose ps` may be passed in order to filter the service list,# see `__docker_compose_services`.__docker_compose_complete_services() {	COMPREPLY=( $(compgen -W "$(__docker_compose_services "$@")" -- "$cur") )}# The services for which at least one running container exists__docker_compose_complete_running_services() {	local names=$(__docker_compose_services --filter status=running)	COMPREPLY=( $(compgen -W "$names" -- "$cur") )}_docker_compose_build() {	case "$prev" in		--build-arg)			COMPREPLY=( $( compgen -e -- "$cur" ) )			__docker_compose_nospace			return			;;		--memory|-m)			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--build-arg --compress --force-rm --help --memory -m --no-cache --no-rm --pull --parallel -q --quiet" -- "$cur" ) )			;;		*)			__docker_compose_complete_services --filter source=build			;;	esac}_docker_compose_config() {	case "$prev" in		--hash)			if [[ $cur == \\* ]] ; then				COMPREPLY=( '\*' )			else				COMPREPLY=( $(compgen -W "$(__docker_compose_services) \\\* " -- "$cur") )			fi			return			;;	esac	COMPREPLY=( $( compgen -W "--hash --help --no-interpolate --profiles --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) )}_docker_compose_create() {	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--build --force-recreate --help --no-build --no-recreate" -- "$cur" ) )			;;		*)			__docker_compose_complete_services			;;	esac}_docker_compose_docker_compose() {	case "$prev" in		--tlscacert|--tlscert|--tlskey)			_filedir			return			;;		--file|-f)			_filedir "y?(a)ml"			return			;;		--ansi)			COMPREPLY=( $( compgen -W "never always auto" -- "$cur" ) )			return			;;		--log-level)			COMPREPLY=( $( compgen -W "debug info warning error critical" -- "$cur" ) )			return			;;		--profile)			COMPREPLY=( $( compgen -W "$(__docker_compose_q config --profiles)" -- "$cur" ) )			return			;;		--project-directory)			_filedir -d			return			;;		--env-file)			_filedir			return			;;		$(__docker_compose_to_extglob "$daemon_options_with_args") )			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "$daemon_boolean_options $daemon_options_with_args $top_level_options_with_args --help -h --no-ansi --verbose --version -v" -- "$cur" ) )			;;		*)			COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )			;;	esac}_docker_compose_down() {	case "$prev" in		--rmi)			COMPREPLY=( $( compgen -W "all local" -- "$cur" ) )			return			;;		--timeout|-t)			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help --rmi --timeout -t --volumes -v --remove-orphans" -- "$cur" ) )			;;	esac}_docker_compose_events() {	case "$prev" in		--json)			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help --json" -- "$cur" ) )			;;		*)			__docker_compose_complete_services			;;	esac}_docker_compose_exec() {	case "$prev" in		--index|--user|-u|--workdir|-w)			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "-d --detach --help --index --privileged -T --user -u --workdir -w" -- "$cur" ) )			;;		*)			__docker_compose_complete_running_services			;;	esac}_docker_compose_help() {	COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )}_docker_compose_images() {	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help --quiet -q" -- "$cur" ) )			;;		*)			__docker_compose_complete_services			;;	esac}_docker_compose_kill() {	case "$prev" in		-s)			COMPREPLY=( $( compgen -W "SIGHUP SIGINT SIGKILL SIGUSR1 SIGUSR2" -- "$(echo $cur | tr '[:lower:]' '[:upper:]')" ) )			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help -s" -- "$cur" ) )			;;		*)			__docker_compose_complete_running_services			;;	esac}_docker_compose_logs() {	case "$prev" in		--tail)			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--follow -f --help --no-color --no-log-prefix --tail --timestamps -t" -- "$cur" ) )			;;		*)			__docker_compose_complete_services			;;	esac}_docker_compose_pause() {	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )			;;		*)			__docker_compose_complete_running_services			;;	esac}_docker_compose_port() {	case "$prev" in		--protocol)			COMPREPLY=( $( compgen -W "tcp udp" -- "$cur" ) )			return;			;;		--index)			return;			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help --index --protocol" -- "$cur" ) )			;;		*)			__docker_compose_complete_services			;;	esac}_docker_compose_ps() {	local key=$(__docker_compose_map_key_of_current_option '--filter')	case "$key" in		source)			COMPREPLY=( $( compgen -W "build image" -- "${cur##*=}" ) )			return			;;		status)			COMPREPLY=( $( compgen -W "paused restarting running stopped" -- "${cur##*=}" ) )			return			;;	esac	case "$prev" in		--filter)			COMPREPLY=( $( compgen -W "source status" -S "=" -- "$cur" ) )			__docker_compose_nospace			return;			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--all -a --filter --help --quiet -q --services" -- "$cur" ) )			;;		*)			__docker_compose_complete_services			;;	esac}_docker_compose_pull() {	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help --ignore-pull-failures --include-deps --no-parallel --quiet -q" -- "$cur" ) )			;;		*)			__docker_compose_complete_services --filter source=image			;;	esac}_docker_compose_push() {	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help --ignore-push-failures" -- "$cur" ) )			;;		*)			__docker_compose_complete_services			;;	esac}_docker_compose_restart() {	case "$prev" in		--timeout|-t)			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) )			;;		*)			__docker_compose_complete_running_services			;;	esac}_docker_compose_rm() {	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--force -f --help --stop -s -v" -- "$cur" ) )			;;		*)			if __docker_compose_has_option "--stop|-s" ; then				__docker_compose_complete_services			else				__docker_compose_complete_services --filter status=stopped			fi			;;	esac}_docker_compose_run() {	case "$prev" in		-e)			COMPREPLY=( $( compgen -e -- "$cur" ) )			__docker_compose_nospace			return			;;		--entrypoint|--label|-l|--name|--user|-u|--volume|-v|--workdir|-w)			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--detach -d --entrypoint -e --help --label -l --name --no-deps --publish -p --rm --service-ports -T --use-aliases --user -u --volume -v --workdir -w" -- "$cur" ) )			;;		*)			__docker_compose_complete_services			;;	esac}_docker_compose_scale() {	case "$prev" in		=)			COMPREPLY=("$cur")			return			;;		--timeout|-t)			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) )			;;		*)			COMPREPLY=( $(compgen -S "=" -W "$(__docker_compose_services)" -- "$cur") )			__docker_compose_nospace			;;	esac}_docker_compose_start() {	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )			;;		*)			__docker_compose_complete_services --filter status=stopped			;;	esac}_docker_compose_stop() {	case "$prev" in		--timeout|-t)			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) )			;;		*)			__docker_compose_complete_running_services			;;	esac}_docker_compose_top() {	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )			;;		*)			__docker_compose_complete_running_services			;;	esac}_docker_compose_unpause() {	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )			;;		*)			__docker_compose_complete_services --filter status=paused			;;	esac}_docker_compose_up() {	case "$prev" in		=)			COMPREPLY=("$cur")			return			;;		--exit-code-from)			__docker_compose_complete_services			return			;;		--scale)			COMPREPLY=( $(compgen -S "=" -W "$(__docker_compose_services)" -- "$cur") )			__docker_compose_nospace			return			;;		--timeout|-t)			return			;;	esac	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--abort-on-container-exit --always-recreate-deps --attach-dependencies --build -d --detach --exit-code-from --force-recreate --help --no-build --no-color --no-deps --no-log-prefix --no-recreate --no-start --renew-anon-volumes -V --remove-orphans --scale --timeout -t" -- "$cur" ) )			;;		*)			__docker_compose_complete_services			;;	esac}_docker_compose_version() {	case "$cur" in		-*)			COMPREPLY=( $( compgen -W "--short" -- "$cur" ) )			;;	esac}_docker_compose() {	local previous_extglob_setting=$(shopt -p extglob)	shopt -s extglob	local commands=(		build		config		create		down		events		exec		help		images		kill		logs		pause		port		ps		pull		push		restart		rm		run		scale		start		stop		top		unpause		up		version	)	# Options for the docker daemon that have to be passed to secondary calls to	# docker-compose executed by this script.	local daemon_boolean_options="		--skip-hostname-check		--tls		--tlsverify	"	local daemon_options_with_args="		--context -c		--env-file		--file -f		--host -H		--project-directory		--project-name -p		--tlscacert		--tlscert		--tlskey	"	# These options require special treatment when searching the command.	local top_level_options_with_args="		--ansi		--log-level		--profile	"	COMPREPLY=()	local cur prev words cword	_get_comp_words_by_ref -n : cur prev words cword	# search subcommand and invoke its handler.	# special treatment of some top-level options	local command='docker_compose'	local top_level_options=()	local counter=1	while [ $counter -lt $cword ]; do		case "${words[$counter]}" in			$(__docker_compose_to_extglob "$daemon_boolean_options") )				local opt=${words[counter]}				top_level_options+=($opt)				;;			$(__docker_compose_to_extglob "$daemon_options_with_args") )				local opt=${words[counter]}				local arg=${words[++counter]}				top_level_options+=($opt $arg)				;;			$(__docker_compose_to_extglob "$top_level_options_with_args") )				(( counter++ ))				;;			-*)				;;			*)				command="${words[$counter]}"				break				;;		esac		(( counter++ ))	done	local completions_func=_docker_compose_${command//-/_}	declare -F $completions_func >/dev/null && $completions_func	eval "$previous_extglob_setting"	return 0}eval "$__docker_compose_previous_extglob_setting"unset __docker_compose_previous_extglob_settingcomplete -F _docker_compose docker-compose docker-compose.exe
 |