Learning the Command Line – Bash Prompts (1)

NOTE: This article assumes you have been following the other articles in this series.
Another Note: I can’t take credit for this. I got it from a now defunct website called dotfiles.com. I don’t remember who the original author was and I’ve edited it to suit me. I won’t be explaining every little detail because some are more advanced.

If you’ve been keeping up with this series, you’ll know I’ve promised you a little magic. This is it and you might learn a little something too. It’s really simple but shows the power of Bash and using shell scripts. So let’s get started.

This .zip file contains three text files which we will be using. All code will be in the article also. So download and unzip or, to start, paste the following at the end of your .bashrc: (this is from the file bashrc-setup)

#advanced prompt settings
if [ -f ~/.bash_styles ];
then
. ~/.bash_styles dumb;
fi
#some aliases to set fancy prompts
if [ -f ~/.bash_styles ];
then
alias dumb='. ~/.bash_styles dumb'
alias ice='. ~/.bash_styles ice'
alias fire='. ~/.bash_styles fire'
alias nature='. ~/.bash_styles nature'
alias sunshine='. ~/.bash_styles sunshine'
alias dream='. ~/.bash_styles dream'
alias magic='. ~/.bash_styles magic'
fi

And save the file. What this does is source, or read the next file into memory and change the prompt. Now change the name of bash_styles-setup to .bash_styles. This file needs to be in your Home directory. Restart Terminal for the changes to take effect. Note: this looks best with the Homebrew theme in Terminal. With some editing it can probably be used with other themes.
So, the prompt looks a little plain right? Try this:

$ ice

Wow, a little different now. Now try:

$ fire

As you can see from the list above the aliases are dumb, ice, fire, nature, sunshine, dream and magic. This pic shows the prompts:

Terminal — bash — 94×23 2014-03-27 16-38-17 2014-03-27 16-38-20

 

Now we’re going to learn how to do this. Take a look at the file prompt_info. This is a list of the escape characters used to make the prompts.

######################################################################
#
# Prompt Info
#
# \a     an ASCII bell character (07)
# \d     the date in "Weekday Month Date" format (e.g., "Tue May 26")
# \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
# \u     the username of the current user
# \v     the version of bash (e.g., 2.00)
# \V     the release of bash, version + patchlevel (e.g., 2.00.0)
# \w     the current working directory
# \W     the basename of the current working directory
# \!     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
#
######################################################################

The \ is the escape, any single char after it is not printed to the screen, it represents something that is printed. For example \T prints the time in 12 hour format. If you wanted to have the date and time you would use: \d\T. If you wanted to use a separator between them, something like this: \d : \T. Let’s take a look at the code for the ‘dumb’ prompt.

#
# 'dumb' terminal
#
if [ "$#" -eq 0 ] || [ "$TERM" = "dumb" ] || [ "$1" = "dumb" ];
then
  echo;
  PS1="\u@\h:\w\\$ "
fi

The first line checks if you’re a regular user (not root), what kind of terminal, and the argument or alias used.Then it prints a blank line (echo;) and changes the prompt (the PS1 line). Looking at the PS1 line we see
\u (the user)
@
\h (the Hostname to the first .)
:
\w (the current working directory)
\ (a backslash, you wont see this)
\$ (the user prompt).
This ends up looking like this:

craig@zinger:~$

Using these escaped characters you can do amazing things with the shell prompt, so lets get started.
First let’s set up some colors. Use your favorite editor and create the file “.bash_styles” (or just follow along in the one provided). We’re going to set up some names for colors so we don’t have to use the escape number codes which can get confusing.

# .bash_prompt
#
# Command Prompt
#
######################################################################
# Setting up some colors
#
# ANSI Escape Color
#
DULL=0
BRIGHT=1
#
FG_BLACK=30
FG_RED=31
FG_GREEN=32
FG_YELLOW=33
FG_BLUE=34
FG_VIOLET=35
FG_CYAN=36
FG_WHITE=37

FG_NULL=00

#
BG_BLACK=40
BG_RED=41
BG_GREEN=42
BG_YELLOW=43
BG_BLUE=44
BG_VIOLET=45
BG_CYAN=46
BG_WHITE=47

BG_NULL=00

Here we’re setting foreground colors (FG_) and background colors (BG_). Now a little more setup so we can use single word color names (foreground only).

#
# ANSI Escape Commands
#
ESC="33"
NORMAL="\[$ESC[m\]"
RESET="\[$ESC[${DULL};${FG_WHITE};${BG_NULL}m\]"

#
# Shortcuts for Colored Text ( Bright and FG Only )
#
# DULL TEXT

BLACK="\[$ESC[${DULL};${FG_BLACK}m\]"
RED="\[$ESC[${DULL};${FG_RED}m\]"
GREEN="\[$ESC[${DULL};${FG_GREEN}m\]"
YELLOW="\[$ESC[${DULL};${FG_YELLOW}m\]"
BLUE="\[$ESC[${DULL};${FG_BLUE}m\]"
VIOLET="\[$ESC[${DULL};${FG_VIOLET}m\]"
CYAN="\[$ESC[${DULL};${FG_CYAN}m\]"
WHITE="\[$ESC[${DULL};${FG_WHITE}m\]"

