How to add the current git branch to the existing bash prompt - bash

I'm trying to modify my bash prompt to include the current git branch. This is complicated by the fact that there is already a set of rules that determines what the prompt might be - whether it includes color text, whether the user is on xterm etc. ... so what I really want is to be able to combine the string representing the git branch, colors and all, with the previously set prompt.
But I can't even get the most basic implementation to work. The following includes several of my attempts as I try to simplify the script to eliminate possible problems.
# Add current git branch, if any
parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
}
#PS1="\[\e[34m\]\$(parse_git_branch)\[\e[00m\]$PS1 "
#PS1 = "\$(parse_git_branch) $PS1 "
#PS1 = "\$(parse_git_branch) "
#PS1 = "$(parse_git_branch) "
PS1 = $(parse_git_branch)
Essentially they all produce the same message:
PS1: command not found
I'm sure I am missing something simple. Can anyone tell me what it is?

The error you get is because of the spaces surrounding =, as bash attempts evaluates PS1 as a command, and fails.
You can fix it by just removing the spaces. Here is a sample prompt that prints the current user and directory, along with the prompt:
export PS1='[\u#\h] \W :: $(parse_git_branch)> '
Note the single quotes - if you instead use double quotes, the parse_git_branch will be evaluated and will not update on every prompt. As an alternative to single quotes, you can escape the $ if you prefer.
If you want to update your existing prompt to also have the git branch, you can print the current value of the PS1 environment variable and modify it to suit your needs, finally adding the modified version in say your .bashrc file.

In case you're willing to use an existing solution, there's a Git prompt function already included in many Linux distros. How to use:
PS1=…'$(__git_ps1 " (%s)")'…
The mixed quotes are intentional, and the single quotes are necessary to make this run every time the prompt is displayed. Replace the ellipses with the rest of the prompt, such as '\$ '. If __git_ps1 isn't available out of the box see the full code for a cross-platform solution (works on at least Ubuntu and Arch Linux; should work on recent NixOS).
The " (%s)" part is the format string, that is, a space, open parenthesis (because I want to keep this info separate from the rest of the prompt), the prompt string, and close parenthesis. The %s is replaced by a repository state string, by default just the branch name. See the source code for options and their meanings.

Related

