ZSH Gem #8: Hook function chpwd()
There is a number of magic functions called hook functions in ZSH which are automatically executed under certain circumstances. One of these functions is chpwd()
and it is executed each time you change the current working directory.
This doesn't seem to be too exciting, but it can be pretty useful to know this little function. One thing that is often accomplished with this hook function is to change the title of your graphical terminal emulator (e.g. xterm) every time you change the working directory. With just the default configuration, ZSH doesn't show anything in the title bar of your xterm or xterm compatible TE, but we can change that. What we need to do is to write some escape sequences to STDOUT every time the directory is changed. For this we use print
because with the -P
parameter we can expand prompt escape sequences such as %n
for $USERNAME
or %~
for the current working directory (with home directories replaced with ~
).
print -Pn "\e]2;%~\a"
This little code snippet changes the title of your current xterm (note: for other terminal types, the code looks a little different). Let me explain, what it does exactly. First it uses the print
command with the already explained parameter -P
. The second parameter -n
just suppresses insertion of a newline character at the end. Until here it's easy. The more complex part is the expression itself. But also this isn't as hard to understand as it seems. The first part \e]
just introduces an xterm escape command. \e
is the ASCII form of the special ESC
character (alternate form: \033
). The number specifies what type of command it is. 0 sets the window icon name (don't ask me about that) and the window title, 1 sets only the icon name and 2 only the window title. The following semicolon ends the command sequence. Everything up to the next following BEL
character (ASCII form \a
or \007
) is interpreted as the string to take either for the icon name or the window title (or both). In our case we have the Z Shell prompt escape sequence %~
which will expand to the current working directory.
Now if we put this in our chpwd()
function, every time the working directory is changed, the window title is updated.
function chpwd() {
print -Pn "\e]2;%~\a"
}
If you place this in your .zshrc
, every new ZSH instance will use this setting. Of course you can also write things such as the user and the host to the window title:
function chpwd() {
print -Pn "\e]2;%n@%M: %~\a"
}
I've put a list of all the prompt escape sequences in the links below.
What else could we use chpwd()
for? Well, you can of course not only update the window title with it. You can also do things like sourcing ZSH config files automatically:
function chpwd() {
if [ -r $PWD/.zsh_config ]; then
source $PWD/.zsh_config
fi
}
If there is a file called .zsh_config
in the current working directory, it is automatically sourced. This can be useful if you need special settings for a directory such as a different prompt. But be careful with this! It can be very dangerous because you can't control the contents of such a file before it is executed! Sometimes it is better to do folder-specific configurations directly inside the chpwd()
function:
function chpwd() {
if [[ $PWD == '/home/johndoe' ]]; then
echo "Hi, you're now entering John's home directory!"
if [[ $PROMPT_OLD != "" && $PROMPT_OLD != $PROMPT ]]; then
PROMPT=$PROMPT_OLD
fi
PROMPT_OLD=$PROMPT
PROMPT="(john's home) $PROMPT"
else
PROMPT=$PROMPT_OLD
fi
}
There are lots of possibilities. You can do whatever you want with this function. But what if you don't want to override the chpwd()
function directly (e.g. because you have several actions and you want to keep them modular or you don't want too override some pre-defined behavior)? Then you can also use the shell parameter $chpwd_functions
. This is an array of function names. All of these functions are executed in order when changing the current working directory.
function my_special_chpwd_function() {
echo "Hello World"
}
chpwd_functions=(${chpwd_functions[@]} "my_special_chpwd_function")
You can add as many functions as you want to this array. If a function does not exist, it is skipped silently. If a function produces an error, execution is stopped for all subsequent functions.
Read more about chpwd():
- zsh.sf.net: Directories introduction
- Using escape sequences in prompts
- How to change the title of an xterm
Trackbacks
Yet another reason I keep using zsh: https://t.co/lHWb7VEpzj (do stuff when you change directories, like blasting a todo file to stdout)
.@benhowdle Or be civilized and use zsh hook functions to do it for you! https://t.co/2joxEFeqgE