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
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.
Below is a a screenshot showcasing the key features of this prompt: the current username, the working directory and some extra info.
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:
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!