Skip to content

Commit 4586609

Browse files
authored
Merge pull request #717 from albers/completion-images-2
Improve and fix bash completion for images
2 parents a46fa07 + 53376b6 commit 4586609

File tree

2 files changed

+99
-80
lines changed

2 files changed

+99
-80
lines changed

contrib/completion/bash/docker

Lines changed: 98 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -178,52 +178,78 @@ __docker_complete_container_ids() {
178178
COMPREPLY=( $(compgen -W "${containers[*]}" -- "$cur") )
179179
}
180180

181+
# __docker_images returns a list of images. For each image, up to three representations
182+
# can be generated: the repository (e.g. busybox), repository:tag (e.g. busybox:latest)
183+
# and the ID (e.g. sha256:ee22cbbd4ea3dff63c86ba60c7691287c321e93adfc1009604eb1dde7ec88645).
184+
#
185+
# The optional arguments `--repo`, `--tag` and `--id` select the representations that
186+
# may be returned. Whether or not a particular representation is actually returned
187+
# depends on the user's customization through several environment variables:
188+
# - image IDs are only shown if DOCKER_COMPLETION_SHOW_IMAGE_IDS=all|non-intermediate.
189+
# - tags can be excluded by setting DOCKER_COMPLETION_SHOW_TAGS=no.
190+
# - repositories are always shown.
191+
#
192+
# In cases where an exact image specification is needed, `--force-tag` can be used.
193+
# It ignores DOCKER_COMPLETION_SHOW_TAGS and only lists valid repository:tag combinations,
194+
# avoiding repository names that would default to a potentially missing default tag.
195+
#
196+
# Additional arguments to `docker image ls` may be specified in order to filter the list,
197+
# e.g. `__docker_images --filter dangling=true`.
198+
#
181199
__docker_images() {
182-
local images_args=""
183-
184-
case "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" in
185-
all)
186-
images_args="--no-trunc -a"
187-
;;
188-
non-intermediate)
189-
images_args="--no-trunc"
190-
;;
191-
esac
200+
local repo_format='{{.Repository}}'
201+
local tag_format='{{.Repository}}:{{.Tag}}'
202+
local id_format='{{.ID}}'
203+
local all
204+
local format
192205

193-
local repo_print_command
194-
if [ "${DOCKER_COMPLETION_SHOW_TAGS:-yes}" = "yes" ]; then
195-
repo_print_command='print $1; print $1":"$2'
196-
else
197-
repo_print_command='print $1'
206+
if [ "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" = "all" ] ; then
207+
all='--all'
198208
fi
199209

200-
local awk_script
201-
case "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" in
202-
all|non-intermediate)
203-
awk_script='NR>1 { print $3; if ($1 != "<none>") { '"$repo_print_command"' } }'
204-
;;
205-
none|*)
206-
awk_script='NR>1 && $1 != "<none>" { '"$repo_print_command"' }'
207-
;;
208-
esac
210+
while true ; do
211+
case "$1" in
212+
--repo)
213+
format+="$repo_format\n"
214+
shift
215+
;;
216+
--tag)
217+
if [ "${DOCKER_COMPLETION_SHOW_TAGS:-yes}" = "yes" ]; then
218+
format+="$tag_format\n"
219+
fi
220+
shift
221+
;;
222+
--id)
223+
if [[ $DOCKER_COMPLETION_SHOW_IMAGE_IDS =~ ^(all|non-intermediate)$ ]] ; then
224+
format+="$id_format\n"
225+
fi
226+
shift
227+
;;
228+
--force-tag)
229+
# like `--tag` but ignores environment setting
230+
format+="$tag_format\n"
231+
shift
232+
;;
233+
*)
234+
break
235+
;;
236+
esac
237+
done
209238

210-
__docker_q images $images_args | awk "$awk_script" | grep -v '<none>$'
239+
__docker_q image ls --no-trunc --format "${format%\\n}" $all "$@" | grep -v '<none>$'
211240
}
212241

242+
# __docker_complete_images applies completion of images based on the current value of `$cur` or
243+
# the value of the optional first option `--cur`, if given.
244+
# See __docker_images for customization of the returned items.
213245
__docker_complete_images() {
214-
COMPREPLY=( $(compgen -W "$(__docker_images)" -- "$cur") )
215-
__ltrim_colon_completions "$cur"
216-
}
217-
218-
__docker_complete_image_repos() {
219-
local repos="$(__docker_q images | awk 'NR>1 && $1 != "<none>" { print $1 }')"
220-
COMPREPLY=( $(compgen -W "$repos" -- "$cur") )
221-
}
222-
223-
__docker_complete_image_repos_and_tags() {
224-
local reposAndTags="$(__docker_q images | awk 'NR>1 && $1 != "<none>" { print $1; print $1":"$2 }')"
225-
COMPREPLY=( $(compgen -W "$reposAndTags" -- "$cur") )
226-
__ltrim_colon_completions "$cur"
246+
local current="$cur"
247+
if [ "$1" = "--cur" ] ; then
248+
current="$2"
249+
shift 2
250+
fi
251+
COMPREPLY=( $(compgen -W "$(__docker_images "$@")" -- "$current") )
252+
__ltrim_colon_completions "$current"
227253
}
228254

