Add custom bash autocomplete function to quickly move into code projects
I keep my projects in a Projects
directory on my Mac. It's also not unusual for me to switch back and forth between projects throughout the day. To do that, I have a couple different options:
cd ~/Projects/dashboard
- cd
../../dashboard
Either I type a few extra characters or I have to think about where I am in relationship to where I want to go.
I thought to myself: wouldn't it be nice if I could:
- Type
go
and be in my~/Projects
directory? - Better yet: Type
go dashboard
and be in~/Projects/dashboard
? - Or better yet: Type
go da
, hit tab, and it autocompletes?
After a little bit of tinkering, here's the solution I came up with.
As an aside, Zsh is now the default on the Mac instead of Bash. Zsh is an extension of Bash, and while they're very similar, they do have differences. The functionality below was tested using Zsh.
Create custom cd
function
Let's add a function called go
to ~/.zprofile
. Open ~/.zprofile
for editing:
vi ~/.zprofile
And then add the following:
go() {
cd ~/Projects/$1
}
Save your changes by pressing ESC, type :wq
, and press ENTER. If you restart Terminal, you'll see this actually gets us pretty close.
The $1
refers to whatever we add after go
. It's our first argument so to speak. If you typed in go hello world
, then $1
= hello
and $2
= world
.
We can now type go
and press ENTER to change into ~/Projects
. We can also type go dashboard
to directly move into ~/Projects/dashboard
. What we can't do is enter a partial directory like go da
and press TAB to autocomplete from our projects.
Create autocomplete function
Let's add another function called _go_auto_complete
to ~/.zprofile
:
_go_auto_complete() {
local file
for file in ~/Projects/"$2"*; do
[[ -d $file ]] || continue
COMPREPLY+=( $(basename "$file") )
done
}
local file
creates a local variable calledfile
for file in ~/Projects/
loops over everything within Projects$2
is our partial directory name (e.g.da
) that we want to autocomplete*
is a wildcard character to include anything that starts withda
- I'll explain why it's
$2
and not$1
in the next section -d $file
ensures we only autocomplete directories, not files- If
$file
is a directory, go to next line, elsecontinue
with next iteration COMPREPLY
is an internal bash array that stores possible completions+=
is how we append to that array$file
is the full path, but we only want the directory$(basename "$file")
then ensures we only get the directory
Enable autocomplete function
We have a go
function for us and a _go_auto_complete
function for bash, but bash doesn't yet know of its existence. Let's solve that now.
Edit ~/.zshrc
by running vi ~/.zshrc
and include the following line:
complete -F _go_auto_complete go
complete
is a built-in bash command for auto completion-F
indicates what we're providing is a function_go_auto_complete
indicates what our autocompletion function is calledgo
indicates to run this autocompletion function whenever we usego
- That's why we used
$2
in the last section, because$1
would refer togo
Save your file, restart your Terminal, and add a few directories to ~/Projects
(or wherever you keep them) and watch them autocomplete.
By the way, we put this command in the ~/.zshrc
file because every time we open Terminal (aka start a shell session), all commands in this file get executed, ensuring our autocomplete is always ready to go– pun intended.
If you have any questions or comments, feel free to leave them below.
Featured image by Pablo Martinez.