blob: ed1613062ac4cd1a98a524df0abc72f036f9326b (
plain) (
tree)
|
|
# Frontend to controlling prompt
prompt() {
# What's done next depends on the first argument to the function
case $1 in
# Turn complex, colored prompt on
on)
# Set up pre-prompt command and prompt format
PROMPT_COMMAND='declare -i ret=$? ; history -a'
PS1='[\u@\h:\w]$(prompt vcs)$(prompt job)$(prompt ret)\$'
# If Bash 4.0 is available, trim very long paths in prompt
if ((BASH_VERSINFO[0] >= 4)) ; then
PROMPT_DIRTRIM=4
fi
# Count available colors, reset, and format (decided shortly)
local -i colors=$( {
tput Co || tput colors
} 2>/dev/null )
local reset=$( {
tput me || tput sgr0
} 2>/dev/null )
local format
# Check if we have non-bold bright green available
if ((colors == 256)) ; then
format=$( {
tput AF 10 || tput setaf 10 \
|| tput AF 10 0 0 || tput setaf 10 0 0
} 2>/dev/null )
# If we have only eight colors, use bold green to make it bright
elif ((colors == 8)) ; then
format=$( {
tput AF 2 || tput setaf 2
tput md || tput bold
} 2>/dev/null )
# For non-color terminals (!), just use bold
else
format=$( {
tput md || tput bold
} 2>/dev/null )
fi
# String it all together
PS1='\['"$format"'\]'"$PS1"'\['"$reset"'\] '
;;
# Revert to simple inexpensive prompt
off)
unset -v PROMPT_COMMAND PROMPT_DIRTRIM ret
PS1='\$ '
;;
git)
# Bail if we have no git(1)
if ! hash git 2>/dev/null ; then
return 1
fi
# Attempt to determine git branch, bail if we can't
local branch
branch=$( {
git symbolic-ref --quiet HEAD \
|| git rev-parse --short HEAD
} 2>/dev/null )
if [[ ! $branch ]] ; then
return 1
fi
branch=${branch##*/}
# Safely read status with -z --porcelain
local line
local -i ready modified untracked
while IFS= read -d $'\0' -r line ; do
if [[ $line == [MADRC]* ]] ; then
ready=1
fi
if [[ $line == ?[MADRC]* ]] ; then
modified=1
fi
if [[ $line == '??'* ]] ; then
untracked=1
fi
done < <(git status -z --porcelain 2>/dev/null)
# Build state array from status output flags
local -a state
if [[ $ready ]] ; then
state=("${state[@]}" '+')
fi
if [[ $modified ]] ; then
state=("${state[@]}" '!')
fi
if [[ $untracked ]] ; then
state=("${state[@]}" '?')
fi
# Add another indicator if we have stashed changes
if git rev-parse --verify refs/stash >/dev/null 2>&1 ; then
state=("${state[@]}" '^')
fi
# Print the status in brackets with a git: prefix
local IFS=
printf '(git:%s%s)' "${branch:-unknown}" "${state[*]}"
;;
# Mercurial prompt function
hg)
# Bail if we have no hg(1)
if ! hash hg 2>/dev/null ; then
return 1
fi
# Exit if not inside a Mercurial tree
local branch
if ! branch=$(hg branch 2>/dev/null) ; then
return 1
fi
# Start collecting working copy state flags
local -a state
# Safely read status with -0
local line
local -i modified untracked
while IFS= read -d $'\0' -r line ; do
if [[ $line == '?'* ]] ; then
untracked=1
else
modified=1
fi
done < <(hg status -0 2>/dev/null)
# Build state array from status output flags
local -a state
if [[ $modified ]] ; then
state=("${state[@]}" '!')
fi
if [[ $untracked ]] ; then
state=("${state[@]}" '?')
fi
# Print the status in brackets with an hg: prefix
local IFS=
printf '(hg:%s%s)' "${branch:-unknown}" "${state[*]}"
;;
# Subversion prompt function
svn)
# Bail if we have no svn(1)
if ! hash svn 2>/dev/null ; then
return 1
fi
# Determine the repository URL and root directory
local key value url root
while IFS=: read -r key value ; do
case $key in
'URL')
url=${value## }
;;
'Repository Root')
root=${value## }
;;
esac
done < <(svn info 2>/dev/null)
# Exit if we couldn't get either
if ! [[ $url && $root ]] ; then
return 1
fi
# Remove the root from the URL to get what's hopefully the branch
# name, removing leading slashes and the 'branches' prefix, and any
# trailing content after a slash
local branch
branch=${url/$root}
branch=${branch#/}
branch=${branch#branches/}
branch=${branch%%/*}
# Parse the output of svn status to determine working copy state
local symbol
local -i modified untracked
while read -r symbol _ ; do
if [[ $symbol == *'?'* ]] ; then
untracked=1
else
modified=1
fi
done < <(svn status 2>/dev/null)
# Add appropriate state flags
local -a state
if [[ $modified ]] ; then
state=("${state[@]}" '!')
fi
if [[ $untracked ]] ; then
state=("${state[@]}" '?')
fi
# Print the state in brackets with an svn: prefix
local IFS=
printf '(svn:%s%s)' "${branch:-unknown}" "${state[*]}"
;;
# VCS wrapper prompt function; print the first relevant prompt, if any
vcs)
prompt git || prompt svn || prompt hg
;;
# Show the return status of the last command in angle brackets
ret)
if ((ret > 0)) ; then
printf '<%d>' "$ret"
fi
;;
# Show the count of background jobs in curly brackets
job)
local -i jobc=0
while read -r _ ; do
((jobc++))
done < <(jobs -p)
if ((jobc > 0)) ; then
printf '{%d}' "$jobc"
fi
;;
esac
}
# Complete words
complete -W 'on off git hg svn vcs ret job' prompt
# Start with full-fledged prompt
prompt on
|