root index legacy

Clean Bash Prompt

A clean custom bash prompt designed for maximum efficiency. Showcasing the key features of this prompt and explaining how in works in-depth. 2021-07-30

GitHub

This post is outdated

Since writing this post, I switched to a custom setup using Fish Shell instead of Bash. This post was preserved nonetheless.

Overview

This program is a simple script to change the Bash prompt on your terminal.

The Bash prompt is the part of the terminal after which a user can enter a command. Most Linux distributions configure the Bash prompt to look something like username@hostname:directory$, but you can configure the Bash prompt to contain whatever you like.

HowToGeek

Below is a a screenshot showcasing the key features of this prompt: the current username, the working directory and some extra info.

screenshot of the key features of the program

How it Works

On the Bash shell, one can change the appearance of the prompt presented to the user by exporting an environment variable called PS1. For example, to create a very simple prompt consisting of your username followed by a >, you can simply type the following command right in your terminal:

export PS1="\u> "

In this minimal example, \u represents the current username and > is simply some ascii text to append to the end of it. In my case, since my username is brick, I get the following prompt:

example of a bash prompt

After iterating on this idea for a few hours, I came up with this very Bash prompt. In my opinion, it is the best balance between cleanliness and efficiency. If anyone is feeling like reading gibberish, below is its source code:

export PS1='`status=$?; running=$({ pgrep -x $CLEAN_PROMPT_CHECK_PROC; } | wc -l); if [ $UID -eq 0 ](%20%24UID%20-eq%200%20.md); then printf "\r\[\033[1m\033[38;5;007m\]\`whoami\`"; else printf "\r\[\033[1m\033[38;5;008m\]\`whoami\`"; fi; printf "\[\033[00m\] "; if [ $status -gt 0 ](%20%24status%20-gt%200%20.md); then printf "\[\033[91m\]"; else printf "\[\033[94m\]"; fi; printf "\`pwd | rev | cut -d '/' -f 2 | rev\`/\`pwd | rev | cut -d '/' -f 1 | rev\`\[\033[00m\]"; git branch --show-current &> /dev/null; if [ $? -eq 0 ](%20%24%3F%20-eq%200%20.md); then status=$(git status 2> /dev/null); if [ $status =~ Changes\ not\ staged\ for\ commit: ](%20%24status%20%3D~%20Changes%5C%20not%5C%20staged%5C%20for%5C%20commit%3A%20.md) || [ $status =~ Untracked\ files: ](%20%24status%20%3D~%20Untracked%5C%20files%3A%20.md); then printf "\[\033[1m\033[38;5;166m\]"; elif [ $status =~ Changes\ to\ be\ committed: ](%20%24status%20%3D~%20Changes%5C%20to%5C%20be%5C%20committed%3A%20.md); then printf "\[\033[1m\033[38;5;040m\]"; else printf "\[\033[1m\033[94m\]"; fi; printf " ($(git branch --show-current))"; elif [ running -gt 0 ](%20running%20-gt%200%20.md); then printf " \[\033[1m\033[94m\][live]\[\033[00m\]"; fi; if [ running -eq 0 ](%20running%20-eq%200%20.md); then printf " \[\033[1m\033[91m\][down]\[\033[00m\]"; fi; printf "\[\033[00m\] "`' && export PS2=' ' && export LS_COLORS='ow=01;34;40'

However, for everyone else, below is a commented version of the PS1 environment variable exported in the command above. This is the script that creates the Bash prompt itself, including the text displayed and the colors used.

status=$?; #get exit code of last command
running=$({ pgrep -x $CLEAN_PROMPT_CHECK_PROC; } | wc -l); #check if process CLEAN_PROMPT_CHECK_PROC is running
if [ $UID -eq 0 ](%20%24UID%20-eq%200%20.md); #if root
    then printf "\r\[\033[1m\033[38;5;007m\]\`whoami\`"; #then print the current user in bold light gray
    else printf "\r\[\033[1m\033[38;5;008m\]\`whoami\`"; #otherwise, print the current user in bold dark gray
fi;
printf "\[\033[00m\] "; #reset color styles and print a space
if [ $status -gt 0 ](%20%24status%20-gt%200%20.md); #if the previous command returned a non-zero exit code (error)
    then printf "\[\033[91m\]"; #then print the current working directory in red
    else printf "\[\033[94m\]"; #otherwise, print the current working directory in blue
fi;
printf "\`pwd | rev | cut -d '/' -f 2 | rev\`/\`pwd | rev | cut -d '/' -f 1 | rev\`\[\033[00m\]"; #print the actual current working directory and reset color styles
git branch --show-current &> /dev/null; if [ $? -eq 0 ](%20%24%3F%20-eq%200%20.md); #if `git` is installed and the current directory is a git repository
    then status=$(git status 2> /dev/null); #then get the current branch and print it in bold and in the right color
    if [ $status =~ Changes\ not\ staged\ for\ commit: ](%20%24status%20%3D~%20Changes%5C%20not%5C%20staged%5C%20for%5C%20commit%3A%20.md) || [ $status =~ Untracked\ files: ](%20%24status%20%3D~%20Untracked%5C%20files%3A%20.md); then printf "\[\033[1m\033[38;5;166m\]"; elif [ $status =~ Changes\ to\ be\ committed: ](%20%24status%20%3D~%20Changes%5C%20to%5C%20be%5C%20committed%3A%20.md); then printf "\[\033[1m\033[38;5;040m\]"; else printf "\[\033[1m\033[94m\]"; fi;
    printf " ($(git branch --show-current))"; #print the actual branch
    elif [ running -gt 0 ](%20running%20-gt%200%20.md); #if the current directory is not a git repository and the CLEAN_PROMPT_CHECK_PROC process is running
        then printf " \[\033[1m\033[94m\][live]\[\033[00m\]"; #then print a bold blue `[live]`
    fi;
if [ running -eq 0 ](%20running%20-eq%200%20.md); #if the CLEAN_PROMPT_CHECK_PROC process is not running
    then printf " \[\033[1m\033[91m\][down]\[\033[00m\]"; #then print a bold red `[down]`
fi;
printf "\[\033[00m\] " #reset color styles

If you wish to try out this prompt for yourself, go on this project's github and follow the instructions in the README!

Final Words

As soon as I became aware that it was possible to customize my Bash prompt, I knew I had to do so. However, it was quite a challenge to make it work because of the deeply nested escape sequences I had to use. What's worse, forgetting a simple \ could turn my terminal into a very confusing colorful mess. Despite all that, I now have a shameless way to flex every time someone logs into my server!