HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashgitMinor

Coloured bash prompt including git status and previous exit code

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
previousbashstatusexitcodeincludinggitcolouredandprompt

Problem

I wanted to create a short, informational and colourful prompt.

My prompt includes:

  • Exit status of last command (if not 0)



  • Distinctive changes when root



  • rsync-style user@host:pathname for copy-paste goodness



  • Git branch, index, modified, untracked and upstream information



  • Pretty colours



Example:

Is there a way to achieve a similar result with less lines of code?

In ~/.bashrc:

`#
# Set the prompt #
#

# Select git info displayed, see /usr/lib/git-core/git-sh-prompt for more
export GIT_PS1_SHOWDIRTYSTATE=1 # '*'=unstaged, '+'=staged
export GIT_PS1_SHOWSTASHSTATE=1 # '$'=stashed
export GIT_PS1_SHOWUNTRACKEDFILES=1 # '%'=untracked
export GIT_PS1_SHOWUPSTREAM="verbose" # 'u='=no difference, 'u+1'=ahead by 1 commit
export GIT_PS1_STATESEPARATOR='' # No space between branch and index status
export GIT_PS1_DESCRIBE_STYLE="describe" # detached HEAD style:
# contains relative to newer annotated tag (v1.6.3.2~35)
# branch relative to newer tag or branch (master~4)
# describe relative to older annotated tag (v1.6.3.1-13-gdd42c2f)
# default exactly eatching tag

# Check if we support colours
__colour_enabled() {
local -i colors=$(tput colors 2>/dev/null)
[[ $? -eq 0 ]] && [[ $colors -gt 2 ]]
}
unset __colourise_prompt && __colour_enabled && __colourise_prompt=1

__set_bash_prompt()
{
local exit="$?" # Save the exit status of the last command

# PS1 is made from $PreGitPS1 + + $PostGitPS1
local PreGitPS1="${debian_chroot:+($debian_chroot)}"
local PostGitPS1=""

if [[ $__colourise_prompt ]]; then
export GIT_PS1_SHOWCOLORHINTS=1

# Wrap the colour codes between \[ and \], so that
# bash counts the correct number of characters for line wrapping:
local Red='\[\e[0;31m\]'; local BRed='\[\e[1;31m\]'
local Gre='\[\e[0;32m\]'; local BGre='\[\e[1;32m\]'
local Yel='\[\e[0;33m\]'; local BYel='\[\e[1;33m\]'
local Blu

Solution

Solid script, nicely done.

"less lines of code"

__colour_enabled is used only once,
when setting __colourise_prompt, which in turn is also used only once.
It seems an unnecessary indirection.
You could drop this line:

unset __colourise_prompt && __colour_enabled && __colourise_prompt=1


And change this condition:

if [[ $__colourise_prompt ]]; then


To this:

if __colour_enabled; then


Some color variables are defined but never used.
But I would keep them anyway,
in case you (or somebody else) want to adjust the colors later
(they are not exactly easy to remember).

To shorten the code, you could rewrite some of the if statements in cmd && ... || ... form, but I don't recommend that.
In its current form it's nicely readable and good that way.

Undefined variables

When you detect that colors are enabled, you set a bunch of variables, for example Red, BRed, Mag, None. If colors are not enabled, you don't clear these variables, but they may be used anyway later in the script.

Although it may seem unlikely that these variables are set outside this script, it can happen,
and that will be confusing and possibly annoying.
The clean solution is to make sure to set those variables to blank when colors are not enabled.

Condition without pattern matching

The == operator in [[ is useful for pattern matching.
In this example you don't need pattern matching,
so I suggest to replace it with =, which will do simple literal comparison.

if [[ ${EUID} == 0 ]]; then


Coding style

You mixed two styles of function declaration:

__colour_enabled() {
    # ...
}

__set_bash_prompt()
{
    # ...
}


It would be better to use consistent style (I prefer the first one).

Code Snippets

unset __colourise_prompt && __colour_enabled && __colourise_prompt=1
if [[ $__colourise_prompt ]]; then
if __colour_enabled; then
if [[ ${EUID} == 0 ]]; then
__colour_enabled() {
    # ...
}

__set_bash_prompt()
{
    # ...
}

Context

StackExchange Code Review Q#137799, answer score: 4

Revisions (0)

No revisions yet.