|
| 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