summaryrefslogtreecommitdiff
path: root/git-prompt.sh
diff options
context:
space:
mode:
Diffstat (limited to 'git-prompt.sh')
-rwxr-xr-xgit-prompt.sh221
1 files changed, 145 insertions, 76 deletions
diff --git a/git-prompt.sh b/git-prompt.sh
index dc2a2d1..3fac2f0 100755
--- a/git-prompt.sh
+++ b/git-prompt.sh
@@ -1,4 +1,3 @@
-
# don't set prompt if this is not interactive shell
[[ $- != *i* ]] && return
@@ -6,8 +5,9 @@
##### read config file if any.
- unset dir_color rc_color jobs_color prompt_color user_id_color root_id_color init_vcs_color clean_vcs_color
- unset modified_vcs_color added_vcs_color addmoded_vcs_color untracked_vcs_color op_vcs_color detached_vcs_color
+ unset dir_color rc_color jobs_color prompt_color user_id_color root_id_color init_vcs_color clean_vcs_color
+ unset modified_vcs_color added_vcs_color addmoded_vcs_color untracked_vcs_color op_vcs_color detached_vcs_color hex_vcs_color
+ unset rawhex_len
conf=git-prompt.conf; [[ -r $conf ]] && . $conf
conf=/etc/git-prompt.conf; [[ -r $conf ]] && . $conf
@@ -15,12 +15,14 @@
conf=~/.config/git-prompt.conf; [[ -r $conf ]] && . $conf
unset conf
+
##### set defaults if not set
git_module=${git_module:-on}
svn_module=${svn_module:-off}
hg_module=${hg_module:-on}
vim_module=${vim_module:-on}
+ virtualenv_module=${virtualenv_module:-on}
error_bell=${error_bell:-off}
cwd_cmd=${cwd_cmd:-\\w}
@@ -32,6 +34,7 @@
rc_color=${rc_color:-red}
jobs_color=${jobs_color:-cyan}
prompt_color=${prompt_color:-CYAN}
+ virtualenv_color=${virtualenv_color:-green}
user_id_color=${user_id_color:-blue}
root_id_color=${root_id_color:-magenta}
else # only B/W
@@ -44,7 +47,7 @@
prompt_char="${prompt_char:-'>'}"
root_prompt_char="${root_prompt_char:-'>'}"
- #### vcs state colors
+ #### vcs colors
init_vcs_color=${init_vcs_color:-WHITE} # initial
clean_vcs_color=${clean_vcs_color:-blue} # nothing to commit (working directory clean)
modified_vcs_color=${modified_vcs_color:-red} # Changed but not updated:
@@ -54,8 +57,14 @@
op_vcs_color=${op_vcs_color:-MAGENTA}
detached_vcs_color=${detached_vcs_color:-RED}
+ hex_vcs_color=${hex_vcs_color:-BLACK} # gray
+
+
max_file_list_length=${max_file_list_length:-100}
+ short_hostname=${short_hostname:-off}
upcase_hostname=${upcase_hostname:-on}
+ count_only=${count_only:-off}
+ rawhex_len=${rawhex_len:-5}
aj_max=${aj_max:-20}
@@ -110,9 +119,11 @@
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 doesn't work?
+ CYAN='\['"$(tput setaf 6; tput bold)"'\]'
WHITE='\['"$(tput setaf 7; tput bold)"'\]'
+ dim='\['"$(tput sgr0; tput setaf p1)"'\]' # half-bright
+
bw_bold='\['"$(tput bold)"'\]'
on=''
@@ -129,6 +140,7 @@
op_vcs_color=${!op_vcs_color}
addmoded_vcs_color=${!addmoded_vcs_color}
detached_vcs_color=${!detached_vcs_color}
+ hex_vcs_color=${!hex_vcs_color}
unset PROMPT_COMMAND
@@ -142,7 +154,7 @@
#################################################################### MARKERS
screen_marker="sCRn"
- if [[ $(locale|grep LC_CTYPE) =~ "UTF" && $TERM != "linux" ]]; then
+ if [[ "$LC_CTYPE $LC_ALL" =~ "UTF" && $TERM != "linux" ]]; then
elipses_marker="…"
else
elipses_marker="..."
@@ -192,7 +204,7 @@ cwd_truncate() {
# trunc middle if over limit
if [[ ${#path_middle} -gt $(( $cwd_middle_max + ${#elipses_marker} + 5 )) ]]; then
-
+
# truncate
middle_tail="${path_middle:${#path_middle}-${cwd_middle_max}}"
@@ -213,31 +225,37 @@ cwd_truncate() {
set_shell_label() {
- xterm_label() { echo -n "]2;${@}" ; } # FIXME: replace hardcodes with terminfo codes
+ xterm_label() {
+ local args="$*"
+ echo -n "]2;${args:0:200}" ; # FIXME: replace hardcodes with terminfo codes
+ }
screen_label() {
# FIXME: run this only if screen is in xterm (how to test for this?)
- xterm_label "$screen_marker $plain_who_where $@"
+ xterm_label "$screen_marker $plain_who_where $@"
# FIXME $STY not inherited though "su -"
[ "$STY" ] && screen -S $STY -X title "$*"
}
+ if [[ -n "$STY" ]]; then
+ screen_label "$*"
+ else
+ case $TERM in
- case $TERM in
+ screen*)
+ screen_label "$*"
+ ;;
- screen*)
- screen_label "$*"
- ;;
+ xterm* | rxvt* | gnome-* | konsole | eterm | wterm )
+ # is there a capability which we can to test
+ # for "set term title-bar" and its escapes?
+ xterm_label "$plain_who_where $@"
+ ;;
- xterm* | rxvt* | gnome-terminal | konsole | eterm | wterm )
- # is there a capability which we can to test
- # for "set term title-bar" and its escapes?
- xterm_label "$plain_who_where $@"
- ;;
-
- *)
- ;;
- esac
+ *)
+ ;;
+ esac
+ fi
}
export -f set_shell_label
@@ -263,7 +281,7 @@ set_shell_label() {
# we don't need tty name under X11
case $TERM in
- xterm* | rxvt* | gnome-terminal | konsole | eterm | wterm ) unset tty ;;
+ xterm* | rxvt* | gnome-terminal | konsole | eterm* | wterm | cygwin) unset tty ;;
*);;
esac
@@ -271,6 +289,7 @@ set_shell_label() {
rc_color=${!rc_color}
prompt_color=${!prompt_color}
jobs_color=${!jobs_color}
+ virtualenv_color=${!virtualenv_color}
user_id_color=${!user_id_color}
root_id_color=${!root_id_color}
@@ -284,9 +303,15 @@ set_shell_label() {
#then
host=${HOSTNAME}
- #host="$(hostname --short)"
+ if [[ $short_hostname = "on" ]]; then
+ if [[ "$(uname)" =~ "CYGWIN" ]]; then
+ host="$(hostname)"
+ else
+ host="$(hostname -s)"
+ fi
+ fi
host=${host#$default_host}
- uphost="$(echo ${host} | tr a-z A-Z)"
+ uphost="$(echo ${host} | tr a-z-. A-Z_)"
if [[ $upcase_hostname = "on" ]]; then
host=${uphost}
fi
@@ -294,7 +319,7 @@ set_shell_label() {
host_color=${uphost}_host_color
host_color=${!host_color}
if [[ -z $host_color && -x /usr/bin/cksum ]] ; then
- cksum_color_no="$(echo $uphost | cksum | awk '{print $1%7}')"
+ cksum_color_no="$(echo $uphost | cksum | awk '{print $1%6}')"
color_index=(green yellow blue magenta cyan white) # FIXME: bw, color-256
host_color=${color_index[cksum_color_no]}
fi
@@ -304,7 +329,6 @@ set_shell_label() {
# we might already have short host name
host=${host%.$default_domain}
-
#################################################################### WHO_WHERE
# [[user@]host[-tty]]
@@ -361,8 +385,7 @@ parse_svn_status() {
parse_hg_status() {
# ☿
-
- [[ -d ./.hg/ ]] || return 1
+ hg_root=`hg root 2>/dev/null` || return 1
vcs=hg
@@ -380,11 +403,17 @@ parse_hg_status() {
branch="$(hg branch 2> /dev/null)"
+ [[ -f $hg_root/.hg/bookmarks.current ]] && bookmark=`cat "$hg_root/.hg/bookmarks.current"`
+
[[ -z $modified ]] && [[ -z $untracked ]] && [[ -z $added ]] && clean=clean
vcs_info=${branch/default/D}
+ if [[ "$bookmark" ]] ; then
+ vcs_info+=/$bookmark
+ fi
}
+
parse_git_status() {
# TODO add status: LOCKED (.git/index.lock)
@@ -396,46 +425,52 @@ parse_git_status() {
[[ -n ${git_dir/./} ]] || return 1
vcs=git
- #parse_git_complete
########################################################## GIT STATUS
- file_regex='\([^/]*\/\?\).*'
added_files=()
modified_files=()
untracked_files=()
+ [[ $rawhex_len -gt 0 ]] && freshness="$dim="
+
unset branch status modified added clean init added mixed untracked op detached
- # quoting hell
+ # info not in porcelain status
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
-
- /^# Changes to be committed:/,/^# [A-Z]/ {
- s/^# Changes to be committed:/added=added;/p
-
- s/^# modified: '"$file_regex"'/ [[ \" ${added_files[*]} \" =~ \" \1 \" ]] || added_files[${#added_files[@]}]=\"\1\"/p
- s/^# new file: '"$file_regex"'/ [[ \" ${added_files[*]} \" =~ \" \1 \" ]] || added_files[${#added_files[@]}]=\"\1\"/p
- s/^# renamed:[^>]*> '"$file_regex"'/ [[ \" ${added_files[*]} \" =~ \" \1 \" ]] || added_files[${#added_files[@]}]=\"\1\"/p
- s/^# copied:[^>]*> '"$file_regex"'/ [[ \" ${added_files[*]} \" =~ \" \1 \" ]] || added_files[${#added_files[@]}]=\"\1\"/p
- }
-
- /^# Changed but not updated:/,/^# [A-Z]/ {
- s/^# Changed but not updated:/modified=modified;/p
- s/^# modified: '"$file_regex"'/ [[ \" ${modified_files[*]} \" =~ \" \1 \" ]] || modified_files[${#modified_files[@]}]=\"\1\"/p
- s/^# unmerged: '"$file_regex"'/ [[ \" ${modified_files[*]} \" =~ \" \1 \" ]] || modified_files[${#modified_files[@]}]=\"\1\"/p
- }
-
- /^# Untracked files:/,/^[^#]/{
- s/^# Untracked files:/untracked=untracked;/p
- s/^# '"$file_regex"'/ [[ \" ${untracked_files[*]} ${modified_files[*]} ${added_files[*]} \" =~ \" \1 \" ]] || untracked_files[${#untracked_files[@]}]=\"\1\"/p
- }
+ s/^nothing to commi.*/clean=clean/p
+ s/^# Initial commi.*/init=init/p
+ s/^# Your branch is ahead of \(.\).\+\1 by [[:digit:]]\+ commit.*/freshness=${WHITE}↑/p
+ s/^# Your branch is behind \(.\).\+\1 by [[:digit:]]\+ commit.*/freshness=${YELLOW}↓/p
+ s/^# Your branch and \(.\).\+\1 have diverged.*/freshness=${YELLOW}↕/p
'
)"
- if ! grep -q "^ref:" $git_dir/HEAD 2>/dev/null; then
+ # porcelain file list
+ # TODO: sed-less -- http://tldp.org/LDP/abs/html/arrays.html -- Example 27-5
+
+ # git bug: (was reported to git@vger.kernel.org )
+ # echo 1 > "with space"
+ # git status --porcelain
+ # ?? with space <------------ NO QOUTES
+ # git add with\ space
+ # git status --porcelain
+ # A "with space" <------------- WITH QOUTES
+
+ eval " $(
+ git status --porcelain 2>/dev/null |
+ sed -n '
+ s,^[MARC]. \([^\"][^/]*/\?\).*, added=added; [[ \" ${added_files[@]} \" =~ \" \1 \" ]] || added_files[${#added_files[@]}]=\"\1\",p
+ s,^[MARC]. \"\([^/]\+/\?\).*\"$, added=added; [[ \" ${added_files[@]} \" =~ \" \1 \" ]] || added_files[${#added_files[@]}]=\"\1\",p
+ s,^.[MAU] \([^\"][^/]*/\?\).*, modified=modified; [[ \" ${modified_files[@]} \" =~ \" \1 \" ]] || modified_files[${#modified_files[@]}]=\"\1\",p
+ s,^.[MAU] \"\([^/]\+/\?\).*\"$, modified=modified; [[ \" ${modified_files[@]} \" =~ \" \1 \" ]] || modified_files[${#modified_files[@]}]=\"\1\",p
+ s,^?? \([^\"][^/]*/\?\).*, untracked=untracked; [[ \" ${untracked_files[@]} \" =~ \" \1 \" ]] || untracked_files[${#untracked_files[@]}]=\"\1\",p
+ s,^?? \"\([^/]\+/\?\).*\"$, untracked=untracked; [[ \" ${untracked_files[@]} \" =~ \" \1 \" ]] || untracked_files[${#untracked_files[@]}]=\"\1\",p
+ ' # |tee /dev/tty
+ )"
+
+ if ! grep -q "^ref:" "$git_dir/HEAD" 2>/dev/null; then
detached=detached
fi
@@ -482,12 +517,16 @@ parse_git_status() {
#### GET GIT HEX-REVISION
- rawhex="$(git rev-parse HEAD 2>/dev/null)"
- rawhex="${rawhex/HEAD/}"
- rawhex="${rawhex:0:6}"
+ if [[ $rawhex_len -gt 0 ]] ; then
+ rawhex="$(git rev-parse HEAD 2>/dev/null)"
+ rawhex=${rawhex/HEAD/}
+ rawhex="$hex_vcs_color${rawhex:0:$rawhex_len}"
+ else
+ rawhex=""
+ fi
#### branch
- branch="${branch/master/M}"
+ 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; } )
@@ -496,7 +535,7 @@ parse_git_status() {
### compose vcs_info
if [[ $init ]]; then
- vcs_info=M$white=init
+ vcs_info=${white}init
else
if [[ "$detached" ]] ; then
@@ -510,7 +549,7 @@ parse_git_status() {
fi
#branch="<$branch>"
fi
- vcs_info="$branch$white=$rawhex"
+ vcs_info="$branch$freshness$rawhex"
fi
}
@@ -554,23 +593,33 @@ parse_vcs_status() {
eval $old_nullglob
if [[ $vim_glob ]]; then
- vim_file=${vim_glob#.}
- vim_file=${vim_file/.sw?/}
+ set $vim_glob
+ #vim_file=${vim_glob#.}
+ if [[ $# > 1 ]] ; then
+ vim_files="*"
+ else
+ vim_file=${1#.}
+ vim_file=${vim_file/.sw?/}
+ [[ .${vim_file}.swp -nt $vim_file ]] && vim_files=$vim_file
+ fi
# if swap is newer, then this is unsaved vim session
- #[[ .${vim_file}.swp -nt $vim_file ]] && vim_files=$vim_file
# [temoto custom] if swap is older, then it must be deleted, so show all swaps.
- vim_files=$vim_file
fi
fi
### file list
unset file_list
- [[ ${added_files[0]} ]] && file_list+=" "$added_vcs_color${added_files[@]}
- [[ ${modified_files[0]} ]] && file_list+=" "$modified_vcs_color${modified_files[@]}
- [[ ${untracked_files[0]} ]] && file_list+=" "$untracked_vcs_color${untracked_files[@]}
- [[ ${vim_files} ]] && file_list+=" "${RED}VIM:${vim_files}
- file_list=${file_list:+:$file_list}
+ if [[ $count_only = "on" ]] ; then
+ [[ ${added_files[0]} ]] && file_list+=" "${added_vcs_color}+${#added_files[@]}
+ [[ ${modified_files[0]} ]] && file_list+=" "${modified_vcs_color}*${#modified_files[@]}
+ [[ ${untracked_files[0]} ]] && file_list+=" "${untracked_vcs_color}?${#untracked_files[@]}
+ else
+ [[ ${added_files[0]} ]] && file_list+=" "$added_vcs_color${added_files[@]}
+ [[ ${modified_files[0]} ]] && file_list+=" "$modified_vcs_color${modified_files[@]}
+ [[ ${untracked_files[0]} ]] && file_list+=" "$untracked_vcs_color${untracked_files[@]}
+ fi
+ [[ ${vim_files} ]] && file_list+=" "${MAGENTA}vim:${vim_files}
if [[ ${#file_list} -gt $max_file_list_length ]] ; then
file_list=${file_list:0:$max_file_list_length}
@@ -580,7 +629,7 @@ parse_vcs_status() {
fi
- head_local="(${vcs_info}$vcs_color${file_list}$vcs_color)"
+ head_local="$vcs_color(${vcs_info}$vcs_color${file_list}$vcs_color)"
### fringes
head_local="${head_local+$vcs_color$head_local }"
@@ -588,11 +637,22 @@ parse_vcs_status() {
#tail_local="${tail_local+$vcs_color $tail_local}${dir_color}"
}
+parse_virtualenv_status() {
+ unset virtualenv
+
+ [[ $virtualenv_module = "on" ]] || return 1
+
+ if [[ -n "$VIRTUAL_ENV" ]] ; then
+ virtualenv=`basename $VIRTUAL_ENV`
+ rc="$rc $virtualenv_color<$virtualenv> "
+ fi
+ }
+
disable_set_shell_label() {
trap - DEBUG >& /dev/null
}
-# enable stuffing currently executed command displays in label
+# show currently executed command in label
enable_set_shell_label() {
disable_set_shell_label
# check for BASH_SOURCE being empty, no point running set_shell_label on every line of .bashrc
@@ -600,19 +660,27 @@ enable_set_shell_label() {
set_shell_label "$BASH_COMMAND"' DEBUG >& /dev/null
}
+declare -ft disable_set_shell_label
+declare -ft enable_set_shell_label
+
# autojump (see http://wiki.github.com/joelthelion/autojump)
+
+# TODO reverse the line order of a file
+#awk ' { line[NR] = $0 }
+# END { for (i=NR;i>0;i--)
+# print line[i] }' listlogs
+
j (){
: ${1? usage: j dir-beginning}
# go in ring buffer starting from current index. cd to first matching dir
- for (( i=(aj_idx+1)%aj_max; i != aj_idx%aj_max; i=++i%aj_max )) ; do
- #echo == ${aj_dir_list[$i]} == $i
+ for (( i=(aj_idx-1)%aj_max; i != aj_idx%aj_max; i=(--i+aj_max)%aj_max )) ; do
if [[ ${aj_dir_list[$i]} =~ ^.*/$1[^/]*$ ]] ; then
cd "${aj_dir_list[$i]}"
return
fi
done
echo '?'
-}
+ }
alias jumpstart='echo ${aj_dir_list[@]}'
@@ -626,6 +694,7 @@ prompt_command_function() {
cwd="${PWD/$HOME/~}" # substitute "~"
set_shell_label "${cwd##[/~]*/}/" # default label - path last dir
+ parse_virtualenv_status
parse_vcs_status
# autojump
@@ -642,7 +711,7 @@ prompt_command_function() {
PS1="$colors_reset$color_who_where$dir_color$cwd $head_local\n$colors_reset$rc$jobs$prompt_color$prompt_char $colors_reset"
unset head_local tail_local pwd
-}
+ }
PROMPT_COMMAND=prompt_command_function