linux - Why does my zsh prompt wander upwards when window is too narrow?

06
2014-04
  • javex

    I have a weird behaviour that seems to be a combination of zsh and maybe urxvt (?) My setup is this: I start urxvt -e 'tmux' to get myself a terminal which launches zsh as the default shell.

    I then started customizing my $PROMPT and it currently looks like this:

     zstyle ':vcs_info:*' enable git svn hg bzr
     zstyle ':vcs_info:*' formats $' \e[0;33m(%s:%b)\e[0m'
     precmd () { vcs_info }
     PROMPT+=$'\e[0;31m%n\e[0m'
     PROMPT+="@"
     PROMPT+=$'\e[0;34m%m\e[0m'
     PROMPT+=":"
     PROMPT+=$'\e[0;36m%3c\e[0m'
     PROMPT+=$'\e[0;33m%c\e[0m'
     PROMPT+='${vcs_info_msg_0_}'
     export PROMPT
    

    You might notice the second %c line, that is, of course, for testing.

    The normal behaviour of a prompt is to create a new line after pressing enter, optionally executing the command that may be present. The a new line is printed. However, I notice a different behaviour under certain circumstances: When I press enter, the command is executed and the output is displayed. However, when the previous prompt was not at the top of the terminal, the last line of previous output is overwritten because the whole new output is moved one line upwards.

    Maybe an example is in order. Start with an empty terminal and a new prompt:

    user@hostname:very long directory name/with multiple components/foo~very long directory name/with multiple components/foo (git:master)
    

    Now we enter ls -la in this directory (sample output):

    user@hostname:very long directory name/with multiple components/foo~very long directory name/with multiple components/foo (git:master)ls -la
    drwxr-xr-x 7 user user 4096 25. Jan 16:17 .
    drwxr-xr-x 7 user user 4096 25. Jan 16:17 ..
    user@hostname:very long directory name/with multiple components/foo~very long directory name/with multiple components/foo (git:master)
    

    Notice how there is something missing, as in reality, there is a .git directory in here:

    drwxr-xr-x 7 user user 4096 25. Jan 16:17 .
    drwxr-xr-x 7 user user 4096 25. Jan 16:17 ..
    drwxr-xr-x 7 user user 4096 25. Jan 16:17 .git
    

    What happened here is easily described: The command output is generated correctly but then the prompt line is moved up by one line and overwrites the last line of output. So if I do the same again, my output looks like this:

    user@hostname:very long directory name/with multiple components/foo~very long directory name/with multiple components/foo (git:master)ls -la
    drwxr-xr-x 7 user user 4096 25. Jan 16:17 .
    user@hostname:very long directory name/with multiple components/foo~very long directory name/with multiple components/foo (git:master)ls -la
    drwxr-xr-x 7 user user 4096 25. Jan 16:17 .
    drwxr-xr-x 7 user user 4096 25. Jan 16:17 ..
    user@hostname:very long directory name/with multiple components/foo~very long directory name/with multiple components/foo (git:master)
    

    As you can see, everything was moved up once again, this time replacing the .. from the last output and the .git from this output.

    But this does not happen on all setups. It only happens, when the window is too narrow. I additionally, tested this by resizing the open urxvt window with zsh inside. When I make it too narrow. From what I see it starts once the prompt takes up about two thirds of the windows width. However, I don't know why this happens on this occassion.

    Some notes: - It does not happen with bash (even when the prompt itself is multiline) - RPROMPT and RPROMPT2 are empty - It does not seem to depend on the type of information displayed (i.e. disabling vcs_info only helps if the prompt gets short enough again) - It does not happen when the prompt is multiline (and the second line does not reach the two-thirds mark) - It does not happen in a console (tty), but it does happen with xterm and urxvt.

    Summary: My zsh prompt moves when line upwards if the prompt line is about two thirds of the window long.

  • Answers
  • javex

    I seem to have fixed it by using %{fg[color]%} instead of the bash color codes (of course for that I need to load the color module).


  • Related Question

    terminal - Using zsh extensions - why do I have to manually type "zsh" to get it to appear?
  • Wayne M

    I am using Robby Russell's "oh-my-zsh" extension on OSX 10.5 Leopard. However I find that it's not loaded by default.. when I start a new Terminal it uses the "default" ZSH prompt, and I must manually type "zsh" and press Return to get the "enhanced" prompt. My .zshrc file lists the ZSH path as pointing to the oh-my-zsh directory:

    This gets very annoying because every time I open a new tab I've got to type zsh again (as an aside is it possible to get a new tab to remember my current working directory? I mainly write Rails apps so I'll have 2-3 windows open inside the same directory and it's frustrating to have to cd back into it every time). Is there an easy way to get it automatically start oh-my-zsh when I open a terminal so I don't have to type zsh every time?

    EDIT

    I automatically installed oh-my-zsh following Robby's instructions on Github, so here's the .zshrc it created for me:

    # Path to your oh-my-zsh configuration.
    export ZSH=$HOME/.oh-my-zsh
    
    # Set to the name theme to load.
    # Look in ~/.oh-my-zsh/themes/
    export ZSH_THEME="maran"
    
    # Comment this out to disable weekly auto-update checks
    # export DISABLE_AUTO_UPDATE="false"
    
    source $ZSH/oh-my-zsh.sh
    
    # Customize to your needs...
    export     PATH=/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr  /local/bin:/usr/X11/bin:/usr/local/git/bin
    export GIT_EDITOR="mate -w"
    

    I tried changing the default shell to point to that but then I get an error saying it's been set to an illegal variable. The $HOME variable points correctly to my home directory, but it doesn't seem to be loading until I type zsh in the terminal when I have the regular zsh prompt.

    EDIT

    Here is the output of pstree -wp $$

    -+= 00001 root /sbin/launchd
     \-+= 00066 waynemolina /sbin/launchd
       \-+= 68844 waynemolina /Applications/Utilities/Terminal.app/Contents/MacOS/Terminal -psn_0_704684
         \-+= 68845 root login -pfq waynemolina /bin/zsh
           \-+= 68846 waynemolina -zsh
             \-+= 68939 waynemolina pstree -wp 68846
               \--- 68940 root ps -axwwo user
    

  • Related Answers
  • Chris Johnsen

    Back in 10.4, Terminal has a preference for “When creating a new Terminal window” to either use /usr/bin/login or to let the user specify a command. I expect that Terminal in 10.5 has something similar.

    Do you happen to have something like zsh -f as the specified command instead of using /usr/bin/login or a zsh invocation without -f? The -f option will cause zsh to ignore all the startup files except /etc/zshenv (i.e. it will ignore your ~/.zshrc).

    Another way to check this setting might be with defaults read com.apple.Terminal Shell. If it shows some output you have a custom setting. If it is blank or does not exist then you are probably still using the default of /usr/bin/login.

    Edited to add:
    In one of your shells with the default prompt (a new Terminal window or tab), check for the following:

    • Does set -o | fgrep rcs show “on” for norcs?
    • Does [[ "$ZDOTDIR" -ef "$HOME" ]] || echo "ZDOTDIR=$ZDOTDIR" show anything?

    If one or both of these conditions are true, you'll need to track down where they are being set. Note that norcs might be set with any of set +o rcs, set -o norcs, setopt norcs, unsetopt rcs, or set -f. Also the option names are not case sensitive and may have underscores inserted anythere (NO_rC___s is the same as norcs). Look in /etc/zshenv, /etc/zprofile, /etc/zshrc, /etc/zlogin; and .zshenv, .zprofile, .zshrc, and .zlogin from your ZDOTDIR directory.

    It might also be useful to know the full parentage of your “default prompt” shells (pstree -wp $$ if you have pstree from (e.g.) MacPorts). Maybe the normal ‘rc’ process is being interrupted by something like zsh -f in an ‘rc’ file.

  • Ryan Thompson

    I don't know too much about how Mac OS X works with shells, but in general I find it useful to sprinkle some echo statements around my initialization files, to make sure that they are being sourced. So, in your .zshrc file, you could put a line that says echo "Loading .zshrc". And so on. The presence or absence of these echo statements when you start a new shell (or open a new tab) should help you diagnose the problem.

    As for the directory changing problem, there are two potential solutions:
    1. Use screen, and forget about tabs.
    2. Write a function to echo the current directory to a file somewhere, then put that function in your precmd, and then add a line in .zshrc to read that file and cd to it. To be more specific (but untested!):

    PWD_SAVE_FILE="$HOME/.pwd_save"
    function savepwd {
      pwd > "$PWD_SAVE_FILE"
    }
    
    function precmd {
      savepwd
    }
    
    cd "`cat "$PWD_SAVE_FILE"`"
    
  • Anark

    I had this problem. It was due to having a .zlogin in my home directory. Once I removed .zlogin oh my zsh worked

  • Dennis Williamson

    Try putting this in your ~/.zshrc file for debugging purposes:

    Right after this line:

    export ZSH=$HOME/.oh-my-zsh
    

    Put:

    echo $HOME
    echo $ZSH