Skip to content

Commit 63c3f6c

Browse files
committed
chapter: Programmable Completion
1 parent 833660b commit 63c3f6c

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed

index.ptree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ pages/bibliography.poly.pm
123123
pages/io_redirection_de.poly.pm
124124
pages/command_line_opt.poly.pm
125125
pages/important_files.poly.pm
126+
pages/completion_intro.poly.pm
126127
}
127128

128129
}

pages/completion_intro.poly.pm

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#lang pollen
2+
3+
◊page-init{}
4+
◊define-meta[page-title]{Programmable Completion}
5+
◊define-meta[page-description]{An Introduction to Programmable Completion}
6+
7+
The programmable completion feature in Bash permits typing a partial
8+
command, then pressing the [Tab] key to auto-complete the command
9+
sequence. If multiple completions are possible, then [Tab] lists
10+
them all. Let's see how it works.
11+
12+
◊example{
13+
bash$ xtra[Tab]
14+
xtraceroute xtrapin xtrapproto
15+
xtraceroute.real xtrapinfo xtrapreset
16+
xtrapchar xtrapout xtrapstats
17+
18+
19+
bash$ xtrac[Tab]
20+
xtraceroute xtraceroute.real
21+
22+
23+
bash$ xtraceroute.r[Tab]
24+
xtraceroute.real
25+
}
26+
27+
Tab completion also works for variables and path names.
28+
29+
◊example{
30+
bash$ echo $BASH[Tab]
31+
$BASH $BASH_COMPLETION $BASH_SUBSHELL
32+
$BASH_ARGC $BASH_COMPLETION_DIR $BASH_VERSINFO
33+
$BASH_ARGV $BASH_LINENO $BASH_VERSION
34+
$BASH_COMMAND $BASH_SOURCE
35+
36+
37+
bash$ echo /usr/local/[Tab]
38+
bin/ etc/ include/ libexec/ sbin/ src/
39+
doc/ games/ lib/ man/ share/
40+
}
41+
42+
The Bash ◊command{complete} and ◊command{compgen} builtins make it
43+
possible for tab completion to recognize partial parameters and
44+
options to commands. In a very simple case, we can use
45+
◊command{complete} from the command-line to specify a short list of
46+
acceptable parameters.
47+
48+
◊example{
49+
bash$ touch sample_command
50+
bash$ touch file1.txt file2.txt file2.doc file30.txt file4.zzz
51+
bash$ chmod +x sample_command
52+
bash$ complete -f -X '!*.txt' sample_command
53+
54+
55+
bash$ ./sample[Tab][Tab]
56+
sample_command
57+
file1.txt file2.txt file30.txt
58+
}
59+
60+
The ◊code{-f} option to complete specifies filenames, and ◊code{-X}
61+
the filter pattern.
62+
63+
For anything more complex, we could write a script that specifies a
64+
list of acceptable command-line parameters. The compgen builtin
65+
expands a list of arguments to generate completion matches.
66+
67+
Let us take a modified version of the ◊fname{UseGetOpt.sh} script as
68+
an example command. This script accepts a number of command-line
69+
parameters, preceded by either a single or double dash. And here is
70+
the corresponding completion script, by convention given a filename
71+
corresponding to its associated command.
72+
73+
◊example{
74+
# file: UseGetOpt-2
75+
# UseGetOpt-2.sh parameter-completion
76+
77+
_UseGetOpt-2 () # By convention, the function name
78+
{ #+ starts with an underscore.
79+
local cur
80+
# Pointer to current completion word.
81+
# By convention, it's named "cur" but this isn't strictly necessary.
82+
83+
COMPREPLY=() # Array variable storing the possible completions.
84+
cur=${COMP_WORDS[COMP_CWORD]}
85+
86+
case "$cur" in
87+
-*)
88+
COMPREPLY=( $( compgen -W '-a -d -f -l -t -h --aoption --debug \
89+
--file --log --test --help --' -- $cur ) );;
90+
# Generate the completion matches and load them into $COMPREPLY array.
91+
# xx) May add more cases here.
92+
# yy)
93+
# zz)
94+
esac
95+
96+
return 0
97+
}
98+
99+
complete -F _UseGetOpt-2 -o filenames ./UseGetOpt-2.sh
100+
# ^^ ^^^^^^^^^^^^ Invokes the function _UseGetOpt-2.
101+
}
102+
103+
Now, let's try it.
104+
105+
◊example{
106+
bash$ source UseGetOpt-2
107+
108+
bash$ ./UseGetOpt-2.sh -[Tab]
109+
-- --aoption --debug --file --help --log --test
110+
-a -d -f -h -l -t
111+
112+
113+
bash$ ./UseGetOpt-2.sh --[Tab]
114+
-- --aoption --debug --file --help --log --test
115+
}
116+
117+
We begin by sourcing the "completion script." This sets the
118+
command-line parameters. ◊footnote{Normally the default parameter
119+
completion files reside in either the ◊fname{/etc/profile.d} directory
120+
or in ◊fname{/etc/bash_completion}. These autoload on system
121+
startup. So, after writing a useful completion script, you might wish
122+
to move it (as root, of course) to one of these directories.}
123+
124+
In the first instance, hitting [Tab] after a single dash, the output
125+
is all the possible parameters preceded by one or more dashes. Hitting
126+
[Tab] after two dashes gives the possible parameters preceded by two
127+
or more dashes.
128+
129+
Now, just what is the point of having to jump through flaming hoops to
130+
enable command-line tab completion? It saves keystrokes.
131+
132+
Resources:
133+
134+
◊list-block[#:type "bullet"]{
135+
136+
◊list-entry{Project ◊emphasize{bash-completion} in Debian.
137+
138+
See:
139+
◊url[#:link "https://salsa.debian.org/debian/bash-completion"]{}
140+
}
141+
142+
◊list-entry{Mitch Frazier's Linux Journal article, ◊emphasize{More on
143+
Using the Bash Complete Command}.
144+
145+
See: ◊url[#:link
146+
"https://www.linuxjournal.com/content/more-using-bash-complete-command"]{}
147+
}
148+
149+
◊list-entry{Steve Kemp's excellent article, ◊emphasize{An Introduction
150+
to Bash Completion}
151+
152+
Part 1, see: ◊url[#:link
153+
"http://web.archive.org/web/20180129055754/https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1"]{}
154+
155+
Part 2, see: ◊url[#:link
156+
"http://web.archive.org/web/20180304191616/https://debian-administration.org/article/317/An_introduction_to_bash_completion_part_2"]{}
157+
158+
}
159+
160+
}

0 commit comments

Comments
 (0)