Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting a dynamic bash prompt PS1 right

Tags:

bash

ps1

I'm working on a dynamic bash prompt where I want reported in PS1 which version of a config file is enabled on the local filesystem. This is a contrived example of what I'm trying to do, simplified. The things that are going wrong: bad wrapping and/or escape brackets appearing. Can anyone spot what I'm doing wrong?

If the contrived config matches "v2", I want to see that version in PS1 as YELLOW. If it's "v1", in the prompt as GREEN. The setup:

$ grep FOOVER foo-*.conf
foo-v1.conf:# FOOVER xyz-v1
foo-v2.conf:# FOOVER zet-v2

I'd then symlink foo.conf foo-v1.conf. My bashrc:

 0 GREEN=$(tput setaf 034)
 1 YELLOW=$(tput setaf 3)
 2 BLUE=$(tput setaf 4)
 3 CYAN=$(tput setaf 6)
 4 BOLD=$(tput bold)
 5 RESET=$(tput sgr0)
 6 CONF=$HOME/foo.conf
 7
 8 function __get_foo_version () {
 9   FOOVER=$(grep FOOVER $CONF | awk '{print $3}')
10   if [[ "$FOOVER" =~ v2$ ]]; then
11     style_foover="${BOLD}${YELLOW}$FOOVER"
12     #style_foover="\[${BOLD}${YELLOW}\]$FOOVER"
13   elif [[ "$FOOVER" =~ v1$ ]]; then
14     style_foover="${BOLD}${GREEN}$FOOVER"
15     #style_foover="\[${BOLD}${GREEN}\]$FOOVER"
16   fi
17   echo $style_foover
18 }
19
20 style_host="\[${RESET}${BLUE}\]"
21 style_path="\[${RESET}${CYAN}\]"
22 style_reset="\[${RESET}\]"
23
24 PS1='user@'
25 PS1+="${style_host}host"
26 PS1+="${style_reset} "
27 PS1+="\$(__get_foo_version) "
28 PS1+="${style_reset}"
29 PS1+="${style_path}\W"
30 PS1+="${style_reset} $ "

When I run the above, I get this behavior, which looks good at first: http://imgur.com/HIR3SoA

But when I up-arrow to a long command, the bad wrapping happens: http://imgur.com/qLfdUor

When I disable lines 11, 14 and enable lines 12, 15, I get the brackets that are intended to handle non-printing chars showing up in PS1:

(not enough reputation points to post more than 2 links :( imgur.com slash nkXFDyJ)

user@host \[\]xyz-v1 ~ $

.. and I still get the bad wrapping in this case.

like image 305
groknaut Avatar asked Mar 28 '14 07:03

groknaut


People also ask

What does PS1 do in bash?

The PS1 variable contains the value of the default prompt. It is used to change the looks and environment of the shell command prompt. Different examples of using the PS1 variable have been shown in this tutorial.

How do I change bash prompt?

You can change the BASH prompt temporarily by using the export command. This command changes the prompt until the user logs out. You can reset the prompt by logging out, then logging back in.

How do I get to the bash prompt in Linux?

You need to set PS1, PS2, PS3 and PS4 variable. If set, the value is executed as a command prior to issuing each primary prompt. From the bash command: PS0 – The value of this parameter is expanded (see PROMPTING below) and displayed by interactive shells after reading a command and before the command is executed.

What is command PS1?

PS1 is one of the few variables used by the shell to generate the prompt. As explained in the bash manual, PS1 represents the primary prompt string (hence the “PS”) - which is what you see most of the time before typing a new command in your terminal.


1 Answers

Use \x01 (or \001) and \x02 (or \002) and then evaluate them with echo -e:

    function __get_foo_version () {
      FOOVER=$(grep FOOVER $CONF | awk '{print $3}')
      if [[ "$FOOVER" =~ v2$ ]]; then
        #style_foover="${BOLD}${YELLOW}$FOOVER"
>>>     style_foover="\x01${BOLD}${YELLOW}\x02$FOOVER"
      elif [[ "$FOOVER" =~ v1$ ]]; then
        #style_foover="${BOLD}${GREEN}$FOOVER"
>>>     style_foover="\x01${BOLD}${GREEN}\x02$FOOVER"
      fi
>>>   echo -e "$style_foover"
    }

A more complete answer as to why this fixes it is here: https://superuser.com/questions/301353/escape-non-printing-characters-in-a-function-for-a-bash-prompt

like image 130
Cobi Avatar answered Oct 02 '22 19:10

Cobi