Fancy bash prompt with colors

Read full article: Fancy bash prompt

I got bored of the normal bash promt a long time ago, which lead me to configure my .bashrc to betther highlight terminal inputs. Still, I used to see some terminal on the net with a very fancy looking bash promt that I found really appealing. After some googling I decided to give it a go and try to generate my own. All it takes is a fancy triangle character to create the colored overlaps, shown in the above figure, and some tweaking. All in all, the end result speaks for itself.

Check out my implementation after the break, and leave a comment if you like it or want to make some suggestions to further improve it!

Update: a new and easy to install version can be found here.






Source

You can find the latest iteration of this script in my GIT repository, among many other useful bash scripts. Before you use this script, remember to to install the package fonts-powerline.

This script updates your "PS1" environment variable to display colors. additionally, it also shortens the name of your current part to maximum 25 characters, which is quite useful when working in deeply nested folders.

To install it, simply copy the following text into your user's .bashrc file, or if you prefer to keep things tidy, paste it into a new .fancy-bash-promt.sh, and simply run this command:  

echo "source ~/.fancy-bash-promt.sh" >> ~/.bashrc



#!/bin/sh

################################################################################
##  FUNCTIONS                                                                 ##
################################################################################

##
## ARRANGE $PWD AND STORE IT IN $NEW_PWD
## * The home directory (HOME) is replaced with a ~
## * The last pwdmaxlen characters of the PWD are displayed
## * Leading partial directory names are striped off
##  /home/me/stuff -> ~/stuff (if USER=me)
##  /usr/share/big_dir_name -> ../share/big_dir_name (if pwdmaxlen=20)
##
## Original source: WOLFMAN'S color bash promt
## https://wiki.chakralinux.org/index.php?title=Color_Bash_Prompt#Wolfman.27s
##
bash_prompt_command() {
 # How many characters of the $PWD should be kept
 local pwdmaxlen=25

 # Indicate that there has been dir truncation
 local trunc_symbol=".."

 # Store local dir
 local dir=${PWD##*/}

 # Which length to use
 pwdmaxlen=$(( ( pwdmaxlen < ${#dir} ) ? ${#dir} : pwdmaxlen ))

 NEW_PWD=${PWD/#$HOME/\~}
 
 local pwdoffset=$(( ${#NEW_PWD} - pwdmaxlen ))

 # Generate name
 if [ ${pwdoffset} -gt "0" ]
 then
  NEW_PWD=${NEW_PWD:$pwdoffset:$pwdmaxlen}
  NEW_PWD=${trunc_symbol}/${NEW_PWD#*/}
 fi
}




##
## GENERATE A FORMAT SEQUENCE
##
format_font()
{
 ## FIRST ARGUMENT TO RETURN FORMAT STRING
 local output=$1


 case $# in
 2)
  eval $output="'\[\033[0;${2}m\]'"
  ;;
 3)
  eval $output="'\[\033[0;${2};${3}m\]'"
  ;;
 4)
  eval $output="'\[\033[0;${2};${3};${4}m\]'"
  ;;
 *)
  eval $output="'\[\033[0m\]'"
  ;;
 esac
}



##
## COLORIZE BASH PROMT
##
bash_prompt() {

 ############################################################################
 ## COLOR CODES                                                            ##
 ## These can be used in the configuration below                           ##
 ############################################################################
 
 ## FONT EFFECT
 local      NONE='0'
 local      BOLD='1'
 local       DIM='2'
 local UNDERLINE='4'
 local     BLINK='5'
 local    INVERT='7'
 local    HIDDEN='8'
 
 
 ## COLORS
 local   DEFAULT='9'
 local     BLACK='0'
 local       RED='1'
 local     GREEN='2'
 local    YELLOW='3'
 local      BLUE='4'
 local   MAGENTA='5'
 local      CYAN='6'
 local    L_GRAY='7'
 local    D_GRAY='60'
 local     L_RED='61'
 local   L_GREEN='62'
 local  L_YELLOW='63'
 local    L_BLUE='64'
 local L_MAGENTA='65'
 local    L_CYAN='66'
 local     WHITE='67'
 
 
 ## TYPE
 local     RESET='0'
 local    EFFECT='0'
 local     COLOR='30'
 local        BG='40'
 
 
 ## 256 COLOR CODES
 local NO_FORMAT="\[\033[0m\]"
 local ORANGE_BOLD="\[\033[1;38;5;208m\]"
 local TOXIC_GREEN_BOLD="\[\033[1;38;5;118m\]"
 local RED_BOLD="\[\033[1;38;5;1m\]"
 local CYAN_BOLD="\[\033[1;38;5;87m\]"
 local BLACK_BOLD="\[\033[1;38;5;0m\]"
 local WHITE_BOLD="\[\033[1;38;5;15m\]"
 local GRAY_BOLD="\[\033[1;90m\]"
 local BLUE_BOLD="\[\033[1;38;5;74m\]"
 
 
 
 
 
 ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  
   ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##
 ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ## 

 
 
 ##                          CONFIGURE HERE                                ##

 
 
 ############################################################################
 ## CONFIGURATION                                                          ##
 ## Choose your color combination here                                     ##
 ############################################################################
 local FONT_COLOR_1=$WHITE
 local BACKGROUND_1=$BLUE
 local TEXTEFFECT_1=$BOLD
 
 local FONT_COLOR_2=$WHITE
 local BACKGROUND_2=$L_BLUE
 local TEXTEFFECT_2=$BOLD
 
 local FONT_COLOR_3=$D_GRAY
 local BACKGROUND_3=$WHITE
 local TEXTEFFECT_3=$BOLD
 
 local PROMT_FORMAT=$BLUE_BOLD

 
 ############################################################################
 ## EXAMPLE CONFIGURATIONS                                                 ##
 ## I use them for different hosts. Test them out ;)                       ##
 ############################################################################
 
 ## CONFIGURATION: BLUE-WHITE
 if [ "$HOSTNAME" = dell ]; then
  FONT_COLOR_1=$WHITE; BACKGROUND_1=$BLUE; TEXTEFFECT_1=$BOLD
  FONT_COLOR_2=$WHITE; BACKGROUND_2=$L_BLUE; TEXTEFFECT_2=$BOLD 
  FONT_COLOR_3=$D_GRAY; BACKGROUND_3=$WHITE; TEXTEFFECT_3=$BOLD 
  PROMT_FORMAT=$CYAN_BOLD
 fi
 
 ## CONFIGURATION: BLACK-RED
 if [ "$HOSTNAME" = giraff6 ]; then
  FONT_COLOR_1=$WHITE; BACKGROUND_1=$BLACK; TEXTEFFECT_1=$BOLD
  FONT_COLOR_2=$WHITE; BACKGROUND_2=$D_GRAY; TEXTEFFECT_2=$BOLD
  FONT_COLOR_3=$WHITE; BACKGROUND_3=$RED; TEXTEFFECT_3=$BOLD
  PROMT_FORMAT=$RED_BOLD
 fi
 
 ## CONFIGURATION: RED-BLACK
 #FONT_COLOR_1=$WHITE; BACKGROUND_1=$RED; TEXTEFFECT_1=$BOLD
 #FONT_COLOR_2=$WHITE; BACKGROUND_2=$D_GRAY; TEXTEFFECT_2=$BOLD
 #FONT_COLOR_3=$WHITE; BACKGROUND_3=$BLACK; TEXTEFFECT_3=$BOLD
 #PROMT_FORMAT=$RED_BOLD

 ## CONFIGURATION: CYAN-BLUE
 if [ "$HOSTNAME" = sharkoon ]; then
  FONT_COLOR_1=$BLACK; BACKGROUND_1=$L_CYAN; TEXTEFFECT_1=$BOLD
  FONT_COLOR_2=$WHITE; BACKGROUND_2=$L_BLUE; TEXTEFFECT_2=$BOLD
  FONT_COLOR_3=$WHITE; BACKGROUND_3=$BLUE; TEXTEFFECT_3=$BOLD
  PROMT_FORMAT=$CYAN_BOLD
 fi
 
 ## CONFIGURATION: GRAY-SCALE
 if [ "$HOSTNAME" = giraff ]; then
  FONT_COLOR_1=$WHITE; BACKGROUND_1=$BLACK; TEXTEFFECT_1=$BOLD
  FONT_COLOR_2=$WHITE; BACKGROUND_2=$D_GRAY; TEXTEFFECT_2=$BOLD
  FONT_COLOR_3=$WHITE; BACKGROUND_3=$L_GRAY; TEXTEFFECT_3=$BOLD
  PROMT_FORMAT=$BLACK_BOLD
 fi
 
 ## CONFIGURATION: GRAY-CYAN
 if [ "$HOSTNAME" = light ]; then
  FONT_COLOR_1=$WHITE; BACKGROUND_1=$BLACK; TEXTEFFECT_1=$BOLD
  FONT_COLOR_2=$WHITE; BACKGROUND_2=$D_GRAY; TEXTEFFECT_2=$BOLD
  FONT_COLOR_3=$BLACK; BACKGROUND_3=$L_CYAN; TEXTEFFECT_3=$BOLD
  PROMT_FORMAT=$CYAN_BOLD
 fi
 
 
 ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  
   ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##
 ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  

 
 
 
 ############################################################################
 ## TEXT FORMATING                                                         ##
 ## Generate the text formating according to configuration                 ##
 ############################################################################
 
 ## CONVERT CODES: add offset
 FC1=$(($FONT_COLOR_1+$COLOR))
 BG1=$(($BACKGROUND_1+$BG))
 FE1=$(($TEXTEFFECT_1+$EFFECT))
 
 FC2=$(($FONT_COLOR_2+$COLOR))
 BG2=$(($BACKGROUND_2+$BG))
 FE2=$(($TEXTEFFECT_2+$EFFECT))
 
 FC3=$(($FONT_COLOR_3+$COLOR))
 BG3=$(($BACKGROUND_3+$BG))
 FE3=$(($TEXTEFFECT_3+$EFFECT))
 
 FC4=$(($FONT_COLOR_4+$COLOR))
 BG4=$(($BACKGROUND_4+$BG))
 FE4=$(($TEXTEFFECT_4+$EFFECT))
 

 ## CALL FORMATING HELPER FUNCTION: effect + font color + BG color
 local TEXT_FORMAT_1
 local TEXT_FORMAT_2
 local TEXT_FORMAT_3
 local TEXT_FORMAT_4 
 format_font TEXT_FORMAT_1 $FE1 $FC1 $BG1
 format_font TEXT_FORMAT_2 $FE2 $FC2 $BG2
 format_font TEXT_FORMAT_3 $FC3 $FE3 $BG3
 format_font TEXT_FORMAT_4 $FC4 $FE4 $BG4
 
 
 # GENERATE PROMT SECTIONS
 local PROMT_USER=$"$TEXT_FORMAT_1 \u "
 local PROMT_HOST=$"$TEXT_FORMAT_2 \h "
 local PROMT_PWD=$"$TEXT_FORMAT_3 \${NEW_PWD} "
 local PROMT_INPUT=$"$PROMT_FORMAT "


 ############################################################################
 ## SEPARATOR FORMATING                                                    ##
 ## Generate the separators between sections                               ##
 ## Uses background colors of the sections                                 ##
 ############################################################################
 
 ## CONVERT CODES
 TSFC1=$(($BACKGROUND_1+$COLOR))
 TSBG1=$(($BACKGROUND_2+$BG))
 
 TSFC2=$(($BACKGROUND_2+$COLOR))
 TSBG2=$(($BACKGROUND_3+$BG))
 
 TSFC3=$(($BACKGROUND_3+$COLOR))
 TSBG3=$(($DEFAULT+$BG))
 

 ## CALL FORMATING HELPER FUNCTION: effect + font color + BG color
 local SEPARATOR_FORMAT_1
 local SEPARATOR_FORMAT_2
 local SEPARATOR_FORMAT_3
 format_font SEPARATOR_FORMAT_1 $TSFC1 $TSBG1
 format_font SEPARATOR_FORMAT_2 $TSFC2 $TSBG2
 format_font SEPARATOR_FORMAT_3 $TSFC3 $TSBG3
 

 # GENERATE SEPARATORS WITH FANCY TRIANGLE
 local TRIANGLE=$'\uE0B0' 
 local SEPARATOR_1=$SEPARATOR_FORMAT_1$TRIANGLE
 local SEPARATOR_2=$SEPARATOR_FORMAT_2$TRIANGLE
 local SEPARATOR_3=$SEPARATOR_FORMAT_3$TRIANGLE



 ############################################################################
 ## WINDOW TITLE                                                           ##
 ## Prevent messed up terminal-window titles                               ##
 ############################################################################
 case $TERM in
 xterm*|rxvt*)
  local TITLEBAR='\[\033]0;\u:${NEW_PWD}\007\]'
  ;;
 *)
  local TITLEBAR=""
  ;;
 esac



 ############################################################################
 ## BASH PROMT                                                             ##
 ## Generate promt and remove format from the rest                         ##
 ############################################################################
 PS1="$TITLEBAR\n${PROMT_USER}${SEPARATOR_1}${PROMT_HOST}${SEPARATOR_2}${PROMT_PWD}${SEPARATOR_3}${PROMT_INPUT}"

 

 ## For terminal line coloring, leaving the rest standard
 none="$(tput sgr0)"
 trap 'echo -ne "${none}"' DEBUG
}




################################################################################
##  MAIN                                                                      ##
################################################################################

## Bash provides an environment variable called PROMPT_COMMAND. 
## The contents of this variable are executed as a regular Bash command 
## just before Bash displays a prompt. 
## We want it to call our own command to truncate PWD and store it in NEW_PWD
PROMPT_COMMAND=bash_prompt_command

## Call bash_promnt only once, then unset it (not needed any more)
## It will set $PS1 with colors and relative to $NEW_PWD, 
## which gets updated by $PROMT_COMMAND on behalf of the terminal
bash_prompt
unset bash_prompt




# EOF
 
Functional description

bash_prompt_command()
This function takes your current working directory and stores a shortenedversion in the variable "NEW_PWD".
format_font()
A small helper function to generate color formating codes from simple number codes (defined below as local variables for convenience). bash_promtp()
This function colorizes the bash promt. The exact color scheme can be configured here. The structure of the function is as follows:
  1. Color keywords
    1. Definition of available colors for 16 bits.
    2. Definition of some colors for 256 bits (add your own).
  2. Configuration >> EDIT YOUR PROMT HERE<<.
  3. Generation of color codes.
  4. Formating of the bash promt.
Main script body It calls the adequate helper functions to colorize your promt and sets a hook to regenerate your working directory "NEW_PWD" when you change it.

12 comments :

  1. Anonymous15/8/18 11:50

    Awesome, thank you! 3 things, how to remove the empty lines (like on top of terminal)? Also I would like type commands in normal mode (not bold) and white color, but only when I type. Thanks again, very good work!

    ReplyDelete
    Replies
    1. Hey! Sorry for the late answer. For whatever reason your comment got lost in Blogger's comment moderation system. Sorry about that. I hope your questions are still relevant though.

      1. You can remove the extra new line (if I'm not mistaken) by using this line (almost at the end of the script) instead. Notice that it has a missing "\n" almost at the very front. That "\n" was responsible for the extra new line
      PS1="$TITLEBAR${PROMT_USER}${SEPARATOR_1}${PROMT_HOST}${SEPARATOR_2}${PROMT_PWD}${SEPARATOR_3}${PROMT_INPUT}"

      2. You can set your "command text style" to whatever you want. For example, PROMT_FORMAT=$RED_BOLD sets it to red and bold text, whereas PROMT_FORMAT=$WHITE sets it to white without bold. I think this also answers your third question.

      I hope this helps. If you problem persist though, tell me and I'll look at it more carefully at home ;)

      Delete
    2. Thank you. I really like this and how customizable it is. This really helps a lot.

      Delete
  2. Replies
    1. Thanks for liking my stuff. You might also be interested in this new script, its very useful if you usually work with a terminal: https://yalneb.blogspot.com/2019/04/bash-terminal-greeter.html

      Delete
  3. Marvelous, can you make it show git status

    ReplyDelete
    Replies
    1. Indeed. Info about your current git folder is actually already implemented in the latest version. Just head over to the GitHub version and follow the installation instructions: https://github.com/andresgongora/synth-shell

      Delete
    2. The latest version (https://github.com/andresgongora/synth-shell) now also tells if you have to push/pull of if your current branch is dirty.

      Delete
  4. There is a bug in line 29: pwdmaxlen=$(( ( pwdmaxlen < ${#dir} ) ? ${#dir} : pwdmaxlen ))
    The way it is, it expands pwdmaxlen to the size of the current directory name, and so it doesn't shorten NEW_PWD. Rewriting as pwdmaxlen=$(( ( pwdmaxlen > ${#dir} ) ? ${#dir} : pwdmaxlen )) solves the problem.

    ReplyDelete
    Replies
    1. Thanks a lot for your feedback! :) All fixes have been added to the latest version of the script at https://github.com/andresgongora/synth-shell

      Delete
  5. Anonymous3/10/24 15:27

    @Andres Gongora Thanks for this amazing script!
    How can I make this work on Docker containers?
    It works beautifully on my PC, my servers, VMs and even on LXC containers, but on Docker it is all broken.

    ReplyDelete
    Replies
    1. Anonymous3/10/24 15:29

      Have a look at the latest release of the script here: https://github.com/andresgongora/synth-shell-prompt

      Delete