229255
# __docker_networks returns a list of all networks. Additional options to
@@ -1354,11 +1380,8 @@ _docker_container_commit() {
13541380
if [ "$cword" -eq "$counter" ]; then
13551381
__docker_complete_containers_all
13561382
return
1357-
fi
1358-
(( counter++ ))
1359-
1360-
if [ "$cword" -eq "$counter" ]; then
1361-
__docker_complete_image_repos_and_tags
1383+
elif [ "$cword" -eq "$((counter + 1))" ]; then
1384+
__docker_complete_images --repo --tag
13621385
return
13631386
fi
13641387
;;
@@ -1529,8 +1552,7 @@ _docker_container_ls() {
15291552
local key=$(__docker_map_key_of_current_option '--filter|-f')
15301553
case "$key" in
15311554
ancestor)
1532-
cur="${cur##*=}"
1533-
__docker_complete_images
1555+
__docker_complete_images --cur "${cur##*=}" --repo --tag --id
15341556
return
15351557
;;
15361558
before)
@@ -1998,7 +2020,7 @@ _docker_container_run_and_create() {
19982020
*)
19992021
local counter=$( __docker_pos_first_nonflag "$( __docker_to_alternatives "$options_with_args" )" )
20002022
if [ "$cword" -eq "$counter" ]; then
2001-
__docker_complete_images
2023+
__docker_complete_images --repo --tag --id
20022024
fi
20032025
;;
20042026
esac
@@ -2513,7 +2535,7 @@ _docker_image_build() {
25132535
return
25142536
;;
25152537
--cache-from)
2516-
__docker_complete_image_repos_and_tags
2538+
__docker_complete_images --repo --tag --id
25172539
return
25182540
;;
25192541
--file|-f|--iidfile)
@@ -2541,7 +2563,7 @@ _docker_image_build() {
25412563
return
25422564
;;
25432565
--tag|-t)
2544-
__docker_complete_image_repos_and_tags
2566+
__docker_complete_images --repo --tag
25452567
return
25462568
;;
25472569
--target)
@@ -2587,9 +2609,9 @@ _docker_image_history() {
25872609
COMPREPLY=( $( compgen -W "--format --help --human=false -H=false --no-trunc --quiet -q" -- "$cur" ) )
25882610
;;
25892611
*)
2590-
local counter=$(__docker_pos_first_nonflag)
2612+
local counter=$(__docker_pos_first_nonflag '--format')
25912613
if [ "$cword" -eq "$counter" ]; then
2592-
__docker_complete_images
2614+
__docker_complete_images --force-tag --id
25932615
fi
25942616
;;
25952617
esac
@@ -2613,12 +2635,10 @@ _docker_image_import() {
26132635
*)
26142636
local counter=$(__docker_pos_first_nonflag '--change|-c|--message|-m')
26152637
if [ "$cword" -eq "$counter" ]; then
2638+
_filedir
26162639
return
2617-
fi
2618-
(( counter++ ))
2619-
2620-
if [ "$cword" -eq "$counter" ]; then
2621-
__docker_complete_image_repos_and_tags
2640+
elif [ "$cword" -eq "$((counter + 1))" ]; then
2641+
__docker_complete_images --repo --tag
26222642
return
26232643
fi
26242644
;;
@@ -2651,9 +2671,8 @@ _docker_image_list() {
26512671
_docker_image_ls() {
26522672
local key=$(__docker_map_key_of_current_option '--filter|-f')
26532673
case "$key" in
2654-
before|since|reference)
2655-
cur="${cur##*=}"
2656-
__docker_complete_images
2674+
before|since)
2675+
__docker_complete_images --cur "${cur##*=}" --force-tag --id
26572676
return
26582677
;;
26592678
dangling)
@@ -2663,6 +2682,10 @@ _docker_image_ls() {
26632682
label)
26642683
return
26652684
;;
2685+
reference)
2686+
__docker_complete_images --cur "${cur##*=}" --repo --tag
2687+
return
2688+
;;
26662689
esac
26672690

26682691
case "$prev" in
@@ -2684,7 +2707,7 @@ _docker_image_ls() {
26842707
return
26852708
;;
26862709
*)
2687-
__docker_complete_image_repos
2710+
__docker_complete_images --repo --tag
26882711
;;
26892712
esac
26902713
}
@@ -2725,12 +2748,12 @@ _docker_image_pull() {
27252748
for arg in "${COMP_WORDS[@]}"; do
27262749
case "$arg" in
27272750
--all-tags|-a)
2728-
__docker_complete_image_repos
2751+
__docker_complete_images --repo
27292752
return
27302753
;;
27312754
esac
27322755
done
2733-
__docker_complete_image_repos_and_tags
2756+
__docker_complete_images --repo --tag
27342757
fi
27352758
;;
27362759
esac
@@ -2744,7 +2767,7 @@ _docker_image_push() {
27442767
*)
27452768
local counter=$(__docker_pos_first_nonflag)
27462769
if [ "$cword" -eq "$counter" ]; then
2747-
__docker_complete_image_repos_and_tags
2770+
__docker_complete_images --repo --tag
27482771
fi
27492772
;;
27502773
esac
@@ -2760,7 +2783,7 @@ _docker_image_rm() {
27602783
COMPREPLY=( $( compgen -W "--force -f --help --no-prune" -- "$cur" ) )
27612784
;;
27622785
*)
2763-
__docker_complete_images
2786+
__docker_complete_images --force-tag --id
27642787
;;
27652788
esac
27662789
}
@@ -2782,7 +2805,7 @@ _docker_image_save() {
27822805
COMPREPLY=( $( compgen -W "--help --output -o" -- "$cur" ) )
27832806
;;
27842807
*)
2785-
__docker_complete_images
2808+
__docker_complete_images --repo --tag --id
27862809
;;
27872810
esac
27882811
}
@@ -2796,13 +2819,10 @@ _docker_image_tag() {
27962819
local counter=$(__docker_pos_first_nonflag)
27972820

27982821
if [ "$cword" -eq "$counter" ]; then
2799-
__docker_complete_image_repos_and_tags
2822+
__docker_complete_images --force-tag --id
28002823
return
2801-
fi
2802-
(( counter++ ))
2803-
2804-
if [ "$cword" -eq "$counter" ]; then
2805-
__docker_complete_image_repos_and_tags
2824+
elif [ "$cword" -eq "$((counter + 1))" ]; then
2825+
__docker_complete_images --repo --tag
28062826
return
28072827
fi
28082828
;;
@@ -2858,7 +2878,7 @@ _docker_inspect() {
28582878
'')
28592879
COMPREPLY=( $( compgen -W "
28602880
$(__docker_containers --all)
2861-
$(__docker_images)
2881+
$(__docker_images --force-tag --id)
28622882
$(__docker_networks)
28632883
$(__docker_nodes)
28642884
$(__docker_plugins_installed)
@@ -2872,7 +2892,7 @@ _docker_inspect() {
28722892
__docker_complete_containers_all
28732893
;;
28742894
image)
2875-
__docker_complete_images
2895+
__docker_complete_images --force-tag --id
28762896
;;
28772897
network)
28782898
__docker_complete_networks
@@ -3495,7 +3515,7 @@ _docker_service_update_and_create() {
34953515
esac
34963516
;;
34973517
--image)
3498-
__docker_complete_image_repos_and_tags
3518+
__docker_complete_images --repo --tag --id
34993519
return
35003520
;;
35013521
--network-add|--network-rm)
@@ -3591,7 +3611,7 @@ _docker_service_update_and_create() {
35913611
fi
35923612
else
35933613
if [ "$cword" -eq "$counter" ]; then
3594-
__docker_complete_images
3614+
__docker_complete_images --repo --tag --id
35953615
fi
35963616
fi
35973617
;;
@@ -4639,8 +4659,7 @@ _docker_system_events() {
46394659
return
46404660
;;
46414661
image)
4642-
cur="${cur##*=}"
4643-
__docker_complete_images
4662+
__docker_complete_images --cur "${cur##*=}" --repo --tag
46444663
return
46454664
;;
46464665
network)
@@ -4737,7 +4756,7 @@ _docker_trust_revoke() {
47374756
*)
47384757
local counter=$(__docker_pos_first_nonflag)
47394758
if [ "$cword" -eq "$counter" ]; then
4740-
__docker_complete_images
4759+
__docker_complete_images --repo --tag
47414760
fi
47424761
;;
47434762
esac
@@ -4751,7 +4770,7 @@ _docker_trust_sign() {
47514770
*)
47524771
local counter=$(__docker_pos_first_nonflag)
47534772
if [ "$cword" -eq "$counter" ]; then
4754-
__docker_complete_images
4773+
__docker_complete_images --force-tag --id
47554774
fi
47564775
;;
47574776
esac
@@ -4765,7 +4784,7 @@ _docker_trust_view() {
47654784
*)
47664785
local counter=$(__docker_pos_first_nonflag)
47674786
if [ "$cword" -eq "$counter" ]; then
4768-
__docker_complete_images
4787+
__docker_complete_images --repo --tag
47694788
fi
47704789
;;
47714790
esac

docs/reference/commandline/events.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ The currently supported filters are:
179179
* container (`container=<name or id>`)
180180
* daemon (`daemon=<name or id>`)
181181
* event (`event=<event action>`)
182-
* image (`image=<tag or id>`)
182+
* image (`image=<repository or tag>`)
183183
* label (`label=<key>` or `label=<key>=<value>`)
184184
* network (`network=<name or id>`)
185185
* node (`node=<id>`)

0 commit comments

Comments
 (0)