1

I already changed my bash output format to something like this:

enter image description here

which I am very happy with. I achieved this by adding this code to the .bashrc:

set_PS1()
{
    local RESET=$(tput sgr0 )
    local BOLD=$(tput bold )
    local RED=$(tput setaf 1 )
    local GREEN=$(tput setaf 2 )
    local YELLOW=$(tput setaf 3 )
    local BLUE=$(tput setaf 4 )
    local CYAN=$(tput setaf 6 )

    local WHOAMI='\u'
    local WHERE='\w'
    local HOSTNAME='\h'
    local TIME='\D{%H:%M:%S}'


     exit_code_prompt() {
        local EXIT_CODE=$?
        local RED=$(tput setaf 1 )
        local GREEN=$(tput setaf 2 )
        if [ $EXIT_CODE -ne 0 ]; then
            echo -e "$RED$BOLD\xE2\x9C\x98 $EXIT_CODE \xE2\x86\x92"  # Red cross mark symbol
        else
            echo -e "$GREEN$BOLD\xE2\x9C\x93 \xE2\x86\x92"  # Green checkmark symbol
        fi
    }

    local LINE_1="$BOLD$YELLOW$TIME $CYAN$WHOAMI$BLUE@$CYAN$HOSTNAME$RESET$BOLD":" $BLUE$WHERE$RESET"
    local LINE_2="$BOLD\$(exit_code_prompt) "$RESET$BOLD' \$: '$RESET


    PS1="$LINE_1\n$LINE_2"

    unset -f set_PS1
}

set_PS1

My problem was that if I had a comand that is longer than one line it didn't do a linebreak but instead it overwrote the content from the same line (only in visual representation ofc):

enter image description here

Now when I delete the complete command, it deletes a part of the bash prompt as well:

enter image description here

This could be solved by adding \[ and \]:

    local LINE_1="\[$BOLD$YELLOW$TIME $CYAN$WHOAMI$BLUE@$CYAN$HOSTNAME$RESET$BOLD":" $BLUE$WHERE$RESET\]"
    local LINE_2="\[$BOLD\$(exit_code_prompt) "$RESET$BOLD' \$: \]'$RESET

Another problem persists though. When I cycle through the last used commands it deletes the prompt sign $:

enter image description here

how do I solve this issue?

I already looked into using zsh but I didn't want to loose the bash functionality like keyboard shortcuts that I already got used to...

UPDATE: below is my updated code, that still doesn't work:

set_PS1()
{
    local Reset="\\[$(tput sgr0 )\\]"
    local Bold="\\[$(tput bold )\\]"
    local Red="\\[$(tput setaf 1 )\\]"
    local Green="\\[$(tput setaf 2 )\\]"
    local Yellow="\\[$(tput setaf 3 )\\]"
    local Blue="\\[$(tput setaf 4 )\\]"
    local MagentaBG="\\[$(tput setab 5 )\\]"
    local Cyan="\\[$(tput setaf 6 )\\]"

    local Whoami='\u'
    local Where='\w'
    local Hostname='\h'
    local Time='\D{%H:%M:%S}'
    local Exit_Code="$?"

    exit_code_prompt() {
        local Exit_Code="$?"
        local Red="$(tput setaf 1 )"
        local Green="$(tput setaf 2 )"
        if [ $Exit_Code -ne 0 ]; then
            printf "$Red\xE2\x9C\x98 $Exit_Code \xE2\x86\x92 " # Red cross mark symbol
        else
            printf "$Green\xE2\x9C\x93 \xE2\x86\x92 " # Green checkmark symbol
        fi
    }

    local Line_1="$Bold$Yellow$Time $Cyan$Whoami$Blue@$Cyan$Hostname$Reset$Bold":" $Blue$Where$Reset"
    local Line_2="$Bold\$(exit_code_prompt)$Reset$Bold \$: $Reset"

    PS1="$Line_1\n$Line_2"

    unset -f set_PS1
}

set_PS1

I will have the same problem as before. Text that is longer than one line will appear on the start of the same line and overwrite. Cycling through commands results in either the deletion of a part of the prompt or in an visual bug that shows part of a previous command that is not accessible.

UPDATE 2: The problem definitely lies in the exit_code_prompt function. when i delete it from $Line_2 everything works as expected.

12
  • 1
    might have found the solution here ecaping the prompt with \[ and \] works for now
    – reneas
    Feb 19 at 13:52
  • 1
    Don't wrap the whole thing in that. Only wrap the color codes, not the prompt sign or the spaces
    – Daniel T
    Feb 19 at 17:02
  • 2
    Get out of the habit of using ALLCAPS variable names, leave those as reserved by the shell. One day you'll write PATH=something and then wonder why your script is broken. Feb 19 at 18:18
  • 1
    It sounds like the problem you asked about in your question has been solved and then an additional problem has also been solved. Please accept the answer you got to your original problem then ask a new question that's only about whatever your current problem is as Chameleon Questions atre strongly discouraged.
    – Ed Morton
    Feb 21 at 17:33
  • 2
    Does this answer your question? PS1 problem, messing up CLI
    – Daniel T
    Feb 22 at 1:38

1 Answer 1

4

Following @Daniel's advice, use

    local RESET="\\[$(tput sgr0 )\\]"

And similar with all the other colour codes.

From 6.9 Controlling the Prompt in the manual:

\[
    Begin a sequence of non-printing characters. This could be used to
    embed a terminal control sequence into the prompt.

\]
    End a sequence of non-printing characters.

Looping back to your question:

When I cycle through the last used commands it deletes the prompt sign

That's because without the \[ and \] to wrap the control sequences, bash cannot correctly calculate the length of your prompt.

6
  • even after implementing your suggestion (where I also don't really understand why there are two \\) the problem persists. When I cycle through the last used commands it not only deletes the prompt sign but almost all of the prompt...
    – reneas
    Feb 19 at 23:11
  • There are 2 \ because the string is within double quotes so the shell can expand $(tput sgr0 ) but that means the shell will also interpret/strip a \, so \[ would become [, and so if you want \[ left after shell interpretation then you need to add a \ for the shell to consume - \\[ will become \[ after shell interpretation.
    – Ed Morton
    Feb 20 at 21:41
  • @EdMorton okay thanks for the explanation! Strangely enough it's also working with only one \. Any idea why said problem is still not gone?
    – reneas
    Feb 21 at 9:38
  • I notice at local LINE_2="$BOLD\$(exit_code_prompt) "$RESET$BOLD' \$: '$RESET you have $RESET$BOLD and $RESET unquoted so maybe that's the problem, or maybe your use of all-upper-case variable names (don't do that - see correct-bash-and-shell-script-variable-capitalization!) is clobbering some environment variable, idk.
    – Ed Morton
    Feb 21 at 12:23
  • @EdMorton By now I've already corrected my Variables to look like $Bold and local Line_2="$Bold\$(exit_code_prompt)$Reset$Bold \$: $Reset" But still I have the weird formatting error. I updated the question to show my current code.
    – reneas
    Feb 21 at 15:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .