How can I get zsh
to play a sound when the command is not found?
Ex: I have the alias vpn
to open my VPN from the terminal (zsh). If sometimes by mistake I type cpn
instead of vpn
, I get the following output:
me@iMac ~ % cpn
zsh: command not found: cpn
I know how to play a sound from terminal, in general. How do I integrate it so that there is a sound whenever the command is not found?
The specific sound I want to play is available at System Preferences > Sound > Sound Effects > Funky.
Best Answer
First, some background on command execution in zsh is helpful:
So, there are two requirements now:
command_not_found_handler
defined;zsh
will have to load this function every time it starts.The second point can be taken care of by defining the function in
~/.zshrc
file. For the first point I used the following definition:Breakdown of the function body:
osascript -e beep&
: This command produces the default beep sound of macOS. It's the same sound as the one that plays in System Preferences > Sound > Sound Effects > Funky. The actual location where it is present in macOS is/System/Library/Sounds/Funk.aiff
. I have added&
at the end of this to execute the sound in parallel. Otherwise the next part of the code will be delayed in execution.echo "zsh: command not found: $1"&
: This is the default action that zsh takes when a bad command is executed. Since the goal is to produce the sound and have the error output on the terminal code, this has to be here. Again, I have added&
at the end of this to execute the sound and this message echo in parallel.return 127;
: This, as mentioned in the quoted text at the top of the answer, is the expected status code when a bad command is executed. While the method worked for me without it, it is a good programming habit to return what is expected.Copy pasting the method in
~/.zshrc
file and then sourcing it again makeszsh
aware of this function. Now when I callcpn
instead of my actual aliasvpn
, my terminal behaves more consistently with the rest of the macOS and produces the same sound as it does in other GUI interactions, and produces an error message on the terminal.Credit for this answer goes to @glennjackman's comment.