Adding to $PS1 variable on Git Bash for Windows using ~/.bash_profile causes an issue with __git_ps1

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
\[\033]0;$TITLEPREFIX:$PWD\007\]\n\[\033[32m\]\u#\h \[\033[35m\]$MSYSTEM \[\033[33m\]\w\[\033[36m\]`__git_ps1`\[\033[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\]\[\033]0;$TITLEPREFIX:$PWD\007\]\n\[\033[32m\]\u#\h \[\033[35m\]$MSYSTEM \[\033[33m\]\w\[\033[36m\]`__git_ps1`\[\033[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: $MSYSTEM\007\]\n\[\e[31m\]`nonzero_return`\[\e[32m\] \u#\h \[\e[35m\]\w\[\e[36m\]`__git_ps1`\e[0m\n$'
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=$?
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\]\[\033]0;$TITLEPREFIX:$PWD\007\]\n\[\033[32m\]\u#\h \[\033[35m\]$MSYSTEM \[\033[33m\]\w\[\033[36m\]\`__git_ps1\`\[\033[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='\[\033]0;$TITLEPREFIX:$PWD\007\]\n\[\e[31m\]`nonzero_return`\[\e[m\]\[\033[32m\]\u#\h \[\033[35m\]$MSYSTEM \[\033[33m\]\w\[\033[36m\]`__git_ps1`\[\033[0m\]\n$'
Details:
\[\033]0;$TITLEPREFIX:$PWD\007\] 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)
\[\033[32m\]\u#\h user#host in green
\[\033[35m\]$MSYSTEM the value of $MSYSTEM in purple
\[\033[33m\]\w current working directory in yellow
\[\033[36m\]`__git_ps1` is the Git status in Cyan
\[\033[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 \033: 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

How do I prevent an awk command from expanding? [duplicate]

I'm new to git and I'm trying to add the current git branch to my already existing prompt, which is defined as follows :
RESET="\[\017\]"
NORMAL="\[\033[0m\]"
RED="\[\033[31;1m\]"
YELLOW="\[\033[33;1m\]"
WHITE="\[\033[37;1m\]"
SMILEY="${WHITE}:)${NORMAL}"
FROWNY="${RED}:(${NORMAL}"
SELECT="if [ \$? = 0 ]; then echo \"${SMILEY}\"; else echo \"${FROWNY}\"; fi"
export PS1="${RESET}${YELLOW}\u#\h${NORMAL} \`${SELECT}\` ${YELLOW}\w $(__git_ps1) >${NORMAL} "
I tried it (by sourcing my .bashrc file again) and it seemed to work, but then I went on another branch and it did not update. How can I make sure the $(__git_ps1) is not cached?
You need a backslash on the $ so it isn't expanded immediately. (Compare to the `...`, which is a different way of writing $(...).)
export PS1="${RESET}${YELLOW}\u#\h${NORMAL} \`${SELECT}\` ${YELLOW}\w \$(__git_ps1) >${NORMAL} "
I would agree with #MikeSep about using single quotes, but it's actually a bit more optimal to let the colors and such be substituted immediately. Not necessary, just somewhat better. That said, it is easier to understand what's going on if you use the single quotes.
Your PS1 string is probably getting evaluated before it is getting saved, but you really want the __git_ps1 command to run each time you get a command prompt. I'd recommend using single quotes instead of double quotes for your export PS1='${RESET}...' line.

Making the bash prompt smaller

Currently my Windows Git Bash shell prompt looks like this:
UserName#ComputerName Path (Branch)
When I echo $PS1, I get:
\[\033]0;$MSYSTEM:\w\007\]\n\[\033[32m\]\u#\h \[\033[33m\]\w$(__git_ps1)\[\033[0m\]\n$
In my .bashrc file I tried to update this like so:
PS1="\[\033[32m\]\w$(__git_ps1)\[\033[0m\]\n$"
What happens is that I lose the UserName#ComputerName which is what was intended. However for some reason, the $(__git_ps1) also disappeared.
When I however do it like this: PS1=${PS1:46} it works as expected.
My plan was to add some additional changes (replace a fixed path with nothing) so the substring method is less then optimal.
What's going on?
UPDATE:
When I execute the PS1="\[\033[33m\]\w$(__git_ps1)\[\033[0m\]\n$" in the shell directly, it also works as expected.
The problem is that due to the double quotes, $(__git_ps1) expands when you define the prompt rather than when the prompt is later drawn.
It works in the shell directly because by defining it again, you cause $(__git_ps1) to be expanded again for the directory you're in. If you change branch, you'll see that it's stuck.
The solution is to use single quotes so that $(__git_ps1) becomes a literal value in the prompt, to be evaluated later:
PS1='\[\033[33m\]\w$(__git_ps1)\[\033[0m\]\n$ '

Weird behavior in mac os x terminal

I started using this code from Mark Dotto (http://markdotto.com/2013/01/13/improved-terminal-hotness/) to make my terminal is bit sexier.
I just copied the code without editing it, so in my .bash_profile I added:
export PS1='\[\e[0:35m⌘\e[m \e[0:36m\w/\e[m \e[0:33m`git branch 2> /dev/null | grep -e ^* | sed -E s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /`\e[m\]'
Everything's working, but there is a weird thing: when I type 3 characters or less then I hit backspace, it deletes everything, even the informations on the left (the path and git branch).
This could be okay, but the problem is that when I keep typing after that, the command I started typing is still here (but hidden).
I guess you didn't understand so I'll try to show some code:
# this is what my prompt looks like
~/my/path/ (branch) |
# I start typing a command
~/my/path/ (branch) ls|
# now I hit backspace once
|
# everything is removed
# but if I type something else then hit return
git st|
# it throws an error as the `l` from the previous command is still here
-bash: lgit: command not found
I have absolutely know idea how this bash_profile works, anybody can help? Thanks
there appears to be some incorrect syntax in your PS1 variable that's causing some unexpected errors. try this revision instead:
export PS1='\[\e[36m\]\w \[\e[33m\]`git branch 2> /dev/null | grep -e ^* | sed -E s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /` \[\e[0m\]'
(note: i left the git ... grep ... sed pipeline alone and only edited the parts related to the prompt itself.)
edit - take out the 0: parts and the colors actually work. (i.e. \[\e[36m\] instead of \[\e[0:36m\])
and here's a breakdown of what's going on there:
\[\e[36m\] - this block sets a foreground text color (light blue/tealish)
\w - current working directory
\[\e[33m\] - sets a different text color (yellow)
git ... grep ... sed - retrieves your current git branch
\[\e[0m\] - resets the text color to white so you're not typing commands in yellow
if you don't care about colors, prompts are a fairly trivial thing. the color blocks make it a bit more complex, and (as you've seen) error prone.
First of all: Make sure you are using the BASH shell.
I am on Mountain Lion on a MacBook and the PS1 command sort of, kind of works. My prompt looks like this:
⌘ ~/SVN-Precommit-Kitchen-Sink-Hook.git/ (master) _
I guess the question is what do you want your prompt to do. BASH prompts can embed a whole bunch of escape sequences that can do all sorts of neat things that in Kornshell would take a wee bit of hacking.
Type man bash on the command line, and find the PROMPTING heading. You should see something like this:
When executing interactively, bash displays the primary prompt PS1 when it is ready to read a com-
mand, and the secondary prompt PS2 when it needs more input to complete a command. Bash allows these
prompt strings to be customized by inserting a number of backslash-escaped special characters that
are decoded as follows:
\a an ASCII bell character (07)
\d the date in "Weekday Month Date" format (e.g., "Tue May 26")
\D{format}
the format is passed to strftime(3) and the result is inserted into the prompt string;
an empty format results in a locale-specific time representation. The braces are
required
\e an ASCII escape character (033)
\h the hostname up to the first `.'
\H the hostname
\j the number of jobs currently managed by the shell
\l the basename of the shell's terminal device name
\n newline
\r carriage return
\s the name of the shell, the basename of $0 (the portion following the final slash)
\t the current time in 24-hour HH:MM:SS format
\T the current time in 12-hour HH:MM:SS format
\# the current time in 12-hour am/pm format
\A the current time in 24-hour HH:MM format
\u the username of the current user
\v the version of bash (e.g., 2.00)
\V the release of bash, version + patch level (e.g., 2.00.0)
\w the current working directory, with $HOME abbreviated with a tilde
\W the basename of the current working directory, with $HOME abbreviated with a tilde
\! the history number of this command
\# the command number of this command
\$ if the effective UID is 0, a #, otherwise a $
\nnn the character corresponding to the octal number nnn
\\ a backslash
\[ begin a sequence of non-printing characters, which could be used to embed a terminal
control sequence into the prompt
\] end a sequence of non-printing characters
Let's take a simple prompt. I want to display my user name, the system I'm on, and my current directory. I can set PS1 like this:
PS1="\u#\h:\w$ "
This will give me:
david#davebook:~$ _
The \u is my user name (david), the \h is my machine name (davebook), and the \w displays the current directory I'm in relation to my $HOME directory.
You can also embed commands in the prompt too:
PS1="\$(date) \u#\h:\w$ "
Now the date and time will be embedded in my prompt:
Fri Feb 1 09:45:53 EST 2013 david#DaveBook:~
Sort of silly (I should have formatted the date. Besides, BASH already has built in sequences for the date), but you get the idea.
I recommend that you build your own damn prompt. If you're a git user, and you're using command lines comfortably, you can probably make a nice prompt yourself to look the way you want. You can use the \$(command) syntax to include interactive commands that get executed with each new PS command. You can use ANSI escape codes to color different parts of your prompt, or make them do fantastic stuff.
Build your prompt slowly and bit-by-bit. Create a shell script that will set PS1, and source it in like this:
$ echo "PS='\u#\h:\w\$ " > prompt.sh
$ chmod a+x prompt.sh
$ . prompt.sh
Then, add more and more features to your prompt until you get it to work the way you want.
Personally, I avoid over fancy prompts simply because they tend to fall apart sometime when you least expect it. For example, I use VI sequences for editing, and that prompt simply falls completely apart whenever I try to edit my command line.
Fancy prompts remind me of programs like Talking Moose which are really cool for the first few minutes, then start getting really, really annoying after that.

What is the difference between PS1 and PROMPT_COMMAND?

While taking a look at this awesome thread I noticed that some examples use
PS1="Blah Blah Blah"
and some use
PROMPT_COMMAND="Blah Blah Blah"
(and some use both) when setting the prompt in a Bash shell. What is the difference between the two? A Stack Overflow search and even a bit of broader Google searching aren't getting me results, so even a link to the right place to look for the answer would be appreciated.
PROMPT_COMMAND can contain ordinary Bash statements whereas the PS1 variable can also contain the special characters, such as '\h' for hostname, in the variable.
For example, here is my Bash prompt that uses both PROMPT_COMMAND and PS1. The Bash code in PROMPT_COMMAND works out what Git branch you might be in and displays that at the prompt, along with the exit status of the last run process, hostname and basename of the pwd.
The variable RET stores the return value of the last executed program. This is convenient to see if there was an error and the error code of the last program I ran in the terminal. Note the outer ' surrounding the entire PROMPT_COMMAND expression. It includes PS1 so that this variable is reevaluated each time the PROMPT_COMMAND variable is evaluated.
PROMPT_COMMAND='RET=$?;\
BRANCH="";\
ERRMSG="";\
if [[ $RET != 0 ]]; then\
ERRMSG=" $RET";\
fi;\
if git branch &>/dev/null; then\
BRANCH=$(git branch 2>/dev/null | grep \* | cut -d " " -f 2);\
fi;
PS1="$GREEN\u#\h $BLUE\W $CYAN$BRANCH$RED$ERRMSG \$ $LIGHT_GRAY";'
Example output looks like this in a non-Git directory:
sashan#dhcp-au-122 Documents $ false
sashan#dhcp-au-122 Documents 1 $
And in a Git directory you see the branch name:
sashan#dhcp-au-122 rework mybranch $
Update
After reading the comments and Bob's answer, I think that writing it as he describes is better. It's more maintainable than what I originally wrote above, where the PS1 variable is set inside the PROMPT_COMMAND, which itself is a super complicated string that is evaluated at runtime by Bash.
It works, but it's more complicated than it needs to be. To be fair, I wrote that PROMPT_COMMAND for myself about 10 years ago and it worked and didn't think too much about it.
For those curious as to how I've amended my things, I've basically put the code for the PROMPT_COMMAND in a separate file (as Bob described) and then echo the string that I intend to be PS1:
GREEN="\[\033[0;32m\]"
CYAN="\[\033[0;36m\]"
RED="\[\033[0;31m\]"
PURPLE="\[\033[0;35m\]"
BROWN="\[\033[0;33m\]"
LIGHT_GRAY="\[\033[0;37m\]"
LIGHT_BLUE="\[\033[1;34m\]"
LIGHT_GREEN="\[\033[1;32m\]"
LIGHT_CYAN="\[\033[1;36m\]"
LIGHT_RED="\[\033[1;31m\]"
LIGHT_PURPLE="\[\033[1;35m\]"
YELLOW="\[\033[1;33m\]"
WHITE="\[\033[1;37m\]"
RESTORE="\[\033[0m\]" #0m restores to the terminal's default colour
if [ -z $SCHROOT_CHROOT_NAME ]; then
SCHROOT_CHROOT_NAME=" "
fi
BRANCH=""
ERRMSG=""
RET=$1
if [[ $RET != 0 ]]; then
ERRMSG=" $RET"
fi
if which git &>/dev/null; then
BRANCH=$(git branch 2>/dev/null | grep \* | cut -d " " -f 2)
else
BRANCH="(git not installed)"
fi
echo "${GREEN}\u#\h${SCHROOT_CHROOT_NAME}${BLUE}\w \
${CYAN}${BRANCH}${RED}${ERRMSG} \$ $RESTORE"
And in my .bashrc file:
function prompt_command {
RET=$?
export PS1=$(~/.bash_prompt_command $RET)
}
PROMPT_DIRTRIM=3
export PROMPT_COMMAND=prompt_command
From the GNU Bash documentation page (Bash Reference Manual):
PROMPT_COMMAND
If set, the value is interpreted as a command to execute before
the printing of each primary prompt ($PS1).
I never used it, but I could have used this back when I only had sh.
The difference is that PS1 is the actual prompt string used, and PROMPT_COMMAND is a command that is executed just before the prompt. If you want the simplest, most flexible way of building a prompt, try this:
Put this in your .bashrc file:
function prompt_command {
export PS1=$(~/bin/bash_prompt)
}
export PROMPT_COMMAND=prompt_command
Then write a script (Bash, Perl, or Ruby: your choice), and place it in file ~/bin/bash_prompt.
The script can use any information it likes to construct a prompt. This is much simpler, IMO, because you don't have to learn the somewhat baroque substitution language that was developed just for the PS1 variable.
You might think that you could do the same by simply setting PROMPT_COMMAND directly to ~/bin/bash_prompt, and setting PS1 to the empty string.
This at first appears to work, but you soon discover that the readline code expects PS1 to be set to the actual prompt, and when you scroll backwards in history, things get messed up as a result.
This workaround causes PS1 to always reflect the latest prompt (since the function sets the actual PS1 variable used by the invoking instance of the shell), and this makes readline and command history work fine.
From man bash:
PROMPT_COMMAND
If set, the value is executed as a command prior to issuing each primary prompt.
PS1
The value of this parameter is expanded (see PROMPTING below) and used as the primary prompt string. The default value is ''\s-\v\$ ''.
If you simply want to set the prompt string, using PS1 alone is enough:
PS1='user \u on host \h$ '
If you want to do something else just before printing the prompt, use PROMPT_COMMAND. For example, if you want to sync cached writes to disk, you can write:
PROMPT_COMMAND='sync'
Yeah, so to try to really nail this down:
PROMPT_COMMAND is a handy Bash convenience variable/function, but there is, strictly speaking, nothing that cannot also be done using PS1 alone, correct?
I mean, if one wants to set another variable with scope outside the prompt: depending on the shell, that variable would probably need to be declared first outside $PS1 or (worst case) one might have to get fancy with something waiting on a FIFO prior to calling $PS1 (and armed again at the end of $PS1); the \u \h might cause some trouble, particularly if you're using some fancy regex; but otherwise: one can accomplish anything PROMPT_COMMAND can by using command substitution within $PS1 (and, maybe in corner cases, explicit subshells)?
Right?
The difference is that
if you output an incomplete line from PROMPT_COMMAND, it will screw your Bash prompt
PS1 substitutes \H and friends
PROMPT_COMMAND runs its contents, and PS1 uses its contents as the prompt.
PS1 does variable expansion and command substitution at each prompt. There isn't any need to use PROMPT_COMMAND to assign a value to PS1 or to run arbitrary code. You can easily do export PS1='$(uuidgen) $RANDOM' once in file .bash_profile. Just use single quotes.
I spent so much time on this I just wanted to share what worked for me. I looked at a lot of the SO posts about PROMPT_COMMAND and PS1 and tried many combinations of single quotes, double quotes, calling functions... I could not get the prompt to update each time without printing control characters or the literal expanded but not processed prompt string, or without just setting PS1 in PROMPT_COMMAND as we are advised not to do. My problem was setting variables (colors) that contained control characters; these had to be hard-coded after the variable name in PS1. PROMPT_COMMAND is set to a function that sets variables and they are used (escaped) in a double-quoted PS1 string. This is for a powerline-style prompt that changes colors with each command.
icon1=#unicode powerline char like
#these: https://github.com/ryanoasis/powerline-extra-symbols#glyphs
icon2=#same
#array of ANSI colors. 2 for rgb mode then the rgb values
#then 'm' without '\]' control character. these are from
#the solarized theme https://ethanschoonover.com/solarized/
declare -a colors=(
"2;220;50;47m"
"2;203;75;22m"
"2;181;137;0m"
"2;133;153;0m"
"2;42;161;152m"
"2;38;139;210m"
"2;108;113;196m"
"2;211;54;130m"
"2;0;43;54m"
"2;7;54;66m"
"2;88;110;117m"
"2;101;123;131m"
"2;131;148;150m"
"2;147;161;161m"
)
#outside of vars set in PROMPT_COMMAND it's ok to have control chars
LEN=${#colors[#]}
BG="\[\e[48;"#set bg color
FG="\[\e[38;"#set fg color
TRANSP="1m\]"#transparency
BASE2="2;238;232;213m\]"#fg (text) color
myfunc(){
RAND=$(($RANDOM % $LEN))
COLOR1=${colors[$RAND]}
COLOR2=${colors[($RAND + 1) % $LEN]}
COLOR3=${colors[($RAND + 2) % $LEN]}
}
PROMPT_COMMAND=myfunc
#note double quotes and escaped COLOR vars followed by hard-coded '\]' control chars
PS1="$BG$TRANSP$FG\$COLOR1\]$icon1$BG\$COLOR1\]$FG$TRANSP$BG\$COLOR1\]$FG$BASE2
[username hard-coded in unicode] $BG\$COLOR2\]$FG\$COLOR1\]$icon2$BG\$COLOR2\]$FG$BASE2
\w $BG\$COLOR3\]$FG\$COLOR2\]$icon2$BG\$COLOR3\]$FG$BASE2 [more unicode]
\[\e[0m\]$FG\$COLOR3\]$icon2\[\e[0m\] "
That ought to get you going!

Resources