-
Notifications
You must be signed in to change notification settings - Fork 1
/
shprompt
379 lines (342 loc) · 11.1 KB
/
shprompt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
#!/bin/sh
# this file origin zsh src: https://github.com/jordanlewis/config/blob/482e1b33f152c810f082b0d767a66e1942d2fe08/zshprompt
case $1 in -x) set -x; shift; esac
# nonPOSIX: declare -A gitinfo
if [ -d '/\.\C:\Windows' ] || ( cd C:/ 2>&- && [ "$PWD" = 'C:/' ] ); then
echo 1111111
_git_pwd_() { @ pwd; }
else
_git_pwd_() { pwd; }
fi
case $(command -v git) in *__gitinfo_git_fn*) unalias git; esac
#true || { # DEBUG
# # consider when on Linux and testing if will work for Busybox-w32+WSLgit
# mound --bind / /mnt/rootfs
# _git_test_misspath() {
# (cd "/mnt/rootfs/$PWD"; exec \git "$@")
# }
# alias git=_git_test_misspath
#}
# nonPOSIX: local -A c
c_br=$(tput setaf 6) # branch name color
c_halt=$(tput setaf 5) # abnormal status color
c_sha=$(tput setaf 3) # sha color
c_plus=$(tput setaf 2) # revisions ahead color
c_minus=$(tput setaf 1) # revisions behind color
c_equal=$(tput setaf 4)
c_none=$(tput sgr0)
#declare -A gitinfo
gitinfo_update() {
# gitinfo=()
case $PWD in */.git/*| */.git)
echo >&2 "We're inside a .git folder which is going to cause "
echo >&2 "problems for rev-parse"
return 1
esac
# gitinfo__dir=$(git rev-parse --git-dir 2>/dev/null) # does not detect worktree
gitinfo__dir=$(git rev-parse --git-common-dir 2>/dev/null)
case $?:$gitinfo__dir in 0:?*) ;; *)
gitinfo__msg=""
gitinfo__dir=""
return
esac
gitinfo__top=$(git rev-parse --show-toplevel)
gitinfo__bare=$(git rev-parse --is-bare-repository)
local branch_ref;
branch_ref=$(git symbolic-ref HEAD 2>/dev/null)
gitinfo__branch=${branch_ref##*/}
gitinfo__headname=${gitinfo__branch}
case $gitinfo__branch in
'')
#old: gitinfo__headname="${c_br}$(git name-rev --name-only HEAD)" # get hash probably?
gitinfo__headname=${c_br}$(git log -n 1 --pretty=format:"%H" HEAD | cut -c 0-16)
gitinfo__detached=true
;;
*)
gitinfo__detached=''
esac
# TODO: instead of true/false -> count them
# consider using `git status -s | cut -c 0-2`
case $(git ls-files "${gitinfo__top}" --modified) in ?*)
gitinfo__hasmodified=true
esac
if ! git diff --quiet --cached 2>/dev/null; then
gitinfo__hasmodifiedstaged=true
fi
case $(git ls-files -u) in ?*)
gitinfo__unmerged=true
esac
case $(git ls-files --others --exclude-standard) in ?*) # untracked
gitinfo__untracked=true
esac
case $gitinfo__branch in ?*)
local remote;remote=$(git config branch.${gitinfo__branch}.remote)
if [[ "$remote" != '' ]]; then
local merge;merge=$(git config branch.${gitinfo__branch}.merge)
merge=${merge##refs/heads/}
if [[ "$remote" != "." ]]; then
merge=$remote/$merge
fi
merge=$(git rev-parse --abbrev-ref --symbolic-full-name @{u})
local behind ahead
behind=$(git rev-list ${gitinfo__branch}..$merge | wc -l)
ahead=$(git rev-list $merge..${gitinfo__branch} | wc -l)
# reset to master~1: master..origin/master has 1
# add commit to master: origin/master..master has 1
# add commit to master~1: both have 1
local tracking_msg=""
if [[ "$ahead" -eq 0 ]] && [[ "$behind" -eq 0 ]]; then
tracking_msg=$tracking_msg
else
if [[ 0 -lt "$ahead" ]]; then
tracking_msg=$tracking_msg"${c_plus}+$ahead"
fi
if [[ 0 -lt "$behind" ]]; then
tracking_msg=$tracking_msg"${c_minus}-$behind"
fi
fi
gitinfo__tracking_merge="${c_br}$merge"
gitinfo__tracking_msg=$tracking_msg
fi
esac
#gitinfo__headtaggit
local g=${gitinfo__dir}
if [ -d "$g/rebase-merge" ]; then
if [ -f "$g/rebase-merge/interactive" ]; then
gitinfo__op="rb -i"
gitinfo__rb_head=$(git name-rev --name-only $(cat "$g/rebase-merge/orig-head"))
gitinfo__rb_onto=$(git name-rev --name-only $(cat "$g/rebase-merge/onto"))
gitinfo__op_msg="${gitinfo__rb_onto}..${gitinfo__rb_head}"
else
gitinfo__op="rb -m"
gitinfo__rb_head=$(cat "$g/rebase-merge/head-name")
gitinfo__op_msg="on ${gitinfo__rb_head}"
fi
elif [ -d "$g/rebase-apply" ]; then
if [ -f "$g/rebase-apply/rebasing" ]; then
gitinfo__op="rb"
elif [ -f "$g/rebase-apply/applying" ]; then
gitinfo__op="am"
else
gitinfo__op="am/rb"
fi
gitinfo__op_msg="on ${gitinfo__headname}"
elif [ -f "$g/MERGE_HEAD" ]; then
gitinfo__op="mrg"
gitinfo__merge_head=$(cat "$g/MERGE_HEAD")
gitinfo__op_msg="$(git name-rev --name-only ${gitinfo__merge_head}) into ${gitinfo__headname}"
elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
gitinfo__op="chrypck"
gitinfo__cp_head=$(cat "$g/CHERRY_PICK_HEAD")
gitinfo__op_msg="from $(git name-rev --name-only ${gitinfo__cp_head}) onto ${gitinfo__headname}"
elif [ -f "$g/BISECT_LOG" ]; then
gitinfo__op="bs"
gitinfo__bs_start=$(cat "$g/BISECT_START")
gitinfo__op_msg="from ${gitinfo__bs_start} on ${gitinfo__headname}"
else
case $gitinfo__detached in
'') gitinfo__op='';;
*) gitinfo__op=dtch;;
esac
gitinfo__op_msg=${gitinfo__headname}
case $gitinfo__tracking_msg in ?*)
gitinfo__op_msg=$gitinfo__op_msg" ${gitinfo__tracking_msg} ${gitinfo__tracking_merge}"
esac
fi
case ${gitinfo__op} in
#on) gitinfo__op="${c_none}${gitinfo__op}";;
'') ;;
*) gitinfo__op="${c_halt}${gitinfo__op}";;
esac
#printf %s\\n gitinfo__msg="${gitinfo__op}${gitinfo__op:+${gitinfo__op_msg:+- }}${gitinfo__op_msg}" >&2 # DEBUG
# ( set -x; # DEB
# gitinfo__op=${gitinfo__op}
# : ${gitinfo__op:+x}
# gitinfo__op_msg=${gitinfo__op_msg}
# : ${gitinfo__op_msg:+x}
# : ${gitinfo__op:+${gitinfo__op_msg:+x}}
# )
gitinfo__msg="${gitinfo__op}${gitinfo__op:+${gitinfo__op_msg:+- }}${gitinfo__op_msg}"
}
# echo '<==> gitinfo_update'
gitinfo_update
# echo '<==>'
# git_status() { # fn never used?
# if [[ "${gitinfo__dir}" = '' ]]; then
# return
# else
# printf %s " ${gitinfo__op} ${gitinfo__op_msg}"
# fi
# }
trimparser_ltr() {
local trimparser_word_next pat
for pat; do
#case $pat in
# \*\**) trimparser_word_new=${trimparser_word##$pat};;
# *) trimparser_word_new=${trimparser_word#$pat};;
trimparser_word_new=${trimparser_word##$pat}
#esac
case $trimparser_word_new in "$trimparser_word")
# printf %s\\n >&2 "trimparser_ltr: '$trimparser_word' does not match ($pat)"
return 1
esac
trimparser_word=$trimparser_word_new
done
}
git_path() {
case $gitinfo__dir in '')
# echo $(print -P %~)
case ${HOME:+x} in '') false;; *)
case $PWD in "$HOME"|"$HOME"/*)
printf %s "~${PWD#"$HOME"}"
;; *) false; esac;
esac || {
printf %s "$PWD"
}
return
esac
case ${gitinfo__hasmodified:+x}:${gitinfo__hasmodifiedstaged:+x} in
x:*) color=$(tput setaf 1);;
:) color=$(tput setaf 2);;
:x) color=$(tput setaf 3);;
esac
local gitinfo__toprepo;gitinfo__toprepo=$gitinfo__top
local gitinfo__remainingpwd
gitinfo__remainingpwd=$(_git_pwd_) # wsl path
gitinfo__remainingpwd=${gitinfo__remainingpwd#"$gitinfo__top"}
gitinfo__remainingpwd=${gitinfo__remainingpwd#/}
local buf;buf=''
trimparser_word=$gitinfo__toprepo
local gh_link_begin link_end
unset gh_link_begin
if
if trimparser_ltr "*/ http:/" || trimparser_ltr "*/ http%25/"; then
trimparser_ltr "github.com/"
else
trimparser_ltr "*/ github.com/"
fi
then
gh_link_begin=$(
trimparser_word_=$trimparser_word # =user/repo/raw/branch
##printf %s\\n >&2 "=user/repo/raw/branch = $trimparser_word_" # DEBUG
if trimparser_ltr '*/raw/' || trimparser_ltr '*/blob/' || trimparser_ltr '*/tree/'; then
##printf %s\\n >&2 "=branch = $trimparser_word" # DEBUG
trimparser_word_=${trimparser_word_%"/$trimparser_word"}
##printf %s\\n >&2 "=user/repo/raw = $trimparser_word_" # DEBUG
trimparser_word_=${trimparser_word_%/*}
##printf %s\\n >&2 "=user/repo = $trimparser_word_" # DEBUG
trimparser_word=$trimparser_word_/tree/$trimparser_word # =user/repo/tree/branch
##printf %s\\n >&2 "=user/repo/tree/branch = $trimparser_word" # DEBUG
fi
# printf '\e]8;;%s\e\\' "copy:https://github.com/$trimparser_word"
printf '\e]8;;%s\e\\' "https://github.com/$trimparser_word"
#printf '[%s](' "https://github.com/$trimparser_word"
)
link_end=$(printf '\e]8;;\e\\\n')
#link_end=$(printf ')')
buf=$buf${buf:+/}${gh_link_begin}
{
case $trimparser_word in
denisde4ev/*) ;; # pointless to show when its me
*) buf=$buf${trimparser_word%%/*}/;; # ${trimparser_word%%/*}=username
esac
trimparser_word=${trimparser_word#*/}
#printf %s\\n >&2 "=repo/tree/branch = $trimparser_word" # DEBUG
#printf %s\\n >&2 "=repo = ${trimparser_word%%/*}" # DEBUG
buf=$buf${trimparser_word%%/*}
}
trimparser_word=${trimparser_word#*/}
##printf %s\\n >&2 "=tree/branch = $trimparser_word" # DEBUG
buf=${buf}${link_end}/${trimparser_word%/*}/${color}${trimparser_word#**/}$(tput sgr0)
else
trimparser_word=${gitinfo__toprepo##*/}
# underline the main repo name:
buf=$buf${buf:+/}$(tput smul)${color}${trimparser_word%%/*}$(tput sgr0)
##printf %s\\n >&2 "=git_top = $trimparser_word" # DEBUG
if trimparser_ltr '*/'; then
buf=$buf${buf:+${trimparser_word:+/}}$trimparser_word
else
buf=$buf${buf:+/}$trimparser_word
fi
fi
#( set -x;
# gitinfo__remainingpwd=$gitinfo__remainingpwd
# buf=$buf
#)
case $gitinfo__remainingpwd in *??????/*)
gitinfo__remainingpwd='**'/${gitinfo__remainingpwd##*/}
esac
buf=${buf}${gitinfo__remainingpwd:+/}$gitinfo__remainingpwd
printf %s "$buf"
#local root;root=${gitinfo__top}
# WTF:
# echo ${${${$(print -P %d)/${root}/${root:h}/${color}${root:t}$(tput setaf 6)}/${HOME}/\~/}/\/\//\/} # original line
# expended:
#printf %s \
# ${
# ${
# ${
# $PWD
# /$root
# /${root:h}
# /${color}${root:t}$(tput setaf 6)
# }
# /${HOME}
# /\~
# /
# }
# /\/\/
# /\/
# } \
#;
#echo
}
case ${0##*/} in *-prompt-*|*-prompt|git-*) ;; *) # only when it is sourced
case ${ZSH_VERSION+x} in
x)
gitinfo_zsh_preexec() {
case $2 in 'git '*|*[\ \;\&\|\\]"git "*) ;; *) return; esac
args=${2#*'git '}
case ${args%%" "*} in status|ls|ls-files|log|lg|shortlog|last|diff|diffstat|show) return; esac # Don't update if git status, git ls, etc.
gitinfo__do_update=1
}
gitinfo_zsh_precmd() {
case $gitinfo__do_update in 1)
gitinfo__do_update=0
gitinfo_update
esac
}
add-zsh-hook chpwd gitinfo_update
add-zsh-hook preexec gitinfo_zsh_preexec
add-zsh-hook precmd gitinfo_zsh_precmd
PS1='$(tput setaf 3)[%T$(tput setaf 6)%1(j.%%$(tput setaf 2)%j$(tput setaf 6).)%0(?..:$(tput setaf 1)%B%?%b)$(tput setaf 3)]$(tput setaf 6)%# %f'
RPS1='%100>..>$(tput setaf 6)%n%f%B@%b$(tput setaf 6)%m%f%B:%b%<<$(tput setaf 6)$(git_path)${gitinfo__msg}%b%k%f'
;;
*) # when not zsh / all other shells
case $(command -v git) in
'') printf %s\\n >&2 "is 'git' command in your path?";;
*/*)
__gitinfo_git_fn() {
\git "$@"
case $1 in status|ls|ls-files|log|lg|shortlog|last|diff|diffstat|show) return; esac # Don't update if git status, git ls, etc.
gitinfo_update
}
__gitinfo_cd_fn() {
\cd "$@" || return
gitinfo_update || {
printf %s\\n >&2 "gitinfo_update: status: $?"
return 0
}
}
true || alias \
git=__gitinfo_git_fn \
cd=__gitinfo_cd_fn \
;
;;
*) ;; ##printf %s\\n >&2 "warning: seems like current shell have already defined 'git' as function/alias?";;
esac
esac
esac
case ${0##*/} in shprompt)
printf %s\\n "$(git_path) $gitinfo__msg"
esac