Resume Zsh-Terminal (OS X Lion)
OS X Lion has "Resume" feature, i. e. when you reopen an app it restores all windows and their contents. That works for Terminal as well. But if you use Zsh instead of Bash it doesn't restore opened directory. How can I fix this?
UPDATE: This isn't entirely correct, for reasons mentioned in the comments. Use the answer below. Thanks @ChrisPage for going the extra mile :)
The answer can be found by reverse engineering how bash does it in /etc/bashrc
. I tried many approaches from around the net but Apple's way seems to work best (go figure).
In your .zshrc
add the following
# Set Apple Terminal.app resume directory
if [[ $TERM_PROGRAM == "Apple_Terminal" ]] && [[ -z "$INSIDE_EMACS" ]] {
function chpwd {
local SEARCH=' '
local REPLACE='%20'
local PWD_URL="file://$HOSTNAME${PWD//$SEARCH/$REPLACE}"
printf '\e]7;%s\a' "$PWD_URL"
}
chpwd
}
Happy resuming.
For clarify, this answer pertains to the mysterious message in OS X Lion's Terminal.app preferences:
**Programs notify Terminal of the current working directory using escape sequences. You may need to configure your shell or other programs to enable this behavior.*
This answer works when you're using zsh as your shell. Terminal Resume for bash has already been implemented by Apple.
Here's my adaptation of /etc/bashrc for zsh. I've included percent-encoding of all URL characters that require it, which is important if you want this to work with all valid file and directory names.
This registers a precmd
hook, which allows more than one function to be registered in other scripts and configuration files.
UPDATED March 2019: Set LC_ALL
to empty so it doesn’t override LC_CTYPE
. Use precmd
to update the working directory at each prompt instead of using chpwd
to update it every time it is changed—command pipelines may change it temporarily and the terminal shouldn’t display those. Also, it can be helpful to have each prompt update the terminal state in case it was changed during the previous command. Use printf -v
to explicitly write to the variable instead of using subshell syntax.
# Tell the terminal about the working directory whenever it changes.
if [[ "$TERM_PROGRAM" == "Apple_Terminal" ]] && [[ -z "$INSIDE_EMACS" ]]; then
update_terminal_cwd() {
# Identify the directory using a "file:" scheme URL, including
# the host name to disambiguate local vs. remote paths.
# Percent-encode the pathname.
local url_path=''
{
# Use LC_CTYPE=C to process text byte-by-byte. Ensure that
# LC_ALL isn't set, so it doesn't interfere.
local i ch hexch LC_CTYPE=C LC_ALL=
for ((i = 1; i <= ${#PWD}; ++i)); do
ch="$PWD[i]"
if [[ "$ch" =~ [/._~A-Za-z0-9-] ]]; then
url_path+="$ch"
else
printf -v hexch "%02X" "'$ch"
url_path+="%$hexch"
fi
done
}
printf '\e]7;%s\a' "file://$HOST$url_path"
}
# Register the function so it is called at each prompt.
autoload add-zsh-hook
add-zsh-hook precmd update_terminal_cwd
fi