Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?

share|improve this question

2 Answers 2

up vote 14 down vote accepted

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.

share|improve this answer
1  
Probably not a big thing in practice, but I see the stock /etc/bashrc has the last line of chpwd as printf '\e]7;%s\a' "$PWD_URL" with the double quotes. Thanks for the tip. –  Ryan McCuaig Aug 2 '11 at 19:11
    
This 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. –  Ryan McCuaig Aug 3 '11 at 17:06
1  
Also 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 Aug 19 '11 at 11:08
1  
The 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. –  Chris Page Aug 26 '11 at 0:50
    
Thanks Ryan, Chris. I've updated the script to use the double quotes for consistency. –  CaptainPete Aug 29 '11 at 6:21

Here's my adaptation of /etc/bashrc for zsh. I've included percent-encoding of all invalid URL characters, which is important if you want this to work with all valid file and directory names.

This version registers a chpwd hook instead of defining chpwd directly. This enables more than one function to be registered in other scripts and configuration files.

# 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 LANG=C to process text byte-by-byte.
            local i ch hexch LANG=C
            for ((i = 1; i <= ${#PWD}; ++i)); do
                ch="$PWD[i]"
                if [[ "$ch" =~ [/._~A-Za-z0-9-] ]]; then
                    URL_PATH+="$ch"
                else
                    hexch=$(printf "%02X" "'$ch")
                    URL_PATH+="%$hexch"
                fi
            done
        }

        local PWD_URL="file://$HOST$URL_PATH"
        #echo "$PWD_URL"        # testing
        printf '\e]7;%s\a' "$PWD_URL"
    }

    # Register the function so it is called whenever the working
    # directory changes.
    autoload add-zsh-hook
    add-zsh-hook chpwd update_terminal_cwd

    # Tell the terminal about the initial directory.
    update_terminal_cwd
fi
share|improve this answer
    
Thanks, the accepted solution didn't work for me, but this one does. –  eelco Sep 8 '11 at 10:00
    
This one is working for me as well. –  Sikachu Feb 6 '12 at 22:13
1  
It should also be noted that this solution is already in oh-my-zsh, just activate the terminalapp plugin. –  Simon Dec 16 '13 at 10:11
    
Just to be clear, @Simon means this is now in oh-my-zsh, added since this answer was written. –  Chris Page Dec 16 '13 at 22:27
    
That 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 in oh-my-zsh. It is in deed the exact same solution and you deserve all the credit. –  Simon Dec 17 '13 at 18:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.