The idea of my PS1
configuration is to show some extended info like Mercurial or Git repo status, command execution time, etc. The prompt is split by two lines because it produces too many characters to fit into a single line. Here is my PS1
in my .bashrc
(not sure if the entire source code is necessary here):
function prompt_status {
local color_app="\e[1;38;5;214m"
local color_branch="\e[1;38;5;32m"
local color_revision="\e[0;38;5;64m"
if git rev-parse --is-inside-work-tree &> /dev/null; then
local branch="$(git rev-parse --abbrev-ref HEAD | tr -d '\n')"
local revision="$(git rev-parse HEAD | tr -d '\n')"
echo -ne $color_app"git "$color_branch"$branch "$color_revision"($revision)"
elif hg status &> /dev/null; then
local branch="$(hg branch | tr -d '\n')"
local revision_number="$(hg identify -n | tr -d '\n')"
local revision="$(hg parent --template '{node}' | tr -d '\n')"
echo -ne $color_app"hg "$color_branch"$branch "$color_revision"($revision_number:$revision)"
else
return
fi
echo -e " \e[0m"
}
function prompt_return_value {
RET=$?
if [[ $RET -eq 0 ]]; then
echo -ne "" #echo -ne "\e[32m$RET\e[0m"
else
echo -ne "\e[1;37;41m$RET\e[0m "
fi
}
function timer_start {
timer=${timer:-$SECONDS}
}
function timer_stop {
seconds_elapsed=$(($SECONDS - $timer))
unset timer
}
function prompt_seconds_elapsed {
local c;
local t=${seconds_elapsed}s
if [ $seconds_elapsed -ge 60 ]; then
c=196
t=$(format_seconds $seconds_elapsed)
elif [ $seconds_elapsed -ge 20 ]; then
c=214
elif [ $seconds_elapsed -ge 10 ]; then
c=100
elif [ $seconds_elapsed -ge 5 ]; then
c=34
elif [ $seconds_elapsed -ge 1 ]; then
c=22
else
return
fi
echo -ne "\e[0;38;5;${c}m${t} \e[0m"
}
function format_seconds {
((h=${1}/3600))
((m=(${1}%3600)/60))
((s=${1}%60))
printf "%02d:%02d:%02d\n" $h $m $s
}
trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop
export PS1="\n\e[1;38;5;106m\u@\h \e[0;38;5;136m\w\[\e[0m\]\n\$(prompt_return_value)\$(prompt_seconds_elapsed)\$(prompt_status)\$ "
The problem is that the prompt looks broken when a terminal window has small width. This is what I get for 80 columns:
username@some-very-long-hostname ~/tmp/d
06a14b06cac) $ 9866c9d0d26d2b27063a89ee1c330
It's like wrapped at the 2nd line causing total mess (see the $ sign in the middle). It works almost perfectly for a larger terminal column number, say 120:
username@some-very-long-hostname ~/tmp/d
hg default (0:69866c9d0d26d2b27063a89ee1c3306a14b06cac) $
Also I noticed that add more text to the end of the terminal line causes an issue that's very similar to the effects described for 80 columns above. The question is: does bash
handle new lines or "too long" incorrectly for PS1
?
Thanks.
UPDATE
This question is not an exact duplicate of Why is my bash prompt getting bugged when I browse the history? . After some discussion with @AdamKatz, it seems that zero-length output escapes \[
and ']
work only when they are literally put in the PS1
string, but they does not seem to work when returned from a function causing to appear unescaped on terminal.