5

I want to display a green smile face if the previous exit code is 0 and red smile face if not successful.

Basically I want to do this prompt but with other stuff included.

PS1='\u@\h:\w `if [ $? = 0 ]; then echo \[\e[32m\]:\)\[\e[37m\]; else echo \[\e[31m\]:\(\[\e[37m\]; fi` $ '

I want to abstract the condition logic to a function but when I try to combine these two the escape characters show instead of the colors.

smiley()                                                                       
{
    if [ $? == 0 ]; then
        echo ':)'
    else
        echo ':('
    fi
}
RED="\033[1;5;91m"
GREEN="\033[1;5;92m"
NONE="\033[m"
NORMAL="\[\033[0m\]"
YELLOW="\[\033[1;4;93m\]"
MAGENTA="\[\033[35m\]"
WHITE="\[\033[1;37m\]"
BLINK="\[\033[5m\]"
#INVERT="\[\e[7m\]"
#OFF="\[\033[m\]"

PS1="${YELLOW}\u${MAGENTA}@${YELLOW}\h${NORMAL}:${WHITE}\w $(smiley)\n"

I even tried one line but it didn't work either.

 PS1='\[\033[1;4;93m\]\u\[\033[35m\]@\[\033[1;4;93m\]\h\[\033[0m\]\[\033[1;37m\]    \W if [ $? = 0 ]; then echo \[\e[32m\]:\)\[\e[37m\]; else echo \[\e[31m\]:\(\[\    e[37m\]; fi\n'

If there any way to do this without PROMPT_COMMAND?

Char
  • 1,635
  • 7
  • 27
  • 38
  • smiley is a great idea as status indicator! I used `{0}` or `{1}` but changing to this now. – karakfa Mar 25 '17 at 13:05
  • `PS1='\[\e[$([[ $? = 0 ]] && printf 32 || printf 31);1m\]^^^\[\e[m\] ${debian_chroot:+($debian_chroot)}\[\e[1;31m\]\u\[\e[1;33m\]@\[\e[1;36m\]\h \[\e[1;33m\]\w \[\e[1;35m\]\$ \[\e[0m\]' ` It will print ^^^ at the beginning of your prompt red or green. In addition you will have nice colourful user,host, path :) – Petras L Jan 31 '19 at 07:48

3 Answers3

5

I assume your quoting is not correct. I fiddled a little bit around with this and finally got it working:

$ bash --version
GNU bash, version 4.4.12(3)-release (i686-pc-cygwin)

$ smiley()
> {
>   if [ "$?" == "0" ]; then
>     echo -e '\e[0;32m:) '
>   else
>     echo -e '\e[0;31m:( '
>   fi
> }

$ PS1="$PS1"'`smiley`'

$ :) rm non-existing
rm: cannot remove 'non-existing': No such file or directory

$ :( echo "Everything fine"
Everything fine

$ :)

I did this on Windows (64 bit) but I guess it should work on Linux (or any other Unix-like) as well.

Notes:

  1. I wrote a function smiley() (a simplified version of your) and checked it by calling it from command line. It worked fine.

  2. I added it to PS1 and it echoed :) in any case. I realized that the bash replacement was already done in assignment of PS1.

  3. Thus, I safed the invocation of smiley by an extra pair of single quotes to defer the invocation until the output of prompt. Now, it works like expected.

  4. Because the questioner required a colored version I made an update. I found the actual solution in this link: SO: How to change the output color of echo in Linux. It's easy to find the necessary terminal escape sequences. The trick is to use echo -e to enable the backslash escaping in echo.

The snapshot below shows how does it look (with colors):

Snapshot of <code>bash</code> with tuned prompt in an <code>xterm</code>

Community
  • 1
  • 1
Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
  • Did you get it to work with colors? Green for the smiley and red for the frowny face? – Char Mar 25 '17 at 16:42
  • This is awesome! Why do you use the backtick symbol for the function call tho? Is `smiley` different from $(smiley)? – Char Mar 25 '17 at 17:18
  • @Charles You will find the exact answer in `man bash`. I believe `$( )` is new (and may be nested). The backticks are old and may not be nested. (Please, correct me if you read something else in the man page.) – Scheff's Cat Mar 25 '17 at 17:22
  • 1
    [This](http://stackoverflow.com/questions/22709371/bash-backticks-vs-braces) suggests that you are correct that they both do substitution but backticks are deprecated because they are not POSIX standard. Also, they silently remove double quotes according to that answer. – Char Mar 25 '17 at 17:28
  • Instead of `rm non-existing` and `echo ..` for testing you could just use `true` and `false` commands – Marcin Orlowski Jan 12 '18 at 22:47
  • I believe this solution doesn't count prompt length correctly. – Yurkee Nov 12 '20 at 18:26
  • @Yurkee Sorry, where did I _count prompt length_? – Scheff's Cat Nov 12 '20 at 18:58
2

This works for me:

export PS1="\
\$(if [[ \$? -gt 0 ]]; then printf \"\\[\\033[01;31m\\]\xF0\x9F\x98\xA7\"; else printf \"\\[\\033[01;32m\\]\xF0\x9F\x98\x83\"; fi)\
\[\033[01;30m\]\u\
\[\033[01;33m\]@\
\[\033[01;36m\]\h \
\[\033[01;33m\]\w \
\[\033[01;31m\][\$(__git_ps1 '%s')] \
\[\033[01;35m\]\\$ \
\[\033[00m\]\
"
Michael A.
  • 1,071
  • 12
  • 21
0

I adapted Michael A's answer for a .bashrc file (in my case, git-for-windows)

git bash rc screenshot

PS1='\
`if [[ $? -gt 0 ]]; then printf "\[\033[01;31m\]:("; else printf "\[\033[01;32m\]:)"; fi`\
\[\033]0;$TITLEPREFIX:$PWD\007\] \
\[\033[32m\]\u@\h \
\[\033[33m\]\w\
\[\033[36m\]`__git_ps1`\
\[\033[0m\]\n$'

For reference the default is:

PS1='\
\[\033]0;$TITLEPREFIX:$PWD\007\]\n\
\[\033[32m\]\u@\h\
\[\033[35m\] $MSYSTEM \
\[\033[33m\]\w\
\[\033[36m\]`__git_ps1`\
\[\033[0m\]\n$'
RJFalconer
  • 10,890
  • 5
  • 51
  • 66