summaryrefslogtreecommitdiff
path: root/git-prompt.sh
diff options
context:
space:
mode:
Diffstat (limited to 'git-prompt.sh')
-rw-r--r--git-prompt.sh458
1 files changed, 458 insertions, 0 deletions
diff --git a/git-prompt.sh b/git-prompt.sh
new file mode 100644
index 0000000..9bca4d0
--- /dev/null
+++ b/git-prompt.sh
@@ -0,0 +1,458 @@
+##################################################################### CONFIG
+ default_user=lvv # default user is not displayed
+ default_host="ahp" # default host is not displayed
+ default_domain="lvvnet" # default domain is not deplayed, remote host is alwais shown
+
+ # dir, rc, root color
+ if [ "`tput colors`" -ge 8 ]; then # if terminal supports colors
+ dir_color='CYAN'
+ rc_color='red'
+ root_id_color='magenta'
+ else # only B/W
+ dir_color='bw_bold'
+ rc_color='bw_bold'
+ fi
+
+ # where is user color?
+
+ # per host color
+ TOSHA_host_color=yellow
+ TASHA_host_color=cyan
+ AL_host_color=green
+ SH_host_color=blue
+ LVV_host_color=blue
+ AHP_host_color=white
+
+ # vcs state colors
+ init_vcs_color=WHITE # initial
+ clean_vcs_color=blue # nothing to commit (working directory clean)
+ modified_vcs_color=red # Changed but not updated:
+ added_vcs_color=green # Changes to be committed:
+ mixed_vcs_color=yellow #
+ untracked_vcs_color=BLUE # Untracked files:
+ op_vcs_color=MAGENTA
+ detached_vcs_color=RED
+
+
+##################################################################### post config
+
+ ######################################## terminfo colors
+ #
+ # black? 0 8
+ # red 1 9
+ # green 2 10
+ # yellow 3 11
+ # blue 4 12
+ # magenta 5 13
+ # cyan 6 14
+ # white 7 15
+ #
+ # terminfo setaf/setab - sets ansi foreground/background
+ # terminfo sgr0 - resets all atributes
+ # terminfo colors - number of colors
+
+ ### if term support colors, then use color prompt, else bold
+
+ black='\['`tput sgr0; tput setaf 0`'\]'
+ red='\['`tput sgr0; tput setaf 1`'\]'
+ green='\['`tput sgr0; tput setaf 2`'\]'
+ yellow='\['`tput sgr0; tput setaf 3`'\]'
+ blue='\['`tput sgr0; tput setaf 4`'\]'
+ magenta='\['`tput sgr0; tput setaf 5`'\]'
+ cyan='\['`tput sgr0; tput setaf 6`'\]'
+ white='\['`tput sgr0; tput setaf 7`'\]'
+
+ BLACK='\['`tput setaf 0; tput bold`'\]'
+ RED='\['`tput setaf 1; tput bold`'\]'
+ GREEN='\['`tput setaf 2; tput bold`'\]'
+ YELLOW='\['`tput setaf 3; tput bold`'\]'
+ BLUE='\['`tput setaf 4; tput bold`'\]'
+ MAGENTA='\['`tput setaf 5; tput bold`'\]'
+ CYAN='\['`tput setaf 6; tput bold`'\]' # why 14 dosn't work?
+ WHITE='\['`tput setaf 7; tput bold`'\]'
+
+ bw_bold='\['`tput bold`'\]'
+ bell=`tput bel`
+
+ colors_reset='\['`tput sgr0`'\]'
+
+ # Workaround for UTF readline(?) bug. Dissable bell when UTF
+ locale |grep -qi UTF && bell=''
+
+
+ # replace symbolic colors names to raw treminfo strings
+ init_vcs_color=${!init_vcs_color}
+ modified_vcs_color=${!modified_vcs_color}
+ untracked_vcs_color=${!untracked_vcs_color}
+ clean_vcs_color=${!clean_vcs_color}
+ added_vcs_color=${!added_vcs_color}
+ op_vcs_color=${!op_vcs_color}
+ mixed_vcs_color=${!mixed_vcs_color}
+ detached_vcs_color=${!detached_vcs_color}
+
+#####################################################################
+ # if label non empty, append 1 space
+ label=${1:+$1 }
+
+
+ # echo "*** /etc/prompt on A, TERM=$TERM"
+ unset PROMPT_COMMAND
+
+ ####### work aroud for MC bug
+ if [ -z "$TERM" -o "$TERM" = "dumb" -o -n "$MC_SID" ]; then
+ unset PROMPT_COMMAND
+ PS1='\w> '
+ return 0
+ fi
+
+ export who_where
+
+
+set_shell_title() {
+
+ xterm_title() { echo -n "]2;${@}" ; }
+
+ screen_title() {
+ # FIXME: run this only if screen is in xterm (how to test for this?)
+ xterm_title "sCRn $label$plain_who_where $@"
+
+ # FIXME $STY not enherited though "su -"
+ [ "$STY" ] && screen -S $STY -X title "$@"
+ }
+
+ case $TERM in
+
+ screen*)
+ screen_title "$@"
+ ;;
+
+ xterm* | rxvt* | gnome-terminal | konsole | eterm | wterm )
+ # is there a capability which we can to test
+ # for "set term title-bat" and its escapes?
+ #echo -n "]2;$label$plain_who_where $1"
+ xterm_title "$label$plain_who_where $@"
+ ;;
+
+ *)
+ ;;
+ esac
+ }
+
+ export -f set_shell_title
+
+###################################################### ID (user name)
+ id=`id -un`
+ id=${id#$default_user}
+
+########################################################### TTY
+ tty=`tty`
+ tty=`echo $tty | sed "s:/dev/pts/:p:; s:/dev/tty::" ` # RH tty devs
+ tty=`echo $tty | sed "s:/dev/vc/:vc:" ` # gentoo tty devs
+
+ if [[ "$TERM" = "screen" ]] ; then
+
+ # [ "$WINDOW" = "" ] && WINDOW="?"
+ #
+ # # if under screen then make tty name look like s1-p2
+ # # tty="${WINDOW:+s}$WINDOW${WINDOW:+-}$tty"
+ # tty="${WINDOW:+s}$WINDOW" # replace tty name with screen number
+ tty="$WINDOW" # replace tty name with screen number
+ fi
+
+ # we don't need tty name under X11
+ case $TERM in
+ xterm* | rxvt* | gnome-terminal | konsole | eterm | wterm ) unset tty ;;
+ *) ;;
+ esac
+
+
+ dir_color=${!dir_color}
+ rc_color=${!rc_color}
+ root_id_color=${!root_id_color}
+
+
+ ########################################################### HOST
+ ### we don't display home host/domain $SSH_* set by SSHD or keychain
+
+ # I give up. How to find out if session is local or remote? Working with "su -", ssh-agent, and so on ?
+ ## is sshd our perent?
+ # if { for ((pid=$$; $pid != 1 ; pid=`ps h -o pid --ppid $pid`)); do ps h -o command -p $pid; done | grep -q sshd }
+ #then
+ host=${HOSTNAME}
+ #host=`hostname --short`
+ host=`echo ${host%$default_host} | tr a-z A-Z`
+ #host=`echo ${host} | tr a-z A-Z`
+ host_color=${host}_host_color
+ host_color=${!host_color}
+ #else
+ # host=""
+ #fi
+
+ host_color=${!host_color}
+
+ # we already should have short host name, but just in case
+ host=${host%.localdoman}
+ host=${host%.$default_domain}
+
+
+#################################################################### WHO_WHERE
+ # who_ware. Is constant. Looks like
+ # [user@]host[-tty]
+
+ color_who_where="${id:+$id@}$host_color$host${tty:+ $tty}"
+ plain_who_where="${id:+$id@}$host"
+
+ # remove trailing "@" if any
+ color_who_where="${color_who_where%@}"
+ plain_who_where="${plain_who_where%@}"
+
+ # add traling " "
+ color_who_where="$color_who_where "
+ plain_who_where="$plain_who_where "
+
+ # if $who_where==" " then who_where=""
+ color_who_where="${color_who_where## }"
+ plain_who_where="${plain_who_where## }"
+
+
+ # if root then highlight who_where
+ if [ "$id" == "root" ] ; then
+ color_who_where="$root_id_color$color_who_where$colors_reset"
+ fi
+
+
+parse_svn_dir() {
+
+ if [[ ! -d .svn || $HOME == $PWD ]]; then # if home dir under svn - don't clutter home dir prompt
+ return 1
+ fi
+
+ vcs=svn
+
+ ### get rev
+ eval `
+ svn info |
+ sed -n "
+ s@^URL[^/]*//@repo_dir=@p
+ s/^Revision: /rev=/p
+ "
+ `
+ ### get status
+
+ unset status modified added clean init added mixed untracked op detached
+ eval `svn -q status 2>/dev/null |
+ sed -n "
+ s/^A /modified=modified; modified_files+=\" \"/p
+ s/^M /modified=modified; modified_files+=\" \"/p
+ "
+ `
+ # TODO untracked files; untracked state; branch detection if standart repo layout
+
+ [[ -z $modified ]] && [[ -z $untracked ]] && clean=clean
+ vcs_info=svn:r$rev
+ }
+
+
+parse_git_dir() {
+
+ git_dir=`git-rev-parse --git-dir 2> /dev/null`
+
+ [[ -n ${git_dir/./} ]] || return 1
+
+ vcs=git
+
+ ########################################################## GIT STATUS
+ unset status modified added clean init added mixed untracked op detached
+ eval `
+ git status 2>/dev/null |
+ sed -n "
+ s/^# On branch /branch=/p
+ s/^nothing to commit (working directory clean)/clean=clean/p
+ s/^# Initial commit/init=init/p
+ /^# Untracked files:/,/^[^#]/{
+ s/^# Untracked files:/untracked=untracked/p
+ s/^# /untracked_files+=\" \"/p
+ }
+ /^# Changed but not updated:/,/^# [A-Z]/ {
+ s/^# Changed but not updated:/modified=modified/p
+ s/^# modified: /modified_files+=\" \"/p
+ s/^# unmerged: /modified_files+=\" \"/p
+ }
+ /^# Changes to be committed:/,/^# [A-Z]/ {
+ s/^# Changes to be committed:/added=added/p
+ s/^# modified: /added_files+=\" \"/p
+ s/^# new file: */added_files+=\" \"/p
+ s/^# renamed:[^>]*> /added_files+=\" \"/p
+ s/^# copied:[^>]*> /added_files+=\" \"/p
+ }
+ "
+ `
+
+ if ! grep -q "^ref:" $git_dir/HEAD 2>/dev/null; then
+ detached=detached
+ fi
+
+ ### OP
+ unset op
+
+ if [[ -d "$git_dir/.dotest" ]] ; then
+
+ if [[ -f "$git_dir/.dotest/rebasing" ]] ; then
+ op="rebase"
+
+ elif [[ -f "$git_dir/.dotest/applying" ]] ; then
+ op="am"
+
+ else
+ op="am/rebase"
+
+ fi
+
+ elif [[ -f "$git_dir/.dotest-merge/interactive" ]] ; then
+ op="rebase -i"
+ # ??? branch="$(cat "$git_dir/.dotest-merge/head-name")"
+
+ elif [[ -d "$git_dir/.dotest-merge" ]] ; then
+ op="rebase -m"
+ # ??? branch="$(cat "$git_dir/.dotest-merge/head-name")"
+
+ elif [[ -f "$git_dir/MERGE_HEAD" ]] ; then
+ op="merge"
+ # ??? branch="$(git symbolic-ref HEAD 2>/dev/null)"
+
+ else
+ [[ -f "$git_dir/BISECT_LOG" ]] && op="bisect"
+ # ??? branch="$(git symbolic-ref HEAD 2>/dev/null)" || \
+ # branch="$(git describe --exact-match HEAD 2>/dev/null)" || \
+ # branch="$(cut -c1-7 "$git_dir/HEAD")..."
+ fi
+
+ #####################################################################
+
+ rawhex=`git-rev-parse HEAD 2>/dev/null`
+ rawhex=${rawhex/HEAD/}
+ rawhex=${rawhex:0:6}
+
+ ### branch
+
+ branch=${branch/master/M}
+
+ # another method of above:
+ # branch=$(git-symbolic-ref -q HEAD || { echo -n "detached:" ; git-name-rev --name-only HEAD 2>/dev/null; } )
+ # branch=${branch#refs/heads/}
+
+ ### compose vcs_info
+
+ if [[ $init ]]; then
+ vcs_info=M$white=init
+
+ else
+ if [[ "$detached" ]] ; then
+ branch="<detached:`git-name-rev --name-only HEAD 2>/dev/null`"
+
+
+ elif [[ "$op" ]]; then
+ branch="$op:$branch"
+ if [[ "$op" == "merge" ]] ; then
+ branch+="<~$(git-name-rev --name-only $(<$git_dir/MERGE_HEAD))"
+ fi
+ #branch="<$branch>"
+ fi
+ vcs_info="$branch$white=$rawhex"
+
+ fi
+ }
+
+parse_vcs_dir() {
+
+ unset file_list modified_files untracked_files added_files
+ unset vcs vcs_info
+ unset status modified untracked added init detached
+ unset file_list modified_files untracked_files added_files
+
+ parse_git_dir || parse_svn_dir || return
+
+
+ ### status: choose primary (for branch color)
+ unset status
+ status=${op:+op}
+ status=${status:-$detached}
+ status=${status:-$clean}
+ status=${status:-$modified}
+ status=${status:-$added}
+ status=${status:-$untracked}
+ status=${status:-$init}
+ # at least one should be set
+ : ${status?prompt internal error: git status}
+ eval vcs_color="\${${status}_vcs_color}"
+ # no def: vcs_color=${vcs_color:-$WHITE} # default
+
+
+ ### VIM ( not yet works for multiple files )
+
+ unset vim_glob vim_file vim_files
+ old_nullglob=`shopt -p nullglob`
+ shopt -s nullglob
+ vim_glob=`echo .*.swp`
+ eval $old_nullglob
+
+ if [[ $vim_glob ]]; then
+ vim_file=${vim_glob#.}
+ vim_file=${vim_file%.swp}
+ # if swap is newer, then unsaved vim session
+ [[ .${vim_file}.swp -nt $vim_file ]] && vim_files=$vim_file
+ fi
+
+
+ ### file list
+ unset file_list
+ file_list+=${added_files:+$added_vcs_color$added_files}
+ file_list+=${modified_files:+$modified_vcs_color$modified_files}
+ file_list+=${untracked_files:+$untracked_vcs_color$untracked_files}
+ file_list+=${vim_files:+ ${RED}VIM:$vim_files}
+ file_list=${file_list:+:$file_list}
+
+
+ tail_local="($vcs_info$vcs_color${file_list}$vcs_color)"
+
+ ### fringes (added depended on location)
+ head_local="${head_local+$vcs_color $head_local\n}"
+ tail_local="${tail_local+$vcs_color $tail_local}${dir_color}"
+ }
+
+
+###################################################################### PROMPT_COMMAND
+
+prompt_command_function() {
+ rc="$?"
+
+ if [[ "$rc" == "0" ]]; then
+ rc=""
+ else
+ #rc="$rc_color$rc$colors_reset$bell "
+ rc="$rc_color$rc$colors_reset "
+ fi
+
+ set_shell_title "$PWD/"
+
+ # truncate $PWD to $max
+ max=35
+ front=7
+ head=${PWD:0:$front}"..."
+
+ parse_vcs_dir
+
+ #########################
+ # PS1="$label$rc'$color_who_where$dir_color'${head:10*(${#PWD}<max)}${PWD:(${#PWD}>max)*(${#PWD}-max):max}> '$colors_reset'"
+
+ PS1="$head_local$colors_reset$label$rc$color_who_where$dir_color\w$tail_local$dir_color> $colors_reset"
+
+ unset head_local tail_local
+}
+
+
+ PROMPT_COMMAND=prompt_command_function
+
+ unset rc id tty bell
+
+# vim: set syntax=sh: