I find the bash commands complete
and compgen
overly mysterious, so I’m often playing with them to try to get a better grasp on all of the poorly-documented options. complete
is a shell built-in, no man page, just help complete
output. It’s vague.
I’ve detailed some of my other exploits with this in the past, one of my favorites being custom app alias completions. This time I wanted to go a lot simpler.
The afplay
command comes default with OS X’s BSD installation. It’s the “Audio File Play” command used to play sound files in compatible formats. I usually use it in scripts to play the system sounds (Glass, Basso, etc.). So I wrote a quick function to make it easier to get to those:
play() {
command afplay "/System/Library/Sounds/$1.aiff"
}
With that in place, I can just call play basso
and it will play the sound. I don’t always remember the names of all the sounds, though, which means I have to ls /System/Library/Sounds
to see them. A perfect job for shell completion, right?
So here’s the simple script that I source in ~/.bash_profile to give me tab completion of system sounds, listing them all if I haven’t started typing a word yet.
What it does is create an array from the result of listing the sounds directory and getting the base name of every file minus the .aiff
extension. Then, rather than using compgen
to do the matching, it uses a custom loop to handle case insensitive matching. This would normally work by default with compgen
and shopt -s nocasematch
, but for reasons I’m not clear on, it doesn’t when you’re providing a custom list.
The _complete_system_sounds
function is used to case-insensitively complete the “play” function when I call it, so typing play f[TAB]
will offer me “Frog” and “Funk.” afplay
completion continues using the Bash default, only my custom function is affected.
Neat trick.
Ryan Irelan has produced a series of shell trick videos based on BrettTerpstra.com posts. Readers can get 10% off using the coupon code TERPSTRA
.