Skip to content

Instantly share code, notes, and snippets.

@grifferz
Created February 12, 2019 21:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grifferz/d01e03fdfe9140ed8d21d2718ab646e1 to your computer and use it in GitHub Desktop.
Save grifferz/d01e03fdfe9140ed8d21d2718ab646e1 to your computer and use it in GitHub Desktop.
Would generally recommend powerline of bashline or oh-my-zsh or something but this makes a fancy bash prompt from scratch
#!/bin/bash
# Started off being just the git/svn stuff from authors below but then got
# hacked on by me to add other silly things.
#
# Needs:
# - A 256-colour terminal
# - A terminal that supports colour emoji (else you'll need to substitute boring monochrome unicode glyphs and maybe colour them with terminal escapes)
# - Powerline font ("fonts-powerline" on Debian/Ubuntu) for the separator chevrons
# - Add this to your ~/.bashrc like:
#
# . /path/to/git_svn_bash_prompt.sh
#
# Andy Smith <andy@strugglers.net>
# DESCRIPTION:
#
# Set the bash prompt according to:
# * the branch/status of the current git repository
# * the branch of the current subversion repository
# * the return value of the previous command
#
# USAGE:
#
# 1. Save this file as ~/.git_svn_bash_prompt
# 2. Add the following line to the end of your ~/.profile or ~/.bash_profile:
# . ~/.git_svn_bash_prompt
#
# AUTHOR:
#
# Scott Woods <scott@westarete.com>
# West Arete Computing
#
# Based on work by halbtuerke and lakiolen.
#
# http://gist.github.com/31967
# Emoji for bad exit status.
sym_exit_fail="🔥"
sym_branch=""
sym_section=""
sym_sep=""
sym_computer="💻"
# The various escape codes that we can use to color our prompt.
RED="\[\033[0;31m\]"
YELLOW="\[\033[0;33m\]"
GREEN="\[\033[0;32m\]"
BLUE="\[\033[0;34m\]"
LIGHT_BLUE="\[\033[0;36m\]"
LIGHT_RED="\[\033[1;31m\]"
LIGHT_GREEN="\[\033[1;32m\]"
WHITE="\[\033[1;37m\]"
LIGHT_GRAY="\[\033[0;37m\]"
COLOR_NONE="\[\e[0m\]"
COLOR_BLACK_ON_GREEN="\[\e[0;38;5;16;48;5;72m\]"
COLOR_GREEN_ON_YELLOW="\[\e[0;38;5;72;48;5;194m\]"
COLOR_BLACK_ON_YELLOW="\[\e[0;38;5;16;48;5;194m\]"
COLOR_YELLOW_ON_GRAY="\[\e[0;38;5;194;48;5;247m\]"
COLOR_YELLOW_ON_DEFAULT="\[\e[0;38;5;194;49m\]"
COLOR_BLACK_ON_GRAY="\[\e[0;38;5;16;48;5;247m\]"
COLOR_BLACK_ON_GRAY="\[\e[0;38;5;16;48;5;247m\]"
COLOR_BLACK_ON_LBLUE="\[\e[0;38;5;16;48;5;75m\]"
COLOR_GRAY_ON_DEFAULT="\[\e[0;38;5;247;49m\]"
COLOR_LBLUE_ON_DEFAULT="\[\e[0;38;5;75;49m\]"
# Detect whether we're running under tmux.
function is_in_tmux {
test -n "$TMUX" && hash tmux 2>/dev/null
}
# Detect whether we're running under GNU Screen.
function is_in_screen {
test -n "$STY" && hash screen 2>/dev/null
}
# Set PROMPT_MUX based on tmux window index and name.
function set_mux_prompt {
local winidx=$(tmux display-message -p '#I')
local winname=$(tmux display-message -p '#W')
PROMPT_MUX="${COLOR_BLACK_ON_LBLUE}${sym_section}${sym_computer} ${winidx} ${sym_sep} ${winname} ${COLOR_LBLUE_ON_DEFAULT}${sym_section}"
}
# Set PROMPT_MUX based on GNU Screen window index and title.
function set_mux_prompt_screen {
local winidx="$WINDOW"
# This is absolutely awful. Screen imposes a delay unless you set it to
# zero, and then you have to set it back again.
local wintitle=$(screen -X msgwait 0; screen -QX title; screen -X msgwait 3)
PROMPT_MUX="${COLOR_BLACK_ON_LBLUE}${sym_section}${sym_computer} ${winidx} ${sym_sep} ${wintitle} ${COLOR_LBLUE_ON_DEFAULT}${sym_section}"
}
# Detect whether the current directory is a git repository.
function is_git_repository {
git branch > /dev/null 2>&1
}
# Detect whether the current directory is a subversion repository.
function is_svn_repository {
test -d .svn
}
# Determine the branch/state information for this git repository.
function set_git_branch {
# Capture the output of the "git status" command.
git_status="$(git status 2> /dev/null)"
# Set color based on clean/staged/dirty.
if [[ ${git_status} =~ "working directory clean" ]]; then
state="${GREEN}"
elif [[ ${git_status} =~ "Changes to be committed" ]]; then
state="${YELLOW}"
else
state="${RED}"
fi
# Set arrow icon based on status against remote.
remote_pattern="# Your branch is (.*) of"
if [[ ${git_status} =~ ${remote_pattern} ]]; then
if [[ ${BASH_REMATCH[1]} == "ahead" ]]; then
remote="↑"
else
remote="↓"
fi
else
remote=""
fi
diverge_pattern="# Your branch and (.*) have diverged"
if [[ ${git_status} =~ ${diverge_pattern} ]]; then
remote="↕"
fi
# Get the name of the branch.
branch_pattern="^# On branch ([^${IFS}]*)"
if [[ ${git_status} =~ ${branch_pattern} ]]; then
branch=${BASH_REMATCH[1]}
fi
# Set the final branch string.
BRANCH="${state}(${branch})${remote}${COLOR_NONE} "
}
# Determine the branch information for this subversion repository. No support
# for svn status, since that needs to hit the remote repository.
function set_svn_branch {
svn_info="$(svn info | egrep '^URL: ' 2> /dev/null)"
# Get the name of the branch.
branch_pattern="^URL: .*/(branches|tags)/([^/]+)"
trunk_pattern="^URL: .*/trunk(/.*)?$"
if [[ ${svn_info} =~ $branch_pattern ]]; then
branch=${BASH_REMATCH[2]}
elif [[ ${svn_info} =~ $trunk_pattern ]]; then
branch='trunk'
fi
# Set the final branch string.
BRANCH="(${GREEN}${sym_branch}${COLOR_NONE}${branch}) "
}
# Return the prompt symbol to use, colorized based on the return value of the
# previous command.
function set_prompt_symbol () {
if (( $1 == 0 )); then
PROMPT_SYMBOL="\$"
else
PROMPT_SYMBOL="${sym_exit_fail}${RED}[${COLOR_NONE}$1${RED}]${COLOR_NONE}\$"
fi
}
# Set the full bash prompt.
function set_bash_prompt () {
# Set the PROMPT_SYMBOL variable. We do this first so we don't lose the
# return value of the last command.
set_prompt_symbol $?
# Set the PROMPT_MUX variable. First the default state when not inside tmux
# or screen.
PROMPT_MUX="${COLOR_BLACK_ON_LBLUE}${sym_section}${sym_computer}${COLOR_LBLUE_ON_DEFAULT}${sym_section}"
# Then check if we're inside tmux and then GNU Screen. This is fairly nice
# for tmux since it's just checking some environment variables. Could be
# improved for screen.
if is_in_tmux ; then
set_mux_prompt
elif is_in_screen; then
# Check that screen supports -Q. Really old versions don't!
if [ -z "$_have_screen_q" ]; then
if screen -Q info >/dev/null 2>&1; then
_have_screen_q=1
else
# Just so this is not called again.
_have_screen_q=0
fi
fi
if (( "$_have_screen_q" == 1)); then
set_mux_prompt_screen
fi
fi
# Set the BRANCH variable.
if is_git_repository ; then
set_git_branch
elif is_svn_repository ; then
set_svn_branch
else
BRANCH=''
fi
# Save history
history -a
# Update xterm title
echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"
# Maybe should look up the user's real home directory rather than just
# assuming it's in /home/?
MUNGED_PATH=${PWD/#\/home\/$USER/\~}
# Truncate path to 40 characters if it's longer.
if [[ ${#MUNGED_PATH} -gt 39 ]]; then
MUNGED_PATH="…${MUNGED_PATH:(-39)}"
else
MUNGED_PATH="${MUNGED_PATH/#\//}"
fi
PROMPT_USER="${COLOR_BLACK_ON_GREEN}${sym_sep}\u${COLOR_GREEN_ON_YELLOW}${sym_section}"
PROMPT_HOST="${COLOR_BLACK_ON_YELLOW}@\h ${COLOR_YELLOW_ON_DEFAULT}${sym_section}"
MUNGED_PATH="${MUNGED_PATH//\// ${COLOR_BLACK_ON_GRAY}${sym_sep}${COLOR_BLACK_ON_GRAY} }"
PROMPT_PATH="${COLOR_BLACK_ON_GRAY}${sym_section}${COLOR_BLACK_ON_GRAY} ${MUNGED_PATH} ${COLOR_GRAY_ON_DEFAULT}${sym_section}"
PS1="${PROMPT_USER}${PROMPT_HOST}${PROMPT_MUX}${PROMPT_PATH}${COLOR_NONE} ${BRANCH}\n${PROMPT_SYMBOL} "
}
# Tell bash to execute this function just before displaying its prompt.
PROMPT_COMMAND=set_bash_prompt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment