2

I use a custom PS1 to display more relevant information in my terminal, such as if I'm in a git directory and if it's clean or needs to commit changes. However, sometimes when I'm arrowing through commands, part of the terminal line disappears:

@ ~/tests/testing [tests] > grunt
# up arrow, down arrow
@ ~/tests/testing [t

Essentially, the ests] > gets cut off and I'm left with just the [t.

Is there any particular reason why part of the line is getting cut off with this PS1 config?

Here's some additional info:

My TERM env var is xterm-256color. Here's my .bash_profile:

red='\033[0;31m'
yellow='\033[0;32m'
orange='\033[0;33m'
blue='\033[0;34m'
pink='\033[0;35m'
NC='\033[0m'

function is_git {
  if git rev-parse --is-inside-work-tree 2>/dev/null; then
    return 1
  else
    return 0
  fi
}

function stuff {
  if [ $(is_git) ]; then
    git_dir="$(git rev-parse --git-dir 2>/dev/null)"

    if [ -z "$(ls -A ${git_dir}/refs/heads )" ]; then
      echo -en " [${orange}init${NC}]"
      return
    fi

    echo -n " ["
    if [ $(git status --porcelain 2>/dev/null| wc -l | tr -d ' ') -ne 0 ]; then
      echo -en "${red}"
    else
      echo -en "${blue}"
    fi
    echo -en "$(git rev-parse --abbrev-ref HEAD)${NC}]"
  fi
}

export PS1="@ \w\[\$(stuff)\]\[\$(tput sgr0)\] > "
josh
  • 153

2 Answers2

2

@i_am_root's suggestion to put the \[ and \] inside the definition of red and the like is a good one. However, per this, bash only processes \[ and \] in PS1, not in text included in PS1 by $(). Therefore, use \001 and \002 (or \x01 and \x02) inside red and the like instead of \[ and \].

Note: Per this answer, only the escape codes should be in the \001 and \002. The text that will be visible to the user should be outside the \001 and \002 so that bash knows it takes up space on the screen and can account for that when redrawing.

cxw
  • 1,739
1

Bash color codes, escaping characters, assignments, and such get confusing quickly.

Try this code sample which replaces the echo commands by adding to the PS1 variable.

red='\[\033[0;31m\]'
yellow='\[\033[0;32m\]'
orange='\[\033[0;33m\]'
blue='\[\033[0;34m\]'
pink='\[\033[0;35m\]'
NC='\[\033[0m\]'

export PS1="@ \w"

function is_git {
  if git rev-parse --is-inside-work-tree 2>/dev/null; then
    return 1
  else
    return 0
  fi
}

function stuff {
  if [ $(is_git) ]; then
    git_dir="$(git rev-parse --git-dir 2>/dev/null)"

    if [ -z "$(ls -A ${git_dir}/refs/heads )" ]; then
      PS1="${PS1} [${orange}init${NC}]"
      return
    fi

    PS1="$PS1 ["
    if [ $(git status --porcelain 2>/dev/null| wc -l | tr -d ' ') -ne 0 ]; then
      PS1="${PS1}${red}"
    else
      PS1="${PS1}${blue}"
    fi
    PS1="${PS1}$(git rev-parse --abbrev-ref HEAD)${NC}]"
  fi
}

stuff
PS1="${PS1}$(tput sgr0) > "
i_am_root
  • 333