-
Notifications
You must be signed in to change notification settings - Fork 0
/
snooch.zsh
174 lines (137 loc) · 4.41 KB
/
snooch.zsh
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
#!/usr/bin/env zsh
# Snooch
# by Bob Soppe
# https://github.com/bobsoppe/snooch
# MIT License
# Largely based on Pure by Sindre Sorhus <https://github.com/sindresorhus/pure>
prompt_snooch_git_branch() {
local branch git_dir_local rtn
# get the current git status
branch=$(git status --short --branch -uno --ignore-submodules=all | head -1 | awk '{print $2}' 2>/dev/null)
git_dir_local=$(git rev-parse --git-dir)
# remove reference to any remote tracking branch
branch=${branch%...*}
# check if HEAD is detached
if [[ -d "${git_dir_local}/rebase-merge" ]]; then
branch=$(git status | head -5 | tail -1 | awk '{print $6}')
rtn="rebasing interactively → ${branch//([[:space:]]|\')/}"
elif [[ -d "${git_dir_local}/rebase-apply" ]]; then
branch=$(git status | head -2 | tail -1 | awk '{print $6}')
rtn="rebasing → ${branch//([[:space:]]|\')/}"
elif [[ -f "${git_dir_local}/MERGE_HEAD" ]]; then
branch=$(git status | head -1 | awk '{print $3}')
rtn="merging → ${branch//([[:space:]]|\')/}"
elif [[ "$branch" = "HEAD" ]]; then
commit=$(git status HEAD -uno --ignore-submodules=all | head -1 | awk '{print $4}' 2>/dev/null)
if [[ "$commit" = "on" ]]; then
rtn="no branch"
else
rtn="detached@$commit"
fi
else
rtn="$branch"
fi
print "$rtn"
}
prompt_snooch_git_repo_status() {
local clean message_git count up down
# do a fetch asynchronously
git fetch > /dev/null 2>&1 &!
touched="$(git status --porcelain 2>/dev/null)"
staged="$(git diff --cached --no-ext-diff 2>/dev/null)"
dirty="$(git diff --no-ext-diff 2>/dev/null)"
if [[ $touched != "" ]]; then
if [[ $staged != "" ]]; then
if [[ $dirty != "" ]]; then
message_git="[±]"
else
message_git="[+]"
fi
else
message_git="[?]"
fi
fi
# check if there is an upstream configured for this branch
if command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then
# check git left and right arrow_status
count="$(command git rev-list --left-right --count HEAD...@'{u}' 2>/dev/null)"
# get the push and pull counts
up="$count[(w)1]"
down="$count[(w)2]"
[[ $message_git != "" ]] && message_git+=" "
[[ $up > 0 ]] && message_git+="⇡"
[[ $down > 0 ]] && message_git+="⇣"
fi
print $message_git
}
prompt_snooch_precmd() {
local prompt_snooch_preprompt git_root current_path branch repo_status
# ensure prompt starts on a new line
prompt_snooch_preprompt="\n"
# username
prompt_snooch_preprompt+="%F{red}%n%f "
# hostname
prompt_snooch_preprompt+="at "
prompt_snooch_preprompt+="%F{yellow}$HOST%f "
# directory
prompt_snooch_preprompt+="in "
prompt_snooch_preprompt+="%F{green}%~%f "
# git status
if command git rev-parse --is-inside-work-tree &>/dev/null; then
branch=$(prompt_snooch_git_branch)
repo_status=$(prompt_snooch_git_repo_status)
prompt_snooch_preprompt+="on "
prompt_snooch_preprompt+="%F{blue}$branch $repo_status%f "
fi
print -P $prompt_snooch_preprompt
# reset value since `preexec` isn't always triggered
unset cmd_timestamp
}
prompt_snooch_preexec() {
# shows the current dir and executed command in the title when a process is active
print -Pn "\e]0;"
print -PN "%~: $2"
print -Pn "\a"
}
prompt_snooch_nice_exit_code() {
local exit_status="${1:-$(print -P %?)}";
# nothing to do here
[[ ${SNOOCH_SHOW_EXIT_CODE:=0} != 1 || -z $exit_status || $exit_status == 0 ]] && return;
local sig_name;
# is this a signal name (error code = signal + 128) ?
case $exit_status in
129) sig_name=HUP ;;
130) sig_name=INT ;;
131) sig_name=QUIT ;;
132) sig_name=ILL ;;
134) sig_name=ABRT ;;
136) sig_name=FPE ;;
137) sig_name=KILL ;;
139) sig_name=SEGV ;;
141) sig_name=PIPE ;;
143) sig_name=TERM ;;
esac
# usual exit codes
case $exit_status in
-1) sig_name=FATAL ;;
1) sig_name=WARN ;;
2) sig_name=BUILTINMISUSE ;;
126) sig_name=CCANNOTINVOKE ;;
127) sig_name=CNOTFOUND ;;
esac
echo "$ZSH_PROMPT_EXIT_SIGNAL_PREFIX${exit_status}:${sig_name:-$exit_status}$ZSH_PROMPT_EXIT_SIGNAL_SUFFIX";
}
prompt_snooch_prompt() {
# red if the previous command didn't exit with 0
print "%(?.%F{green}.%F{red}$(prompt_snooch_nice_exit_code))❯%f "
}
prompt_snooch_setup() {
# prevent percentage showing up if output doesn't end with a newline
export PROMPT_EOL_MARK=""
zmodload zsh/datetime
autoload -Uz add-zsh-hook
add-zsh-hook precmd prompt_snooch_precmd
add-zsh-hook preexec prompt_snooch_preexec
PROMPT="$(prompt_snooch_prompt)"
}
prompt_snooch_setup "$@"