More useful bash prompt

Working on a project with a rather deep directory hierarchy, I finally got tired of my prompt overflowing the line and wrapping around. So, here’s a handy bash function to put in your $PS1. It should be noted that I did not write it, I only wrapped it up in a function and added some aesthetic options, but all the hard work and bash hackery was done by BearPerson from #bash.

# Produces the same effect as \w in $PS1, but makes sure that the
# result length doesn't exceed $1 chars. If any dirs are omitted, they
# are replaced with [...]. Optional $2 turns on ANSI VT100 escape
# sequences to dim the [...] part. Optional $3 specifies the colour
# code to dim to (otherwise 02, "dim")
bound_pwd ()
{
    limit=${1:-40}
    ansi=$2
    colour=${3:-2}

    regex="~$|~?/.{1,$limit}$|/[^/]*$"
    pre=$([ $ansi ] && echo -n "\[\033[${colour}m\]")
    suf=$([ $ansi ] && echo -n "\[\033[0m\]")

    CANDIDATE="${PWD/$HOME/~}"
    [[ $CANDIDATE =~ $regex ]]
    [[ $BASH_REMATCH != $CANDIDATE ]] && CANDIDATE="$pre[...]$suf$BASH_REMATCH"

    echo $CANDIDATE
}

To use it, either put it in your .bashrc, or in a file that is sourced by .bashrc, then replace \w in your $PS1 with $(bound_pwd). Personally I use $(bound_pwd 25 1) to get at most 25 chars, with VT100 colour codes.

Obligatory screenshot:

Bash prompt with the shortening

Update: If you use VT100 colours, remember to surround the bound_pwd invocation with \[ \], otherwise non-printing characters will confuse bash and make it wrap lines incorrectly

Update 2: The above update was wrong. It’s actually more complex than that, and due to the fact that bash doesn’t exactly have coherent escaping semantics, I had to rework the function. If you use VT100 colours and have downloaded an earlier version of bound_pwd, you have to download it again, it has changed. Additionally, to have it really work, you have to add this function:

set_ps1 ()
{
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:'"$(bound_pwd 25 1)"'$ '
}

And in .bashrc, add this:

# Yes, it's silly that ; alone is not valid syntax
PROMPT_COMMAND="${PROMPT_COMMAND:-true};set_ps1"

Make sure it’s the last line to set PROMPT_COMMAND. Especially if you’re on Debian/Ubuntu, as their default .bashrc sets it conditionally.