-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.bash_prompt
More file actions
316 lines (284 loc) · 11.8 KB
/
Copy path.bash_prompt
File metadata and controls
316 lines (284 loc) · 11.8 KB
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
#!/bin/env bash
# shellcheck shell=bash
# shellcheck disable=SC2312
# Check termcaps
# Start in our safe space
PS1_color=no
HAS_FANCY_FONT=no
# Check for Color Capability via tput
case $(tput colors 2>/dev/null) in
[1-9]|1[0-6])
PS1_color="yes"
PS1_lc_opts=(-x -f)
;;
*)
PS1_color="yes"
PS1_lc_opts=(-v 0.1 -h 0.1 -b -f)
;;
esac
# Check for Unicode (OS Locale + Terminal Blocklist)
if [[ "${LC_ALL:-${LC_CTYPE:-${LANG}}}" =~ [Uu][Tt][Ff]-?8 ]] && [[ ! "${TERM}" =~ ^(linux|dumb|cons25|vt[0-9]+)$ ]]; then
HAS_FANCY_FONT=yes
fi
# Print UTF-8 char?
# To define fallback chars for terms that don't support Unicode
__ps1_utf8() {
case "${HAS_FANCY_FONT}" in
yes)
echo "${1}"
;;
*)
echo "${2}"
;;
esac
}
# The opening and closing characters for info in the prompt
PS1_Op="$(__ps1_utf8 ⟪ '[')"
PS1_Cl="$(__ps1_utf8 ⟫ ']')"
# Other options, presented with the box drawing character,
# to see which look best with your particular terminal font:
# ═⏴⏵═ ═❨❩═ ═❪❫═ ═❬❭═ ═❮❯═ ═❰❱═ ═❲❳═ ═❴❵═ ═⟦⟧═ ═⟨⟩═ ═⟪⟫═ ═⟬⟭═
# ═⟮⟯═ ═⦃⦄═ ═⦅⦆═ ═⦇⦈═ ═⦉⦊═ ═⦋⦌═ ═⦍⦎═ ═⦏⦐═ ═⦑⦒═ ═⦓⦔═ ═⦕⦖═ ═⦗⦘═
# ═⨠ ═⧏⧐═ ═⧑ ⧒═ ═⧓═ ═⧔ ⧕═ ═⨝═ ═⨭ ⨮═ ═⨴ ⨵═ ═⩤ ⩥═ ═⩹ ⩺═ ═⩽ ⩾═
# ═⩿⪀═ ═⪁⪂═ ═⪃⪄═ ═⪋⪌═ ═⪕⪖═ ═⪗⪘═ ═⪙⪚═ ═⪛⪜═ ═⪡⪢═ ═⪥ ═⪦ ⪧═ ═⪨⪩═
# ═⪪⪫═ ═⪬⪭═ ═⪯⪰═ ═⪳⪴═ ═⪻⪼═ ═⪽⪾═ ═⫇⫈═ ═⫍⫎═ ═⫏⫐═ ═⫑⫒═ ═⫗═ ═⫘═
# ⫞═ ═⫣ ⫤ ⫥ ⫦═ ═⫬ ⫭═ ═⫷ ⫸═ ═⫹ ⫺═ ═⫻ ⫻═ ═⭆ ⭅═ ═⮆ ⮄═ ═⮊ ⮈═ ═⮎ ⮌═
# ═⮑ ⮐═ ═⮘ ⮚═ ═⮜ ⮞═ ═⮡ ⮠═ ═⮣ ⮢═ ═⮩ ⮨═ ═⮫ ⮪═ ═⮵ ⮶═ ═⮷ ⮴═ ═⯰ ⯰═
# ═⯴ ⯴═ ═⯵ ⯵═ ═⯺ ⯺═ ═⯼ ⯼═ ═⸎ ⸎═ ═⸦ ⸧═ ═⸨ ⸩═ ═⸬ ⸬═
# ═〈〉═ ═《》═ ═「」═ ═『』═ ═【】═ ═〔〕═ ═〖〗═ ═〘〙═ ═〚〛═
# Disable Python virtualenv modifications to the prompt
# That's taken care of here instead
export VIRTUAL_ENV_DISABLE_PROMPT="yes"
__ps1_getVirtualenv() {
if [[ -v VIRTUAL_ENV ]]; then
echo -n "${PS1_Op}$(basename "${VIRTUAL_ENV}")${PS1_Cl}"
fi
}
# Print UTF-8 time char?
__ps1_utf8time() {
case "${HAS_FANCY_FONT}" in
yes)
case "${1}:${2}" in
01:[0-2][0-9]) echo "🕐" ;; 01:[3-5][0-9]) echo "🕜" ;;
02:[0-2][0-9]) echo "🕑" ;; 02:[3-5][0-9]) echo "🕝" ;;
03:[0-2][0-9]) echo "🕒" ;; 03:[3-5][0-9]) echo "🕞" ;;
04:[0-2][0-9]) echo "🕓" ;; 04:[3-5][0-9]) echo "🕟" ;;
05:[0-2][0-9]) echo "🕔" ;; 05:[3-5][0-9]) echo "🕠" ;;
06:[0-2][0-9]) echo "🕕" ;; 06:[3-5][0-9]) echo "🕡" ;;
07:[0-2][0-9]) echo "🕖" ;; 07:[3-5][0-9]) echo "🕢" ;;
08:[0-2][0-9]) echo "🕗" ;; 08:[3-5][0-9]) echo "🕣" ;;
09:[0-2][0-9]) echo "🕘" ;; 09:[3-5][0-9]) echo "🕤" ;;
10:[0-2][0-9]) echo "🕙" ;; 10:[3-5][0-9]) echo "🕥" ;;
11:[0-2][0-9]) echo "🕚" ;; 11:[3-5][0-9]) echo "🕦" ;;
12:[0-2][0-9]) echo "🕛" ;; 12:[3-5][0-9]) echo "🕧" ;;
*) ;;
esac
;;
*) ;;
esac
return 0
}
__ps1_color_wrap_non_printing() {
local ESC SOH STX REGEX REPLACE
ESC=$(echo -e '\033')
SOH=$(echo -e '\001')
STX=$(echo -e '\002')
REGEX=${ESC}'\[[[:digit:];]*m'
REPLACE=${SOH}'&'${STX}
sed "s/${REGEX}/${REPLACE}/g"
}
# Get tty
__ps1_tty() {
tty | cut -c 6-
return 0
}
# Get № Jobs Running
__ps1_jr() {
jobs -pr | wc -l
return 0
}
# Get № Jobs Sleeping
__ps1_js() {
jobs -ps | wc -l
return 0
}
# Uptime
__ps1_uptime() {
local PS1_upsecs
PS1_upsecs=$(awk '{print $1}' /proc/uptime | awk -F . '{print $1}')
date -ud @"${PS1_upsecs}" +"$((PS1_upsecs / 3600 / 24))d %H:%M"
return 0
}
# Dir stats
__ps1_dirSize() { sed -n 1p <<<"${PS1_dirList}" | awk '{print $2}'; }
__ps1_files() { \grep "^-" <<<"${PS1_dirList}" | awk '{print $9}' | \grep -cv "^\."; }
__ps1_hiddenFiles() { \grep "^-" <<<"${PS1_dirList}" | awk '{print $9}' | \grep -c "^\."; }
__ps1_execs() { \grep -c "^-..x" <<<"${PS1_dirList}"; }
__ps1_dirs() { \grep "^d" <<<"${PS1_dirList}" | awk '{print $9}' | \grep -cv "^\."; }
__ps1_hiddenDirs() { \grep "^d" <<<"${PS1_dirList}" | awk '{print $9}' | \grep -c "^\."; }
__ps1_links() { \grep -c "^l" <<<"${PS1_dirList}"; }
__ps1_spec() { \grep -c "^[bcps]" <<<"${PS1_dirList}"; }
# Calculate padding
__pad() {
local len pad
if [[ "${1}" = 1_L1 ]]; then
len="$(wc -m <<<"${PS1_L1@P}")"
else
len="$(wc -m <<<"${PS1_L2@P}")"
fi
if [[ "${HAS_FANCY_FONT}" = yes ]]; then
if [[ "${1}" = 1_L1 ]]; then
pad=$((COLUMNS - len - 11))
else
pad=$((COLUMNS - len - 8))
fi
else {
if [[ "${1}" = 1_L1 ]]; then
pad=$((COLUMNS - len - 14))
else
pad=$((COLUMNS - len))
fi
}
fi
printf %"${pad}"s | sed 's/ /═/g'
}
# Tab/Window Title for graphical terms, includes advanced formatting for:
# - Maintaining "~" abbreviation across commands
# - Active command running in foreground, including resumed from "fg"
# - Display "idle" if nothing running
#
# Format: ╭────────────────┤Python virtual environment, if active
# ╭───╯ ╭────────────┤Self-explanatory, I hope!
# ╭───╯ ╭──╯ ╭──────────┤# of Jobs Running in background
# ╭───╯ ╭──╯ ╭─╯ ╭────────┤# of Jobs Sleeping in background
# ╭───╯ ╭──╯ ╭─╯ ╭─╯ ╭──────┤Current Working Dir, or "~" if $HOME
# ╭───╯ ╭──╯ ╭─╯ ╭─╯ ╭─╯ ╭───┤Active command running, or "idle" if none
# ╭──┴──╮ ╭──────┴─────╮╭┴╮ ╭┴╮ ╭┴╮ ╭┴╮
# "(v.env) user@host(tty)(JR/JS):cwd (cmd)"
__ps1_preCommand() {
if tput tsl >/dev/null 2>&1; then
local venv ps1_tty
venv="$(__ps1_getVirtualenv)"
ps1_tty="$(__ps1_tty)"
# Get a reliable copy of $HOME, independent of Bash's mood
local u_home d_pwd
u_home="$(getent passwd "${USER}" | cut -d: -f6)"
# Update $PWD to ~ if we're $HOME
d_pwd="${PWD}"
# Strip the home path regardless of trailing slashes
[[ "${d_pwd}" == "${u_home}"* ]] && d_pwd="~${d_pwd#"${u_home}"}"
# Strip non-printing control chars
d_pwd="${d_pwd//[[:cntrl:]]/}"
# Update jobs!
jobs -p >/dev/null 2>&1
local jr js
jr="$(__ps1_jr)"
js="$(__ps1_js)"
# After a process exits, update the title to read "idle" instead of the
# literal last command run (which is ugly "history -a" here)
local d_cmd="${BASH_COMMAND}"
# If command is 'fg' or 'bg', find out what it's actually resuming
if [[ "${d_cmd}" == "fg"* || "${d_cmd}" == "bg"* ]]; then
# Get the job ID (either from the command or the default %)
local job_id="${d_cmd#?? }"
[[ "${job_id}" == "${d_cmd}" ]] && job_id="%"
# Extract the command string from the jobs list for that ID
local r_cmd
r_cmd=$(jobs -l "${job_id}" 2>/dev/null | awk -F' {2,}' '{print $NF}' | tail -n 1)
# If we found it, wrap it so you know it's a resumed job
[[ -n "${r_cmd}" ]] && d_cmd="${d_cmd} [${r_cmd}]"
fi
[[ "${d_cmd}" == "history -a" ]] && d_cmd="idle"
printf "\033]0;%s %s@%s(%s)(%sR/%sS):%s (%s)\007" \
"${venv}" \
"${USER}" \
"${HOSTNAME%%.*}" \
"${ps1_tty}" \
"${jr}" \
"${js}" \
"${d_pwd}" \
"${d_cmd}"
fi
# Important to return success, lest the debug trap swallows our command!
return 0
}
# Just to be sure the debug trap stays hungry
trap '__ps1_preCommand || true' DEBUG
# Now for the main event!
__prompt_command() {
# Save last exit code
local PS1_exit=$?
local PS1_dirList PS1_L0 PS1_L1 PS1_L2 PS1_L3
# Get dir listing, if we want it
if [[ -n "${PS1_getDirList}" ]]; then
PS1_dirList=$(\ls -Al --si)
fi
# PS1 Line 1
# Exit code of previous command
PS1_L1=" ╚═${PS1_Op}${PS1_exit}${PS1_Cl}"
# Name of the lion using this term
PS1_L1+="══${PS1_Op}$(__ps1_utf8 🦁 'U:')\u${PS1_Cl}"
# The TTY of this term
PS1_L1+="══${PS1_Op}$(__ps1_utf8 📺 'T:')$(__ps1_tty)${PS1_Cl}"
# The host of this term
PS1_L1+="══${PS1_Op}$(__ps1_utf8 💻 'H:')\h${PS1_Cl}"
# The uptime of this host
PS1_L1+="══${PS1_Op}$(__ps1_utf8 ⚡ 'Up:')$(__ps1_uptime)${PS1_Cl}"
# Line padding and eternal flame
PS1_L1+="$(__pad 1_L1)═╡$(__ps1_utf8 🔥 'on I burn')╞══╗\n"
# PS1 Line 2
# The length of our command history, global and for this term
PS1_L2="╔═${PS1_Op}\!:\#${PS1_Cl}"
# Background jobs, running and sleeping
PS1_L2+="══${PS1_Op}$(__ps1_utf8 🏃 'R:')$(__ps1_jr)/$(__ps1_utf8 💤 'S:')$(__ps1_js)${PS1_Cl}"
# Current Working Directory stat's...
PS1_L2+="══${PS1_Op}$(__ps1_utf8 📂 'cwd:')\W($(__ps1_dirSize)B"
# ...№ files, normal and hidden...
PS1_L2+=" $(__ps1_utf8 📄 -)$(__ps1_files).$(__ps1_hiddenFiles)"
# ...№ executables...
PS1_L2+=" $(__ps1_utf8 💾 x)$(__ps1_execs)"
# ...№ directories, normal and hidden...
PS1_L2+=" $(__ps1_utf8 📁 d)$(__ps1_dirs).$(__ps1_hiddenDirs)"
# ...№ links...
PS1_L2+=" $(__ps1_utf8 🔗 l)$(__ps1_links)"
# ...№ special files
PS1_L2+=" $(__ps1_utf8 📠 s)$(__ps1_spec))${PS1_Cl}"
# Line padding
PS1_L2+="$(__pad 1_L2)╝\n"
# PS1 Line 3
# If we're in a python virtual environment, print its name
PS1_L3="╚╦$(__ps1_getVirtualenv)═$(__ps1_utf8 ╾ '>')$(__ps1_utf8 💲 '$') "
# shellcheck disable=SC2016
case "${PS1_color}" in
yes)
if [[ "${HAS_FANCY_FONT}" == yes ]]; then {
PS0='$(lolcat-c '${PS1_lc_opts[*]}' <<< "╾╨────┤Program running $(__ps1_utf8 🗓️) \d $(__ps1_utf8time "$(date +"%I")" "$(date +"%M")")\D{}├$(printf %$((COLUMNS-54))s | sed "s/ /─/g")╮")'
PS1_L0='$(lolcat-c '${PS1_lc_opts[*]}' <<< "╾╥────┤Program finished $(__ps1_utf8 🗓️) \d $(__ps1_utf8time "$(date +"%I")" "$(date +"%M")")\D{}├$(printf %$((COLUMNS-54))s | sed "s/ /─/g")╯")'
}
else {
PS0='$(lolcat-c '${PS1_lc_opts[*]}' <<< "╾╨────┤Program running \d \D{}├$(printf %$((COLUMNS-49))s | sed "s/ /─/g")╮")'
PS1_L0='$(lolcat-c '${PS1_lc_opts[*]}' <<< "╾╥────┤Program finished \d \D{}├$(printf %$((COLUMNS-49))s | sed "s/ /─/g")╯")'
}; fi
PS1='$(lolcat-c '${PS1_lc_opts[*]}' <<< "'${PS1_L0}${PS1_L1}${PS1_L2}${PS1_L3}'" | sed -z "s/\(.*\)\\n/\1/" | __ps1_color_wrap_non_printing)'
PS2="$(lolcat-c "${PS1_lc_opts[@]}" <<<" ╠══$(__ps1_utf8 ╾ ┈) " | sed -z "s/\(.*\)\\n/\1/" | __ps1_color_wrap_non_printing)"
;;
*)
if [[ "${HAS_FANCY_FONT}" == yes ]]; then {
PS0="╾╨────┤Program running $(__ps1_utf8 "🗓️ ") \d $(__ps1_utf8time "$(date +"%I")" "$(date +"%M")") \D{}├$(printf %$((COLUMNS - 62))s | sed "s/ /─/g")╮\n"
PS1_L0="╾╥────┤Program finished $(__ps1_utf8 "🗓️ ") \d $(__ps1_utf8time "$(date +"%I")" "$(date +"%M")") \D{}├$(printf %$((COLUMNS - 62))s | sed "s/ /─/g")╯\n"
}
else {
# shellcheck disable=SC2034
PS0="╾╨────┤Program running \d \D{}├$(printf %$((COLUMNS - 49))s | sed "s/ /─/g")╮"
PS1_L0="╾╥────┤Program finished \d \D{}├$(printf %$((COLUMNS - 49))s | sed "s/ /─/g")╯"
}; fi
PS1="${PS1_L0}${PS1_L1}${PS1_L2}${PS1_L3}"
PS2=" ╠══$(__ps1_utf8 ╾ ┈) "
;;
esac
if tput tsl >/dev/null 2>&1; then
PS1="\[\e]0;$(__ps1_getVirtualenv) \u@\h($(__ps1_tty))($(__ps1_jr)R/$(__ps1_js)S):\w (idle)\a\]${PS1}"
fi
}
PROMPT_COMMAND="__prompt_command${PROMPT_COMMAND:+; ${PROMPT_COMMAND}}"
# vim:noet:sts=4:sw=4:ts=4