Ubuntu – Wrapping lines bugs when trying to colour terminal PS1 (even when escaping non printing caracters)

bashcommand lineps1

Since I've been issue while working too long without plugging my laptop in, I'm trying to write a new PS1 which show my current battery status using upower. I'm almost there, everything is working fine except that little (annoying) bug with color and wrapping (or more precisely, the lack of, ie caracters are printed on the begining of the same line when the end of the window is met/no new line).
At first, I thought I had made a mistake (like all the previous posts I've seen on that topic so far) and forgot to escape non printable caracters (with \[ \] ) but I can't see where… If not, is there any knowed issue with imbricating alias and function in PS1 (or did someone has a better idea for doing what I'm trying to do ?) ?

Here is my PS1 (the "if colored term" part) :

PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\](`battPer`)-\A:\[\033[01;34m\]\w\[\033[00m\]\$ '

And batPer function (and alias) in my .bash_aliases (comments bellow) :

batPer()
{
 percent=`upower -i /org/freedesktop/UPower/devices/battery_BAT1 | grep -E percentage | cut -d : -f 2 | cut -d " " -f 11 | cut -d % -f 1`
 plugged=`upower -i /org/freedesktop/UPower/devices/line_power_ACAD | grep -E "online: " | cut -d y -f 2` 

if [ "$plugged" = 'es' ] ; then
    echo -e "\[\e[0;92m\]$percent%\[\e[0m\]"
else
  if [ "$percent" -le 10 ]  ; then
     echo -e "\[\e[0;91m\]$percent%"
  else 
     echo -e "\[\e[0m\]$percent%" 
  fi
fi
 }
alias battPer='batPer'

(I'm taking the value of line_power_ACAD since it's status changes as soon as I (un)plug my laptop – I'm taking "y" from the "yes" as -f for my cut and therefore test "es" because… eeerrr… I'm lazy;) – then I test : plugged in -> value in green, not plugged in : <10% all the term char in red, >10% reset color/white. I'm doing the alias at the end because I had issue when trying to put the function itself in PS1).

Thanks guys for saving me from long nights of coloured nightmares, sorry if there is a huge mistake in the middle of my mess, I've been looking at those lines too long…

Update : Sorry, I've forgot to source .bashrc after last mod, I'm getting even more lost, when \[\e[0;92m\]$percent%\[\e[0m\] the ouput is :
output1
and when I don't put the escape caracters, it's fine (percentage in green) – still no wrapping… I'm I escaping the escape caracters somewhere ?!?

Best Answer

The problem would be that (emphasis mine, from the bash manual, 6.9 Controlling the Prompt):

After the string is decoded, it is expanded via parameter expansion, command substitution, arithmetic expansion, and quote removal, subject to the value of the promptvars shell option (see Bash Builtins).

So, the \[ in your function output comes too late to tell Bash that control codes follow. You need to set PS1 with the output of the function included for this to work. I'd suggest using PROMPT_COMMAND thus:

PROMPT_COMMAND='PS1="${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\](`batPer`)-\A:\[\033[01;34m\]\w\[\033[00m\]\$ "'

Note how the inner quotes are double quotes, so each time PS1 is set, the function output is added to it, and then Bash decodes PS1 to display the prompt.

Side note: with this, you don't need to echo -e the output. Before, you needed that for colour since Bash wasn't interpreting it after expanding the PS1 string. Now, Bash will decode the control codes as well.

Related Question