Reverse-search in CLI: messed up output afterwards [duplicate]

See my edit below, this is not totally a duplicate of Shell prompt customization and cmd behavior

My reverse-search function in the CLI is broken and I don't know how to fix it back...

When I hit ctrl+r and search a command I did earlier, find it then press the right arrow key to use it, the output is broken. Here is an example:

# I reverse-searched the word "test" then pressed right arrow
yoshiji@x1carbon:~/path/to/git/folder (master) $ch)`test': rake test
#                                              ^^^^^^^^^^ weird output
#                                                     ^ cursor right there

It also "shifts" my cursor to a different position. If I press enter, the right command is executed (rake test in this case) so it means the text displayed is not the same as what is actually executed.

I know this is most-likely related to my PS1 export in my ~/.bashrc, so here are the last lines of this file:

# Git branch in prompt.
git_branch() {
  branch=$(__git_ps1 2> /dev/null)
  if [ "$branch" = " (master)" ]; then
     echo -e "\033[33m${branch}\033[00m" # yellow
  elif [ "$branch" = "" ]; then
     echo -e "\033[90m (no git)\033[00m" # red
  else
     echo -e "\033[32m${branch}\033[00m" # green
  fi
}
PS1='\u@\h:\w$(git_branch) \$ '

This is something I wrote to displays the git branch in orange (if master branch) or else in green (or no git in gray).

Do you guys have any idea on what is causing this weird behavior?


Edit: This is a different problem from the possible duplicate in the way that I am using echo -e "some string" to return a string having color+name of the git branch from the function git_branch(). Using echo -e does not escape the characters \[ and \] (try it yourself in your CLI: echo -e "\[\033[33m\]test").

Ideally, I would like to keep those conditional colors based on the branch's presence & name (gray if no branch, orange if master, else green).


Solution 1:

Wrap the color sequences in readline escapes like so:

echo -e "\001\033[33m\002${branch}\001\033[00m\002" # yellow
echo -e "\001\033[90m\002 (no git)\001\033[00m\002" # red
echo -e "\001\033[32m\002${branch}\001\033[00m\002" # green

The readline escapes are \001 at the start of a non-printing sequence, and \002 at the end. These are equivalent to \[ and \], respectively, in the PS1 string.

Source: archemiro's answer on bash prompt and echoing colors inside a function - Stack Overflow


This is my answer from another question with the code changed.

Solution 2:

When you put colour codes in your prompt you have to add extra markers to let the terminal know that you have invisible characters in the prompt

Change

 echo -e "\033[33m${branch}\033[00m" # yellow

to

 echo -e "\[\033[33m\]${branch}\[\033[00m\]" # yellow
 # .......^^........^^.........^^........^^

and so on

See Controlling the Prompt in the bash manual.