diff --git a/contrib/completion/zsh/_docker-compose b/contrib/completion/zsh/_docker-compose index 9ac7e7560f..58105dc221 100644 --- a/contrib/completion/zsh/_docker-compose +++ b/contrib/completion/zsh/_docker-compose @@ -7,7 +7,7 @@ # ------------------------------------------------------------------------- # Version # ------- -# 0.1.0 +# 1.5.0 # ------------------------------------------------------------------------- # Authors # ------- @@ -37,40 +37,54 @@ __docker-compose_compose_file() { ___docker-compose_all_services_in_compose_file() { local already_selected local -a services - already_selected=$(echo ${words[@]} | tr " " "|") + already_selected=$(echo $words | tr " " "|") awk -F: '/^[a-zA-Z0-9]/{print $1}' "${compose_file:-$(__docker-compose_compose_file)}" 2>/dev/null | grep -Ev "$already_selected" } # All services, even those without an existing container __docker-compose_services_all() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 services=$(___docker-compose_all_services_in_compose_file) - _alternative "args:services:($services)" + _alternative "args:services:($services)" && ret=0 + + return ret } # All services that have an entry with the given key in their docker-compose.yml section ___docker-compose_services_with_key() { local already_selected local -a buildable - already_selected=$(echo ${words[@]} | tr " " "|") + already_selected=$(echo $words | tr " " "|") # flatten sections to one line, then filter lines containing the key and return section name. awk '/^[a-zA-Z0-9]/{printf "\n"};{printf $0;next;}' "${compose_file:-$(__docker-compose_compose_file)}" 2>/dev/null | awk -F: -v key=": +$1:" '$0 ~ key {print $1}' 2>/dev/null | grep -Ev "$already_selected" } # All services that are defined by a Dockerfile reference __docker-compose_services_from_build() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 buildable=$(___docker-compose_services_with_key build) - _alternative "args:buildable services:($buildable)" + _alternative "args:buildable services:($buildable)" && ret=0 + + return ret } # All services that are defined by an image __docker-compose_services_from_image() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 pullable=$(___docker-compose_services_with_key image) - _alternative "args:pullable services:($pullable)" + _alternative "args:pullable services:($pullable)" && ret=0 + + return ret } __docker-compose_get_services() { - local kind expl - declare -a running stopped lines args services + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local kind + declare -a running paused stopped lines args services docker_status=$(docker ps > /dev/null 2>&1) if [ $? -ne 0 ]; then @@ -80,64 +94,78 @@ __docker-compose_get_services() { kind=$1 shift - [[ $kind = (stopped|all) ]] && args=($args -a) + [[ $kind =~ (stopped|all) ]] && args=($args -a) - lines=(${(f)"$(_call_program commands docker ps ${args})"}) - services=(${(f)"$(_call_program commands docker-compose 2>/dev/null ${compose_file:+-f $compose_file} ${compose_project:+-p $compose_project} ps -q)"}) + lines=(${(f)"$(_call_program commands docker ps $args)"}) + services=(${(f)"$(_call_program commands docker-compose 2>/dev/null $compose_options ps -q)"}) # Parse header line to find columns local i=1 j=1 k header=${lines[1]} declare -A begin end - while (( $j < ${#header} - 1 )) { - i=$(( $j + ${${header[$j,-1]}[(i)[^ ]]} - 1)) - j=$(( $i + ${${header[$i,-1]}[(i) ]} - 1)) - k=$(( $j + ${${header[$j,-1]}[(i)[^ ]]} - 2)) - begin[${header[$i,$(($j-1))]}]=$i - end[${header[$i,$(($j-1))]}]=$k - } + while (( j < ${#header} - 1 )); do + i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 )) + j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 )) + k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 )) + begin[${header[$i,$((j-1))]}]=$i + end[${header[$i,$((j-1))]}]=$k + done lines=(${lines[2,-1]}) # Container ID local line s name local -a names for line in $lines; do - if [[ $services == *"${line[${begin[CONTAINER ID]},${end[CONTAINER ID]}]%% ##}"* ]]; then + if [[ ${services[@]} == *"${line[${begin[CONTAINER ID]},${end[CONTAINER ID]}]%% ##}"* ]]; then names=(${(ps:,:)${${line[${begin[NAMES]},-1]}%% *}}) for name in $names; do s="${${name%_*}#*_}:${(l:15:: :::)${${line[${begin[CREATED]},${end[CREATED]}]/ ago/}%% ##}}" s="$s, ${line[${begin[CONTAINER ID]},${end[CONTAINER ID]}]%% ##}" - s="$s, ${${${line[$begin[IMAGE],$end[IMAGE]]}/:/\\:}%% ##}" + s="$s, ${${${line[${begin[IMAGE]},${end[IMAGE]}]}/:/\\:}%% ##}" if [[ ${line[${begin[STATUS]},${end[STATUS]}]} = Exit* ]]; then stopped=($stopped $s) else + if [[ ${line[${begin[STATUS]},${end[STATUS]}]} = *\(Paused\)* ]]; then + paused=($paused $s) + fi running=($running $s) fi done fi done - [[ $kind = (running|all) ]] && _describe -t services-running "running services" running - [[ $kind = (stopped|all) ]] && _describe -t services-stopped "stopped services" stopped + [[ $kind =~ (running|all) ]] && _describe -t services-running "running services" running "$@" && ret=0 + [[ $kind =~ (paused|all) ]] && _describe -t services-paused "paused services" paused "$@" && ret=0 + [[ $kind =~ (stopped|all) ]] && _describe -t services-stopped "stopped services" stopped "$@" && ret=0 + + return ret +} + +__docker-compose_pausedservices() { + [[ $PREFIX = -* ]] && return 1 + __docker-compose_get_services paused "$@" } __docker-compose_stoppedservices() { + [[ $PREFIX = -* ]] && return 1 __docker-compose_get_services stopped "$@" } __docker-compose_runningservices() { + [[ $PREFIX = -* ]] && return 1 __docker-compose_get_services running "$@" } -__docker-compose_services () { +__docker-compose_services() { + [[ $PREFIX = -* ]] && return 1 __docker-compose_get_services all "$@" } __docker-compose_caching_policy() { - oldp=( "$1"(Nmh+1) ) # 1 hour + oldp=( "$1"(Nmh+1) ) # 1 hour (( $#oldp )) } -__docker-compose_commands () { +__docker-compose_commands() { local cache_policy zstyle -s ":completion:${curcontext}:" cache-policy cache_policy @@ -156,13 +184,14 @@ __docker-compose_commands () { _describe -t docker-compose-commands "docker-compose command" _docker_compose_subcommands } -__docker-compose_subcommand () { - local -a _command_args +__docker-compose_subcommand() { + local opts_help='(: -)--help[Print usage]' integer ret=1 + case "$words[1]" in (build) _arguments \ - '--help[Print usage]' \ + $opts_help \ '--no-cache[Do not use cache when building the image]' \ '*:services:__docker-compose_services_from_build' && ret=0 ;; @@ -171,24 +200,29 @@ __docker-compose_subcommand () { ;; (kill) _arguments \ - '--help[Print usage]' \ + $opts_help \ '-s[SIGNAL to send to the container. Default signal is SIGKILL.]:signal:_signals' \ '*:running services:__docker-compose_runningservices' && ret=0 ;; (logs) _arguments \ - '--help[Print usage]' \ + $opts_help \ '--no-color[Produce monochrome output.]' \ '*:services:__docker-compose_services_all' && ret=0 ;; (migrate-to-labels) _arguments -A '-*' \ - '--help[Print usage]' \ + $opts_help \ '(-):Recreate containers to add labels' && ret=0 ;; + (pause) + _arguments \ + $opts_help \ + '*:running services:__docker-compose_runningservices' && ret=0 + ;; (port) _arguments \ - '--help[Print usage]' \ + $opts_help \ '--protocol=-[tcp or udap (defaults to tcp)]:protocol:(tcp udp)' \ '--index=-[index of the container if there are mutiple instances of a service (defaults to 1)]:index: ' \ '1:running services:__docker-compose_runningservices' \ @@ -196,33 +230,33 @@ __docker-compose_subcommand () { ;; (ps) _arguments \ - '--help[Print usage]' \ + $opts_help \ '-q[Only display IDs]' \ '*:services:__docker-compose_services_all' && ret=0 ;; (pull) _arguments \ - '--help[Print usage]' \ + $opts_help \ '*:services:__docker-compose_services_from_image' && ret=0 ;; (rm) _arguments \ + $opts_help \ '(-f --force)'{-f,--force}"[Don't ask to confirm removal]" \ - '--help[Print usage]' \ '-v[Remove volumes associated with containers]' \ '*:stopped services:__docker-compose_stoppedservices' && ret=0 ;; (run) _arguments \ + $opts_help \ '-d[Detached mode: Run container in the background, print new container name.]' \ '--entrypoint[Overwrite the entrypoint of the image.]:entry point: ' \ '*-e[KEY=VAL Set an environment variable (can be used multiple times)]:environment variable KEY=VAL: ' \ - '--help[Print usage]' \ '(-u --user)'{-u,--user=-}'[Run as specified username or uid]:username or uid:_users' \ "--no-deps[Don't start linked services.]" \ '--rm[Remove container after run. Ignored in detached mode.]' \ - "--publish[Run command with manually mapped container's port(s) to the host.]" \ "--service-ports[Run command with the service's ports enabled and mapped to the host.]" \ + '(-p --publish)'{-p,--publish=-}"[Run command with manually mapped container's port(s) to the host.]" \ '-T[Disable pseudo-tty allocation. By default `docker-compose run` allocates a TTY.]' \ '(-):services:__docker-compose_services' \ '(-):command: _command_names -e' \ @@ -230,45 +264,52 @@ __docker-compose_subcommand () { ;; (scale) _arguments \ - '--help[Print usage]' \ + $opts_help \ + '(-t --timeout)'{-t,--timeout}"[Specify a shutdown timeout in seconds. (default: 10)]:seconds: " \ '*:running services:__docker-compose_runningservices' && ret=0 ;; (start) _arguments \ - '--help[Print usage]' \ + $opts_help \ '*:stopped services:__docker-compose_stoppedservices' && ret=0 ;; (stop|restart) _arguments \ - '--help[Print usage]' \ + $opts_help \ '(-t --timeout)'{-t,--timeout}"[Specify a shutdown timeout in seconds. (default: 10)]:seconds: " \ '*:running services:__docker-compose_runningservices' && ret=0 ;; + (unpause) + _arguments \ + $opts_help \ + '*:paused services:__docker-compose_pausedservices' && ret=0 + ;; (up) _arguments \ + $opts_help \ '-d[Detached mode: Run containers in the background, print new container names.]' \ - '--help[Print usage]' \ '--no-color[Produce monochrome output.]' \ "--no-deps[Don't start linked services.]" \ + "--force-recreate[Recreate containers even if their configuration and image haven't changed. Incompatible with --no-recreate.]" \ "--no-recreate[If containers already exist, don't recreate them.]" \ - "--force-recreate[Recreate containers even if their configuration and image haven't changed]" \ "--no-build[Don't build an image, even if it's missing]" \ '(-t --timeout)'{-t,--timeout}"[Specify a shutdown timeout in seconds. (default: 10)]:seconds: " \ '*:services:__docker-compose_services_all' && ret=0 ;; (version) _arguments \ - '--help[Print usage]' \ + $opts_help \ "--short[Shows only Compose's version number.]" && ret=0 ;; (*) - _message 'Unknown sub command' + _message 'Unknown sub command' && ret=1 + ;; esac return ret } -_docker-compose () { +_docker-compose() { # Support for subservices, which allows for `compdef _docker docker-shell=_docker_containers`. # Based on /usr/share/zsh/functions/Completion/Unix/_git without support for `ret`. if [[ $service != docker-compose ]]; then @@ -276,7 +317,8 @@ _docker-compose () { return fi - local curcontext="$curcontext" state line ret=1 + local curcontext="$curcontext" state line + integer ret=1 typeset -A opt_args _arguments -C \ @@ -288,23 +330,9 @@ _docker-compose () { '(-): :->command' \ '(-)*:: :->option-or-argument' && ret=0 - local counter=1 - #local compose_file compose_project - while [ $counter -lt ${#words[@]} ]; do - case "${words[$counter]}" in - -f|--file) - (( counter++ )) - compose_file="${words[$counter]}" - ;; - -p|--project-name) - (( counter++ )) - compose_project="${words[$counter]}" - ;; - *) - ;; - esac - (( counter++ )) - done + local compose_file=${opt_args[-f]}${opt_args[--file]} + local compose_project=${opt_args[-p]}${opt_args[--project-name]} + local compose_options="${compose_file:+--file $compose_file} ${compose_project:+--project-name $compose_project}" case $state in (command)