Peyo61
Peyo61

Reputation: 103

Bash prompt with background color extending to end of line

It's bash-prompt-fiddling-time for me (had to happen one day...).

I'm trying to get a 2-line prompt:

I'm almost there, but I can't crack the "background color to the end of line" part. Not quite.

Putting together bits of info from several sources, and most importantly from here and here, I get this result (terminal screenshot).

As you can see, something's wrong with the COLUMNS calculations:

This is my bashrc code:

PROMPT_COMMAND=__prompt_command
__prompt_command()
{
    local EXIT="$?" 

    local Red='\[\033[1;38;5;9m\]'
    local Green='\[\033[1;38;5;10m\]'
    local Gray='\[\033[0;38;5;248m\]'
    local BgBlue='\[\033[48;5;253;1;38;5;12m\]'
    local BgPurple='\[\033[48;5;253;1;38;5;93m\]'
    local None='\[\e[0m\]'

    PS1="${BgPurple}\u@\h:${BgBlue}\$PWD"

    printf -v TC_SPC "%${COLUMNS}s" ''

    COLUMNS=$(tput cols)
    PS1=`echo $PS1 | sed "s/$/$TC_SPC/; s/^\\(.\\{${COLUMNS}\\}\\) */\\1/"`

    PS1+="\n${Gray}\D{%F %T}"

    if [ $EXIT != 0 ]; then
        PS1+=" ${Red} O_o ${None}"      # Add red if exit code non 0
    else
        PS1+="${Green} ^_^ ${None}"
    fi
}

I tried more hacking but no success.

Oh, there another more sophisticated version of the sed bit, which I also tried:

    PS1=`echo $PS1 | sed "s/$/$TC_SPC/; s/^\\(\\(\\o33\\[[0-9;]*[a-zA-Z]\\)*\\)\\([^\o033]\\{${COLUMNS}\\}\\) */\\1\\3/"`

Different result (terminal screenshot) but still not OK.

At this point I'm taking any help !

Upvotes: 5

Views: 2080

Answers (2)

Peyo61
Peyo61

Reputation: 103

Here is the working solution, thanks to Eric's "erase to end of line" hint.

PROMPT_COMMAND=__prompt_command # Func to gen PS1 after CMDs
__prompt_command()
{
  local EXIT="$?"             # This needs to be first (retrieves last commmand exit code)

  local Red='\[\033[1;38;5;9m\]'
  local Green='\[\033[1;38;5;10m\]'
  local Gray='\[\033[0;38;5;248m\]'
  local BgBlue='\[\033[48;5;253;1;38;5;12m\]'
  local BgPurple='\[\033[48;5;253;1;38;5;93m\]'
  local None='\[\e[0m\]'

  PS1="${BgPurple}\u@\h:${BgBlue}\$PWD"
  PS1+="\033[K"             # erase to end of 1st line (background color stays)

  PS1+="\n${Gray}\D{%F %T}\a"

  if [ $EXIT != 0 ]; then
    PS1+="${Red} O_o ${None}"   # Add red if exit code non 0
  else
    PS1+="${Green} ^_^ ${None}"
  fi
  PS1+="\033[K"             # erase to end of 2nd line (no more background color)
}

And here is the result (terminal screenshot). One more happy prompt owner...

Upvotes: 4

Eric
Eric

Reputation: 1511

Instead of:

printf -v TC_SPC "%${COLUMNS}s" ''

COLUMNS=$(tput cols)
PS1=`echo $PS1 | sed "s/$/$TC_SPC/; s/^\\(.\\{${COLUMNS}\\}\\) */\\1/"`

Use:

PS1+=$'\033[K' #erase to end of line

Upvotes: 3

Related Questions