Browse code

Optimize the bash completion even further

The biggest/bestest change here is cutting down on the number of calls to Docker in the filtering helpers (`__docker_containers_running`, etc), especially calls to the really heavy `docker images`.

Signed-off-by: Andrew Page <admwiggin@gmail.com>

Tianon Gravi authored on 2014/10/03 06:13:37
Showing 1 changed files
... ...
@@ -25,79 +25,59 @@ __docker_q() {
25 25
 	docker 2>/dev/null "$@"
26 26
 }
27 27
 
28
-__docker_containers_all()
29
-{
30
-	local containers="$( __docker_q ps -a -q )"
31
-	local names="$( __docker_q inspect --format '{{.Name}}' $containers | sed 's,^/,,' )"
32
-	COMPREPLY=( $( compgen -W "$names $containers" -- "$cur" ) )
28
+__docker_containers_all() {
29
+	local IFS=$'\n'
30
+	local containers=( $(__docker_q ps -aq --no-trunc) )
31
+	if [ "$1" ]; then
32
+		containers=( $(__docker_q inspect --format "{{if $1}}{{.Id}}{{end}}" "${containers[@]}") )
33
+	fi
34
+	local names=( $(__docker_q inspect --format '{{.Name}}' "${containers[@]}") )
35
+	names=( "${names[@]#/}" ) # trim off the leading "/" from the container names
36
+	unset IFS
37
+	COMPREPLY=( $(compgen -W "${names[*]} ${containers[*]}" -- "$cur") )
33 38
 }
34 39
 
35
-__docker_containers_running()
36
-{
37
-	local containers="$( __docker_q ps -q )"
38
-	local names="$( __docker_q inspect --format '{{.Name}}' $containers | sed 's,^/,,' )"
39
-	COMPREPLY=( $( compgen -W "$names $containers" -- "$cur" ) )
40
+__docker_containers_running() {
41
+	__docker_containers_all '.State.Running'
40 42
 }
41 43
 
42
-__docker_containers_stopped()
43
-{
44
-	local containers="$( { __docker_q ps -a -q; __docker_q ps -q; } | sort | uniq -u )"
45
-	local names="$( __docker_q inspect --format '{{.Name}}' $containers | sed 's,^/,,' )"
46
-	COMPREPLY=( $( compgen -W "$names $containers" -- "$cur" ) )
44
+__docker_containers_stopped() {
45
+	__docker_containers_all 'not .State.Running'
47 46
 }
48 47
 
49
-__docker_containers_paused()
50
-{
51
-	local containers="$( __docker_q ps -q)"
52
-	local names="$( __docker_q inspect --format='{{.State.Paused}} {{.Name}}' $containers | sed 's/^false.*//' | sed 's,^true /,,' )"
53
-	local hostnames="$( __docker_q inspect --format='{{.State.Paused}} {{.Config.Hostname}}' $containers | sed 's/^false.*//' | sed 's,^true ,,' )"
54
-	COMPREPLY=( $( compgen -W "$names $hostnames" -- "$cur" ) )
48
+__docker_containers_pauseable() {
49
+	__docker_containers_all 'and .State.Running (not .State.Paused)'
55 50
 }
56 51
 
57
-__docker_containers_not_paused()
58
-{
59
-	local containers="$( __docker_q ps -q)"
60
-	local names="$( __docker_q inspect --format='{{.State.Paused}} {{.Name}}' $containers | sed 's/^true.*//' | sed 's,^false /,,' )"
61
-	local hostnames="$( __docker_q inspect --format='{{.State.Paused}} {{.Config.Hostname}}' $containers | sed 's/^true.*//' | sed 's/^false //' )"
62
-	COMPREPLY=( $( compgen -W "$names $hostnames" -- "$cur" ) )
52
+__docker_containers_unpauseable() {
53
+	__docker_containers_all '.State.Paused'
63 54
 }
64 55
 
65
-__docker_image_repos()
66
-{
67
-	local repos="$( __docker_q images | awk 'NR>1{print $1}' | grep -v '^<none>$' )"
68
-	COMPREPLY=( $( compgen -W "$repos" -- "$cur" ) )
56
+__docker_image_repos() {
57
+	local repos="$(__docker_q images | awk 'NR>1 && $1 != "<none>" { print $1 }')"
58
+	COMPREPLY=( $(compgen -W "$repos" -- "$cur") )
69 59
 }
70 60
 
71
-__docker_image_repos_and_tags()
72
-{
73
-	local repos="$( __docker_q images | awk 'NR>1{print $1}' | grep -v '^<none>$' )"
74
-	local images="$( __docker_q images | awk 'NR>1{print $1":"$2}' | grep -v '^<none>:' )"
75
-	COMPREPLY=( $( compgen -W "$repos $images" -- "$cur" ) )
61
+__docker_image_repos_and_tags() {
62
+	local reposAndTags="$(__docker_q images | awk 'NR>1 && $1 != "<none>" { print $1; print $1":"$2 }')"
63
+	COMPREPLY=( $(compgen -W "$reposAndTags" -- "$cur") )
76 64
 	__ltrim_colon_completions "$cur"
77 65
 }
78 66
 
79
-__docker_image_repos_and_tags_and_ids()
80
-{
81
-	local repos="$( __docker_q images | awk 'NR>1{print $1}' | grep -v '^<none>$' )"
82
-	local images="$( __docker_q images | awk 'NR>1{print $1":"$2}' | grep -v '^<none>:' )"
83
-	local ids="$( __docker_q images -a -q )"
84
-	COMPREPLY=( $( compgen -W "$repos $images $ids" -- "$cur" ) )
67
+__docker_image_repos_and_tags_and_ids() {
68
+	local images="$(__docker_q images -a --no-trunc | awk 'NR>1 { print $3; if ($1 != "<none>") { print $1; print $1":"$2 } }')"
69
+	COMPREPLY=( $(compgen -W "$images" -- "$cur") )
85 70
 	__ltrim_colon_completions "$cur"
86 71
 }
87 72
 
88
-__docker_containers_and_images()
89
-{
90
-	local containers="$( __docker_q ps -a -q )"
91
-	local names="$( __docker_q inspect --format '{{.Name}}' $containers | sed 's,^/,,' )"
92
-	local repos="$( __docker_q images | awk 'NR>1{print $1}' | grep -v '^<none>$' )"
93
-	local images="$( __docker_q images | awk 'NR>1{print $1":"$2}' | grep -v '^<none>:' )"
94
-	local ids="$( __docker_q images -a -q )"
95
-	COMPREPLY=( $( compgen -W "$containers $names $repos $images $ids" -- "$cur" ) )
96
-	__ltrim_colon_completions "$cur"
73
+__docker_containers_and_images() {
74
+	__docker_containers_all
75
+	local containers=( "${COMPREPLY[@]}" )
76
+	__docker_image_repos_and_tags_and_ids
77
+	COMPREPLY+=( "${containers[@]}" )
97 78
 }
98 79
 
99
-__docker_pos_first_nonflag()
100
-{
80
+__docker_pos_first_nonflag() {
101 81
 	local argument_flags=$1
102 82
 
103 83
 	local counter=$cpos
... ...
@@ -119,8 +99,7 @@ __docker_pos_first_nonflag()
119 119
 	echo $counter
120 120
 }
121 121
 
122
-_docker_docker()
123
-{
122
+_docker_docker() {
124 123
 	case "$prev" in
125 124
 		-H)
126 125
 			return
... ...
@@ -134,13 +113,12 @@ _docker_docker()
134 134
 			COMPREPLY=( $( compgen -W "-H" -- "$cur" ) )
135 135
 			;;
136 136
 		*)
137
-			COMPREPLY=( $( compgen -W "$commands help" -- "$cur" ) )
137
+			COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) )
138 138
 			;;
139 139
 	esac
140 140
 }
141 141
 
142
-_docker_attach()
143
-{
142
+_docker_attach() {
144 143
 	case "$cur" in
145 144
 		-*)
146 145
 			COMPREPLY=( $( compgen -W "--no-stdin --sig-proxy" -- "$cur" ) )
... ...
@@ -154,8 +132,7 @@ _docker_attach()
154 154
 	esac
155 155
 }
156 156
 
157
-_docker_build()
158
-{
157
+_docker_build() {
159 158
 	case "$prev" in
160 159
 		-t|--tag)
161 160
 			__docker_image_repos_and_tags
... ...
@@ -178,8 +155,7 @@ _docker_build()
178 178
 	esac
179 179
 }
180 180
 
181
-_docker_commit()
182
-{
181
+_docker_commit() {
183 182
 	case "$prev" in
184 183
 		-m|--message|-a|--author|--run)
185 184
 			return
... ...
@@ -209,8 +185,7 @@ _docker_commit()
209 209
 	esac
210 210
 }
211 211
 
212
-_docker_cp()
213
-{
212
+_docker_cp() {
214 213
 	local counter=$(__docker_pos_first_nonflag)
215 214
 	if [ $cword -eq $counter ]; then
216 215
 		case "$cur" in
... ...
@@ -233,8 +208,7 @@ _docker_cp()
233 233
 	fi
234 234
 }
235 235
 
236
-_docker_create()
237
-{
236
+_docker_create() {
238 237
 	case "$prev" in
239 238
 		-a|--attach)
240 239
 			COMPREPLY=( $( compgen -W 'stdin stdout stderr' -- "$cur" ) )
... ...
@@ -302,16 +276,14 @@ _docker_create()
302 302
 	esac
303 303
 }
304 304
 
305
-_docker_diff()
306
-{
305
+_docker_diff() {
307 306
 	local counter=$(__docker_pos_first_nonflag)
308 307
 	if [ $cword -eq $counter ]; then
309 308
 		__docker_containers_all
310 309
 	fi
311 310
 }
312 311
 
313
-_docker_events()
314
-{
312
+_docker_events() {
315 313
 	case "$prev" in
316 314
 		--since)
317 315
 			return
... ...
@@ -329,8 +301,7 @@ _docker_events()
329 329
 	esac
330 330
 }
331 331
 
332
-_docker_exec()
333
-{
332
+_docker_exec() {
334 333
 	case "$cur" in
335 334
 		-*)
336 335
 			COMPREPLY=( $( compgen -W "-d --detach -i --interactive -t --tty" -- "$cur" ) )
... ...
@@ -341,24 +312,21 @@ _docker_exec()
341 341
 	esac
342 342
 }
343 343
 
344
-_docker_export()
345
-{
344
+_docker_export() {
346 345
 	local counter=$(__docker_pos_first_nonflag)
347 346
 	if [ $cword -eq $counter ]; then
348 347
 		__docker_containers_all
349 348
 	fi
350 349
 }
351 350
 
352
-_docker_help()
353
-{
351
+_docker_help() {
354 352
 	local counter=$(__docker_pos_first_nonflag)
355 353
 	if [ $cword -eq $counter ]; then
356
-		COMPREPLY=( $( compgen -W "$commands" -- "$cur" ) )
354
+		COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )
357 355
 	fi
358 356
 }
359 357
 
360
-_docker_history()
361
-{
358
+_docker_history() {
362 359
 	case "$cur" in
363 360
 		-*)
364 361
 			COMPREPLY=( $( compgen -W "-q --quiet --no-trunc" -- "$cur" ) )
... ...
@@ -372,8 +340,7 @@ _docker_history()
372 372
 	esac
373 373
 }
374 374
 
375
-_docker_images()
376
-{
375
+_docker_images() {
377 376
 	case "$cur" in
378 377
 		-*)
379 378
 			COMPREPLY=( $( compgen -W "-q --quiet -a --all --no-trunc -v --viz -t --tree" -- "$cur" ) )
... ...
@@ -387,8 +354,7 @@ _docker_images()
387 387
 	esac
388 388
 }
389 389
 
390
-_docker_import()
391
-{
390
+_docker_import() {
392 391
 	local counter=$(__docker_pos_first_nonflag)
393 392
 	if [ $cword -eq $counter ]; then
394 393
 		return
... ...
@@ -401,13 +367,11 @@ _docker_import()
401 401
 	fi
402 402
 }
403 403
 
404
-_docker_info()
405
-{
404
+_docker_info() {
406 405
 	return
407 406
 }
408 407
 
409
-_docker_inspect()
410
-{
408
+_docker_inspect() {
411 409
 	case "$prev" in
412 410
 		-f|--format)
413 411
 			return
... ...
@@ -426,18 +390,15 @@ _docker_inspect()
426 426
 	esac
427 427
 }
428 428
 
429
-_docker_kill()
430
-{
429
+_docker_kill() {
431 430
 	__docker_containers_running
432 431
 }
433 432
 
434
-_docker_load()
435
-{
433
+_docker_load() {
436 434
 	return
437 435
 }
438 436
 
439
-_docker_login()
440
-{
437
+_docker_login() {
441 438
 	case "$prev" in
442 439
 		-u|--username|-p|--password|-e|--email)
443 440
 			return
... ...
@@ -455,8 +416,7 @@ _docker_login()
455 455
 	esac
456 456
 }
457 457
 
458
-_docker_logs()
459
-{
458
+_docker_logs() {
460 459
 	case "$cur" in
461 460
 		-*)
462 461
 			COMPREPLY=( $( compgen -W "-f --follow" -- "$cur" ) )
... ...
@@ -469,24 +429,22 @@ _docker_logs()
469 469
 			;;
470 470
 	esac
471 471
 }
472
-_docker_pause()
473
-{
472
+
473
+_docker_pause() {
474 474
 	local counter=$(__docker_pos_first_nonflag)
475 475
 	if [ $cword -eq $counter ]; then
476
-		__docker_containers_not_paused
476
+		__docker_containers_pauseable
477 477
 	fi
478 478
 }
479 479
 
480
-_docker_port()
481
-{
480
+_docker_port() {
482 481
 	local counter=$(__docker_pos_first_nonflag)
483 482
 	if [ $cword -eq $counter ]; then
484 483
 		__docker_containers_all
485 484
 	fi
486 485
 }
487 486
 
488
-_docker_ps()
489
-{
487
+_docker_ps() {
490 488
 	case "$prev" in
491 489
 		--since|--before)
492 490
 			__docker_containers_all
... ...
@@ -507,8 +465,7 @@ _docker_ps()
507 507
 	esac
508 508
 }
509 509
 
510
-_docker_pull()
511
-{
510
+_docker_pull() {
512 511
 	case "$prev" in
513 512
 		-t|--tag)
514 513
 			return
... ...
@@ -530,16 +487,14 @@ _docker_pull()
530 530
 	esac
531 531
 }
532 532
 
533
-_docker_push()
534
-{
533
+_docker_push() {
535 534
 	local counter=$(__docker_pos_first_nonflag)
536 535
 	if [ $cword -eq $counter ]; then
537 536
 		__docker_image_repos_and_tags
538 537
 	fi
539 538
 }
540 539
 
541
-_docker_restart()
542
-{
540
+_docker_restart() {
543 541
 	case "$prev" in
544 542
 		-t|--time)
545 543
 			return
... ...
@@ -558,8 +513,7 @@ _docker_restart()
558 558
 	esac
559 559
 }
560 560
 
561
-_docker_rm()
562
-{
561
+_docker_rm() {
563 562
 	case "$cur" in
564 563
 		-*)
565 564
 			COMPREPLY=( $( compgen -W "-f --force -l --link -v --volumes" -- "$cur" ) )
... ...
@@ -581,13 +535,11 @@ _docker_rm()
581 581
 	esac
582 582
 }
583 583
 
584
-_docker_rmi()
585
-{
584
+_docker_rmi() {
586 585
 	__docker_image_repos_and_tags_and_ids
587 586
 }
588 587
 
589
-_docker_run()
590
-{
588
+_docker_run() {
591 589
 	case "$prev" in
592 590
 		-a|--attach)
593 591
 			COMPREPLY=( $( compgen -W 'stdin stdout stderr' -- "$cur" ) )
... ...
@@ -655,16 +607,14 @@ _docker_run()
655 655
 	esac
656 656
 }
657 657
 
658
-_docker_save()
659
-{
658
+_docker_save() {
660 659
 	local counter=$(__docker_pos_first_nonflag)
661 660
 	if [ $cword -eq $counter ]; then
662 661
 		__docker_image_repos_and_tags_and_ids
663 662
 	fi
664 663
 }
665 664
 
666
-_docker_search()
667
-{
665
+_docker_search() {
668 666
 	case "$prev" in
669 667
 		-s|--stars)
670 668
 			return
... ...
@@ -682,8 +632,7 @@ _docker_search()
682 682
 	esac
683 683
 }
684 684
 
685
-_docker_start()
686
-{
685
+_docker_start() {
687 686
 	case "$cur" in
688 687
 		-*)
689 688
 			COMPREPLY=( $( compgen -W "-a --attach -i --interactive" -- "$cur" ) )
... ...
@@ -694,8 +643,7 @@ _docker_start()
694 694
 	esac
695 695
 }
696 696
 
697
-_docker_stop()
698
-{
697
+_docker_stop() {
699 698
 	case "$prev" in
700 699
 		-t|--time)
701 700
 			return
... ...
@@ -714,8 +662,7 @@ _docker_stop()
714 714
 	esac
715 715
 }
716 716
 
717
-_docker_tag()
718
-{
717
+_docker_tag() {
719 718
 	case "$cur" in
720 719
 		-*)
721 720
 			COMPREPLY=( $( compgen -W "-f --force" -- "$cur" ) )
... ...
@@ -737,73 +684,68 @@ _docker_tag()
737 737
 	esac
738 738
 }
739 739
 
740
-_docker_unpause()
741
-{
740
+_docker_unpause() {
742 741
 	local counter=$(__docker_pos_first_nonflag)
743 742
 	if [ $cword -eq $counter ]; then
744
-		__docker_containers_paused
743
+		__docker_containers_unpauseable
745 744
 	fi
746 745
 }
747 746
 
748
-_docker_top()
749
-{
747
+_docker_top() {
750 748
 	local counter=$(__docker_pos_first_nonflag)
751 749
 	if [ $cword -eq $counter ]; then
752 750
 		__docker_containers_running
753 751
 	fi
754 752
 }
755 753
 
756
-_docker_version()
757
-{
754
+_docker_version() {
758 755
 	return
759 756
 }
760 757
 
761
-_docker_wait()
762
-{
758
+_docker_wait() {
763 759
 	__docker_containers_all
764 760
 }
765 761
 
766
-_docker()
767
-{
768
-	local commands="
769
-			attach
770
-			build
771
-			commit
772
-			cp
773
-			create
774
-			diff
775
-			events
776
-			exec
777
-			export
778
-			history
779
-			images
780
-			import
781
-			info
782
-			insert
783
-			inspect
784
-			kill
785
-			load
786
-			login
787
-			logs
788
-			pause
789
-			port
790
-			ps
791
-			pull
792
-			push
793
-			restart
794
-			rm
795
-			rmi
796
-			run
797
-			save
798
-			search
799
-			start
800
-			stop
801
-			tag
802
-			top
803
-			unpause
804
-			version
805
-			wait
806
-		"
762
+_docker() {
763
+	local commands=(
764
+		attach
765
+		build
766
+		commit
767
+		cp
768
+		create
769
+		diff
770
+		events
771
+		exec
772
+		export
773
+		history
774
+		images
775
+		import
776
+		info
777
+		insert
778
+		inspect
779
+		kill
780
+		load
781
+		login
782
+		logs
783
+		pause
784
+		port
785
+		ps
786
+		pull
787
+		push
788
+		restart
789
+		rm
790
+		rmi
791
+		run
792
+		save
793
+		search
794
+		start
795
+		stop
796
+		tag
797
+		top
798
+		unpause
799
+		version
800
+		wait
801
+	)
807 802
 
808 803
 	COMPREPLY=()
809 804
 	local cur prev words cword