# BRIGHT TEXT
BRIGHT_BLACK="\[$ESC[${BRIGHT};${FG_BLACK}m\]"
BRIGHT_RED="\[$ESC[${BRIGHT};${FG_RED}m\]"
BRIGHT_GREEN="\[$ESC[${BRIGHT};${FG_GREEN}m\]"
BRIGHT_YELLOW="\[$ESC[${BRIGHT};${FG_YELLOW}m\]"
BRIGHT_BLUE="\[$ESC[${BRIGHT};${FG_BLUE}m\]"
BRIGHT_VIOLET="\[$ESC[${BRIGHT};${FG_VIOLET}m\]"
BRIGHT_CYAN="\[$ESC[${BRIGHT};${FG_CYAN}m\]"
BRIGHT_WHITE="\[$ESC[${BRIGHT};${FG_WHITE}m\]"

Some error checking:

PROMPT_COMMAND='export ERR=$?'

#put here you prompt settings checking $1

And the actual functions the aliases call:

#
# 'dumb' terminal
#
if [ "$#" -eq 0 ] || [ "$TERM" = "dumb" ] || [ "$1" = "dumb" ];
then
  echo;
  PS1="\u@\h:\w\\$ "
fi

#
# 'ice' prompt
#
if [ "$1" = "ice" ];
then

PS1="\n${BRIGHT_CYAN}/-=[ ${BRIGHT_WHITE}\t${BRIGHT_CYAN} ]-[ ${BRIGHT_WHITE}\d${BRIGHT_CYAN} ]-[${BRIGHT_WHITE}\j${BRIGHT_CYAN}]-[${BRIGHT_WHITE}\#${BRIGHT_CYAN}]-[${BRIGHT_RED}$(echo \$ERR)${BRIGHT_CYAN}]=-
${BRIGHT_CYAN}\-=[ ${BRIGHT_WHITE}\u${BRIGHT_CYAN}${WHITE}@${BRIGHT_WHITE}\h${BRIGHT_CYAN}:${BRIGHT_WHITE}\w${BRIGHT_CYAN} ]${NORMAL}\$ ${RESET}"

fi

#
# 'fire' prompt
#
if [ "$1" = "fire" ];
then

PS1="\n${BRIGHT_RED}..::[\d \T]::..
${BRIGHT_RED}..::[ ${BRIGHT_YELLOW}\u${RED}@${BRIGHT_YELLOW}\h${BRIGHT_RED}:${BRIGHT_YELLOW}\w${BRIGHT_RED} ]${BRIGHT_YELLOW}>${NORMAL} ${RESET}"

fi

#
# 'nature' prompt
#
if [ "$1" = "nature" ];
then

PS1="\n${BRIGHT_GREEN}.--~/ ${YELLOW}\u${GREEN}@${YELLOW}\h${BRIGHT_GREEN}:${BRIGHT_CYAN}\w${BRIGHT_GREEN} \~—.${GREEN}\${NORMAL} ${RESET}"

fi

#
# 'sunshine' prompt
#
if [ "$1" = "sunshine" ];
then

PS1="\n${BRIGHT_YELLOW}<--( ${YELLOW}\u${BRIGHT_RED}@${YELLOW}\h${BRIGHT_YELLOW}:${BRIGHT_RED}\w${BRIGHT_YELLOW} )--${YELLOW}\${NORMAL} ${RESET}" fi # # 'dream' prompt # if [ "$1" = "dream" ]; then PS1="${BRIGHT_VIOLET} _________ |${VIOLET}\\ ${BRIGHT_CYAN}DrEaM ${VIOLET}/${BRIGHT_VIOLET}|  ${BRIGHT_WHITE}Last Error Status: ${BRIGHT_RED}$(echo \$ERR) ${BRIGHT_VIOLET}|${VIOLET} \\ ${BRIGHT_CYAN}bOx ${VIOLET}/ ${BRIGHT_VIOLET}|  ${BRIGHT_WHITE} User: ${WHITE}\u  ${BRIGHT_WHITE}Host: ${WHITE}\h ${BRIGHT_VIOLET}|${VIOLET}  \\ ${BRIGHT_CYAN}. ${VIOLET}/  ${BRIGHT_VIOLET}|  ${BRIGHT_WHITE}  Current Working Directory: ${WHITE} \w ${BRIGHT_VIOLET}|_________|  …-${BRIGHT_CYAN}\t ${BRIGHT_VIOLET}--${VIOLET}>${NORMAL} ${RESET}"

fi

#
# 'magic' prompt
#
if [ "$1" = "magic" ];
then

PS1="\n${BRIGHT_BLUE}._._  _. _ ${BRIGHT_WHITE}*${BRIGHT_BLUE} _ 
| | |(_|(_||(_ 
${BRIGHT_CYAN}`date +%k:%M`${BRIGHT_BLUE}    _| ${BRIGHT_VIOLET}Bash${BRIGHT_BLUE}-${BLUE}*${NORMAL} ${RESET}"    

fi

#
# Export Variables
#
export PS1 PROMPT_COMMAND

That last line actually changes the prompt.
Lets break down another one. Look at ‘fire’. It starts with a new line, changes the foreground color to red and prints ‘..::’, the date and time in brackets, and ‘::..’. Then it prints ‘..::’, the username, hostname and working directory in brackets, and in yellow, then ‘::..’ with a ‘>’ as the prompt. Pretty nifty.

By using escape codes you can do all sorts of things with the command prompt. I’m hoping this article will get you thinking and discovering the magic that is the shell and the command line.