@@ -17,102 +17,127 @@ HISTSIZE=-1
1717HISTFILESIZE=-1
1818HISTCONTROL=ignoredups
1919
20- __prompt_is_unmerged_status () {
21- case " $1 " in
22- DD | AU | UD | UA | DU | AA | UU) return 0 ;;
23- * ) return 1 ;;
24- esac
25- }
26-
2720__prompt_git_operation () {
2821 local git_dir=$1
2922
3023 if [[ -f $git_dir /MERGE_HEAD ]]; then
31- printf ' %s\n ' merge
24+ __prompt_git_operation_result= merge
3225 elif [[ -d $git_dir /rebase-merge || -d $git_dir /rebase-apply ]]; then
33- printf ' %s\n ' rebase
26+ __prompt_git_operation_result= rebase
3427 elif [[ -f $git_dir /BISECT_LOG ]]; then
35- printf ' %s\n ' bisect
28+ __prompt_git_operation_result= bisect
3629 elif [[ -f $git_dir /CHERRY_PICK_HEAD ]]; then
37- printf ' %s\n' cherry-pick
30+ __prompt_git_operation_result=cherry-pick
31+ else
32+ __prompt_git_operation_result=
3833 fi
3934}
4035
41- __prompt_git_info () {
42- local branch_color=$1
43- local staged_color=$2
44- local unstaged_color=$3
45- local untracked_color=$4
46- local operation_color=$5
47- local conflict_color=$6
48- local reset=$7
49- local branch git_dir operation line status index_status worktree_status
50- local staged=0 unstaged=0 untracked=0 conflicts=0
51-
52- git_dir=$( git rev-parse --git-dir 2> /dev/null) || return
53- operation=$( __prompt_git_operation " $git_dir " )
54-
55- while IFS= read -r line; do
56- if [[ $line == ' ## ' * ]]; then
57- branch=${line# ' ## ' }
58- branch=${branch# ' No commits yet on ' }
59- branch=${branch%% ...* }
60- branch=${branch%% \[ * }
61- [[ $branch == HEAD\ * ]] && branch=HEAD
62- continue
63- fi
36+ __prompt_git_cache_key=
37+ __prompt_git_dir=
6438
65- status=${line: 0: 2}
66- index_status=${line: 0: 1}
67- worktree_status=${line: 1: 1}
39+ __prompt_find_git_dir () {
40+ local cache_key candidate dir git_file parent target
6841
69- if [[ $status == ' ??' ]]; then
70- (( untracked++ ))
71- elif __prompt_is_unmerged_status " $status " ; then
72- (( conflicts++ ))
42+ cache_key=" ${PWD} " $' \034 ' " ${GIT_DIR-} " $' \034 ' " ${GIT_WORK_TREE-} " $' \034 ' " ${GIT_COMMON_DIR-} "
43+ [[ $cache_key == " $__prompt_git_cache_key " ]] && return
44+
45+ __prompt_git_cache_key=$cache_key
46+ __prompt_git_dir=
47+
48+ if [[ -n ${GIT_DIR:- } ]]; then
49+ if [[ $GIT_DIR == /* ]]; then
50+ candidate=$GIT_DIR
7351 else
74- [[ $index_status != ' ' ]] && (( staged++ ))
75- [[ $worktree_status != ' ' ]] && (( unstaged++ ))
52+ candidate=$PWD /$GIT_DIR
7653 fi
77- done < <( git --no-optional-locks status --porcelain=v1 --branch 2> /dev/null)
54+ [[ -f $candidate /HEAD ]] && __prompt_git_dir=$candidate
55+ return
56+ fi
7857
58+ dir=$PWD
59+ while : ; do
60+ candidate=$dir /.git
61+ if [[ -d $candidate ]]; then
62+ __prompt_git_dir=$candidate
63+ return
64+ elif [[ -f $candidate ]]; then
65+ IFS= read -r git_file < " $candidate " || return
66+ git_file=${git_file% $' \r ' }
67+ if [[ $git_file == gitdir:* ]]; then
68+ target=${git_file# gitdir: }
69+ target=" ${target# " ${target%% [![:space:]]* } " } "
70+ if [[ $target == /* ]]; then
71+ candidate=$target
72+ else
73+ candidate=$dir /$target
74+ fi
75+ [[ -f $candidate /HEAD ]] && __prompt_git_dir=$candidate
76+ fi
77+ return
78+ elif [[ -f $dir /HEAD && -d $dir /objects && -d $dir /refs ]]; then
79+ __prompt_git_dir=$dir
80+ return
81+ fi
82+
83+ [[ $dir == / ]] && return
84+ parent=${dir%/* }
85+ dir=${parent:-/ }
86+ done
87+ }
88+
89+ __prompt_git_info () {
90+ local branch_color=$1
91+ local operation_color=$2
92+ local reset=$3
93+ local branch head
94+
95+ __prompt_git_segment=
96+ __prompt_find_git_dir
97+ [[ -n $__prompt_git_dir ]] || return
98+ IFS= read -r head < " $__prompt_git_dir /HEAD" || return
99+ head=${head% $' \r ' }
100+
101+ if [[ $head == ' ref: refs/heads/' * ]]; then
102+ branch=${head# ' ref: refs/heads/' }
103+ elif [[ $head == ' ref: ' * ]]; then
104+ branch=${head# ' ref: ' }
105+ else
106+ branch=HEAD
107+ fi
79108 [[ -n $branch ]] || return
80109
81- printf ' %s%s%s' " $branch_color " " $branch " " $reset "
82- [[ $staged -gt 0 ]] && printf ' %s+%d%s' " $staged_color " " $staged " " $reset "
83- [[ $unstaged -gt 0 ]] && printf ' %s~%d%s' " $unstaged_color " " $unstaged " " $reset "
84- [[ $untracked -gt 0 ]] && printf ' %s?%d%s' " $untracked_color " " $untracked " " $reset "
85- [[ -n $operation ]] && printf ' %s%s%s' " $operation_color " " $operation " " $reset "
86- [[ $conflicts -gt 0 ]] && printf ' %sconflict:%d%s' " $conflict_color " " $conflicts " " $reset "
87- printf ' \n'
110+ __prompt_git_segment=" ${branch_color}${branch}${reset} "
111+ __prompt_git_operation " $__prompt_git_dir "
112+ if [[ -n $__prompt_git_operation_result ]]; then
113+ __prompt_git_segment+=" ${operation_color}${__prompt_git_operation_result}${reset} "
114+ fi
88115}
89116
90117__prompt_render () {
91118 local exit_status=$1
92119 local cwd=${PWD##*/ }
93- local host git_info segments=()
120+ local host segments=()
94121 local reset=' \[\e[0m\]'
95122 local bold=' \[\e[1m\]'
96123 local dim=' \[\e[2m\]'
97124 local slate=' \[\e[38;5;245m\]'
98125 local red=' \[\e[38;5;203m\]'
99126 local green=' \[\e[38;5;114m\]'
100- local yellow=' \[\e[38;5;179m\]'
101127 local blue=' \[\e[38;5;75m\]'
102128 local purple=' \[\e[38;5;141m\]'
103- local cyan=' \[\e[38;5;109m\]'
104129
105130 [[ -n $cwd ]] || cwd=/
106131
107132 if [[ -n ${SSH_CLIENT:- } ]]; then
108- host=$( hostname -s 2> /dev/null || hostname )
133+ host=${HOSTNAME %% . * }
109134 segments+=(" ${slate}${USER} @${host}${reset} " )
110135 fi
111136
112137 segments+=(" ${bold}${blue}${cwd}${reset} " )
113138
114- git_info= $( __prompt_git_info " $green " " $cyan " " $yellow " " $ purple" " $purple " " $red " " $ reset" )
115- [[ -n $git_info ]] && segments+=(" $git_info " )
139+ __prompt_git_info " $green " " $purple " " $reset "
140+ [[ -n $__prompt_git_segment ]] && segments+=(" $__prompt_git_segment " )
116141 [[ -n ${VIRTUAL_ENV:- } ]] && segments+=(" ${purple} venv${reset} " )
117142 [[ $exit_status -ne 0 ]] && segments+=(" ${red} ✗$exit_status ${reset} " )
118143
@@ -145,8 +170,6 @@ PROMPT_COMMAND=__prompt_command
145170# huponexit send SIGHUP to all jobs when an interactive login shell exits
146171shopt -s autocd cdspell dirspell histappend checkjobs direxpand checkwinsize cmdhist huponexit
147172
148- stty -ixon # Disable ctrl-s and ctrl-q.
149-
150173# Load aliases
151174if [ -f " $HOME /.aliasrc" ]; then
152175 # shellcheck disable=SC1091
0 commit comments