Resume Zsh-Terminal (OS X Lion)
Solution 1
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.
Solution 2
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
Related videos on Youtube
Simon Perepelitsa
Updated on September 18, 2022Comments
-
Simon Perepelitsa almost 2 years
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?
-
nhooyr about 5 yearsRelated to the answers below: making terminal.app aware of the directory is also useful for opening new terminals in the same directory as the current one
-
-
Ryan McCuaig almost 13 yearsProbably not a big thing in practice, but I see the stock /etc/bashrc has the last line of
chpwd
asprintf '\e]7;%s\a' "$PWD_URL"
with the double quotes. Thanks for the tip. -
Ryan McCuaig almost 13 yearsThis is now making its way into oh-my-zsh (see github.com/robbyrussell/oh-my-zsh/pull/522). You'll need to make sure you've turned on the osx plugin in your zshrc.
-
Chris Page almost 13 yearsAlso note that this code only percent-encodes spaces. For bonus points, make it percent-encode all illegal URL characters (and see if you can do it without invoking any programs). This is important if you want it to work with all valid pathnames. Also, some characters aren't even considered part of escape sequences, so percent-encoding is required to get them to the terminal. I was able to do this for bash, but I haven't tried testing it with zsh.
-
Chris Page almost 13 yearsThe quotes around "$PWD_URL" are required to prevent the pathname from being munged. EDIT: This is required in bash, but optional in zsh. I prefer to use the quotes consistently so it's portable.
-
captainpete almost 13 yearsThanks Ryan, Chris. I've updated the script to use the double quotes for consistency.
-
captainpete almost 13 yearsChris, yes this only escapes spaces -- I figured if Apple's built-in bash version only requires the spaces escaped then Terminal.app would handle this behaviour from here too. What sorts of paths are breaking? I'm able to make weird paths like "~/©/stΩff" work with the default behaviour.
-
eelco almost 13 yearsThanks, the accepted solution didn't work for me, but this one does.
-
sikachu over 12 yearsThis one is working for me as well.
-
Chris Page over 12 years@CaptainPete Please use the complete version I posted. Terminal cannot “handle this behavior” if invalid characters are not percent-encoded. First, to conform to terminal standards, it doesn’t treat control characters and some whitespace as part of an escape sequence. Second, to conform to URL standards, it requires all invalid URL characters to be percent-encoded.
-
Chris Page over 12 yearsThe reason this escape sequence was created, and the reason it uses URLs, was to provide complete support for all valid pathnames, not just some of them, via URL percent-encoding. The current version of /etc/bashrc should only be taken as a starting point to draw from, not a justification for limiting the solution when you’re going out of your way to develop and install code for another shell.
-
captainpete over 12 yearsThanks @ChrisPage, nice solution! I've updated the answer.
-
Simon over 10 yearsIt should also be noted that this solution is already in oh-my-zsh, just activate the
terminalapp
plugin. -
Chris Page over 10 yearsJust to be clear, @Simon means this is now in oh-my-zsh, added since this answer was written.
-
Simon over 10 yearsThat is correct @ChrisPage, I apologize for the ambiguous phrasing (english is not my mother tongue). What I meant to say was just that, you don't need to paste this in your
.zprofile
or whatever, like I did before realizing it is in fact available inoh-my-zsh
. It is in deed the exact same solution and you deserve all the credit. -
Ilya Katz over 10 yearsThanks ChrisPage and Simon, it's been bugging me for ages. @ChrisPage, do you think it would be worth updating the answer to indicate that this is not part of the plugin so it's more clearly visible
-
Chris Page over 10 years@IlyaKatz I’m not sure what you’re trying to say. Is “not” a typo for “now”?
-
Ilya Katz over 10 years@ChrisPage, sorry, you're correct.
-
Chris Page over 10 years@IlyaKatz I’m unfamiliar with oh-my-zsh. Can someone suggest how to describe exactly how it’s part of oh-my-zsh, and how to describe it to both people familiar and unfamiliar with it? And how to link to it?
-
Chris Page over 9 years@AndrewJanke I assume that’s because your environment has set LC_CTYPE, which overrides LANG. I’ll see about updating this to use LC_CTYPE instead.
-
besson3c over 9 yearsAh, yep: I have LC_CTYPE set. oh-my-zsh sets it from LANG during its initialization. Didn't realize that was nonstandard.
-
Chris Page about 9 years@AndrewJanke I have tested and updated the code to use LC_CTYPE instead of LANG.
-
ShreevatsaR about 9 years@ChrisPage: Thanks for this. I installed oh-my-zsh to get this feature, but have uninstalled it because it did too much nonsense. Your answer works great. Anyway, for those who have installed oh-my-zsh, they can put
plugins=(terminalapp)
(or a list, likeplugins=(git osx terminalapp)
say) in their~/.zshrc
to get exactly the contents of your answer loaded for them. -
Fijat Ogur over 8 yearsUpdate: OMZ has since added this to the auto-loaded
lib/termsupport.zsh
file, which as of right now can be used without the rest of OMZ, as long as you also includelib/functions.zsh
. (Incase any of the rest of you don't like copy-pasting chunks of code into.zshrc
, and would prefer to depend upon external resources!) -
Fijat Ogur over 8 years… for any of you using Zgen, this becomes as easy as:
zgen load robbyrussell/oh-my-zsh lib/functions.zsh && zgen load robbyrussell/oh-my-zsh lib/termsupport.zsh
-
fred jones almost 4 yearsInterestingly, this code is used verbatim by Apple in /etc/zshrc_Apple_Terminal now that Zsh is the default shell.