skip to Main Content

So I am trying to customize the PS1 value to add a check mark or x to the prompt depending on the result of the previous command. Surprisingly I got that part to work fine.

However, it has broken the part of the prompt that shows the Git branch when viewing a Git repository.

Here is the previous PS1 value:

user@PC MINGW64 ~/Git
$ echo $PS1
[33]0;$TITLEPREFIX:$PWD07]n[33[32m]u@h [33[35m]$MSYSTEM [33[33m]w[33[36m]`__git_ps1`[33[0m]n$

and here is the new ~/.bash_profile script that breaks it:

function nonzero_return() {
    RETVAL=$?
    if [[ $RETVAL -ne 0 ]]
    then
        echo "❌ ($RETVAL)"
    else
        echo "✅"
    fi
}

export PS1="[e[31m]`nonzero_return`[e[m][33]0;$TITLEPREFIX:$PWD07]n[33[32m]u@h [33[35m]$MSYSTEM [33[33m]w[33[36m]`__git_ps1`[33[0m]n$"

Here is an example of the old prompt versus the new one:

user@PC MINGW64 ~/Git/docker-brew-ubuntu-core (dist-amd64)
$


✅
user@PC MINGW64 ~/Git/docker-brew-ubuntu-core
$


❌ (127)
user@PC MINGW64 ~/Git/docker-brew-ubuntu-core
$

SOLUTION

Thanks to @davlet, @joanis, and @torek for helping me resolve this issue. I also used some other suggestions from them to edit my PS1 value even further into a place that I really liked. If anyone is curious, here is the new ~/.bash_profile script:

function nonzero_return() {
    local RETVAL=$?
    if [[ $RETVAL -ne 0 ]]
    then
        echo "❌($RETVAL)"
    else
        echo "✅"
    fi
}

PS1='[e]0;Git Bash: $MSYSTEM07]n[e[31m]`nonzero_return`[e[32m] u@h [e[35m]w[e[36m]`__git_ps1`e[0mn$'

2

Answers


  1. I think you want to use single quotes when assigning to PS1, and loose the backslashes before backticks. Also PS1 shouldn’t be exported:

    PS1='[e[31m]`nonzero_return`[...]'
    

    Also, make RETVAL local in your helper function, otherwise it may interfere with other scripts, ie:

    local RETVAL=$?
    
    Login or Signup to reply.
  2. I’m going to steal that prompt, I really like it!

    You just need to escape the backticks around __git_ps1:

    export PS1="[e[31m]`nonzero_return`[e[m][33]0;$TITLEPREFIX:$PWD07]n[33[32m]u@h [33[35m]$MSYSTEM [33[33m]w[33[36m]`__git_ps1`[33[0m]n$"
    

    The difference is

    ...`__git_ps1`...
    

    instead of

    ...`__git_ps1`...
    

    in the export statement.

    A bit of an explanation

    The way the PS1 variable works is that it gets evaluated each time the prompt is printed. That’s why you can have functions in it like __git_ps1 or your nonzero_return do something different each time the prompt is printed.

    When you use double quotes to define PS1, e.g.:

    PS1="...`my_function`...$MYVAR..."  # won't work
    

    the shell applies normal double quote expansion right when PS1 is defined, which includes expanding that backtick’d function call, and filling in the current value of $MYVAR, storing only the results in PS1, which is not what you want.

    If you escape the backticks, or, better yet, use single quotes as @davlet said, PS1 now contains those backticks and variables themselves, which get evaluation each time the prompt is printed.

    You can give it a try: if you use single quotes and then change the value of $MSYSTEM, your prompt will reflect that change right away. The get the same effect with double quotes, you’d have to escape the $.

    Getting rid of that newline

    In the comments, you ask how to remove the newline after the checkmark or X. That newline comes from the n you have in the middle of your PS1 definition. But I personally like that newline, because it means my prompt is preceded by a blank line, separating it more nicely from the output of the previous command, especially if that didn’t output its own newline.

    Here’s how I would tweak your prompt:

    PS1='[33]0;$TITLEPREFIX:$PWD07]n[e[31m]`nonzero_return`[e[m][33[32m]u@h [33[35m]$MSYSTEM [33[33m]w[33[36m]`__git_ps1`[33[0m]n$'
    

    Details:

    • [33]0;$TITLEPREFIX:$PWD07] sets the Window’s title bar
    • n separates the prompt from the previous command’s output
    • [e[31m]nonzero_return[e[m] your return code function in bold red (note that the [e[m|] is superfluous here: it says reset the colour, but your next thing sets the colour again)
    • [33[32m]u@h user@host in green
    • [33[35m]$MSYSTEM the value of $MSYSTEM in purple
    • [33[33m]w current working directory in yellow
    • [33[36m]`__git_ps1` is the Git status in Cyan
    • [33[0m] resets the font
    • n is the newline
    • $ is the "superuser indicator" which turns to # when you are the superuser.

    More notes:

    • As @torek points out, [ and ] are unnecessary before the final n
    • You mix e and 33: those are both escape sequences inserting an actual escape character in there. I prefer to use e everywhere because I find it more legible.
    • This is a useful reference on bash prompts: https://wiki.archlinux.org/title/Bash/Prompt_customization
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search