-
Notifications
You must be signed in to change notification settings - Fork 0
/
.bash_prompt
270 lines (242 loc) · 7.36 KB
/
.bash_prompt
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
# A lightweight (single file), cross-compatible (bash v3/v4,
# MacOS, Linux), bash prompt with basic theming support. To
# install, just source this file from your .bashrc with, so
# it is only loaded for an interactive session:
#
# if [[ -n $PS1 && -f ~/.bash_prompt ]]; then
# . ~/.bash_prompt
# ps1_colorful_theme
# fi
# Color definitions
c_normal="\001$(tput sgr0)\002"
c_black="\001$(tput setaf 0)\002"
c_red="\001$(tput setaf 1)\002"
c_green="\001$(tput setaf 2)\002"
c_yellow="\001$(tput setaf 3)\002"
c_blue="\001$(tput setaf 4)\002"
c_magenta="\001$(tput setaf 5)\002"
c_cyan="\001$(tput setaf 6)\002"
c_white="\001$(tput setaf 7)\002"
c_bblack="\001$(tput setaf 8)\002"
c_bwhite="\001$(tput setaf 15)\002"
# Dark theme where prompt fades to background in favor of the
# actual command executed and its output.
function ps1_dark_theme {
c_token="$c_bblack"
c_time="$c_bblack"
c_dur_exit_zero="$c_bblack"
c_dur_exit_nonzero="$c_red"
c_user_root="$c_red"
c_user_nonroot="$c_bblack"
c_hostname="$c_bblack"
c_dir_path="$c_bblack"
c_git_branch="$c_bblack"
c_shell_jobs="$c_bblack"
c_text_input="$c_blue"
setup_ps1
}
function ps1_colorful_theme {
c_token="$c_bblack"
c_time="$c_bwhite"
c_dur_exit_zero="$c_green"
c_dur_exit_nonzero="$c_red"
c_user_root="$c_red"
c_user_nonroot="$c_magenta"
c_hostname="$c_yellow"
c_dir_path="$c_cyan"
c_git_branch="$c_magenta"
c_shell_jobs="$c_red"
c_text_input="$c_blue"
setup_ps1
}
function ps1_white_theme {
c_token="$c_bblack"
c_time="$c_bwhite"
c_dur_exit_zero="$c_bwhite"
c_dur_exit_nonzero="$c_red"
c_user_root="$c_red"
c_user_nonroot="$c_bwhite"
c_hostname="$c_bwhite"
c_dir_path="$c_bwhite"
c_git_branch="$c_bwhite"
c_shell_jobs="$c_bwhite"
c_text_input="$c_blue"
setup_ps1
}
function ps1_blue_theme {
c_token="$c_blue"
c_time="$c_blue"
c_dur_exit_zero="$c_blue"
c_dur_exit_nonzero="$c_yellow"
c_user_root="$c_yellow"
c_user_nonroot="$c_blue"
c_hostname="$c_blue"
c_dir_path="$c_blue"
c_git_branch="$c_blue"
c_shell_jobs="$c_blue"
c_text_input="$c_red"
setup_ps1
}
function ps1_green_theme {
c_token="$c_green"
c_time="$c_green"
c_dur_exit_zero="$c_green"
c_dur_exit_nonzero="$c_red"
c_user_root="$c_red"
c_user_nonroot="$c_green"
c_hostname="$c_green"
c_dir_path="$c_green"
c_git_branch="$c_green"
c_shell_jobs="$c_green"
c_text_input="$c_yellow"
setup_ps1
}
function ps1_yellow_theme {
c_token="$c_yellow"
c_time="$c_yellow"
c_dur_exit_zero="$c_yellow"
c_dur_exit_nonzero="$c_red"
c_user_root="$c_red"
c_user_nonroot="$c_yellow"
c_hostname="$c_yellow"
c_dir_path="$c_yellow"
c_git_branch="$c_yellow"
c_shell_jobs="$c_yellow"
c_text_input="$c_blue"
setup_ps1
}
function ps1_red_theme {
c_token="$c_red"
c_time="$c_red"
c_dur_exit_zero="$c_red"
c_dur_exit_nonzero="$c_yellow"
c_user_root="$c_yellow"
c_user_nonroot="$c_red"
c_hostname="$c_red"
c_dir_path="$c_red"
c_git_branch="$c_red"
c_shell_jobs="$c_red"
c_text_input="$c_blue"
setup_ps1
}
function setup_ps1 {
# DEBUG trap is invoked before the shell command is invoked.
# We need to do two things here: 1) reset the color so the cmd
# output not impacted if we opted to change it in our PS1, and
# 2) record the number of seconds so we can compute elapsed
# time in timer_stop.
if [[ ! $(trap -p DEBUG) = *timer_start* ]]; then
trap 'printf $c_normal; timer_start' DEBUG
fi
# PROMPT_COMMAND is invoked after a shell command has completed
# but immediately before PS1 is printed. This allows us to
# compute the elapsed time of the command as we marked the
# start using the DEBUG trap.
if [[ ! $PROMPT_COMMAND = *timer_stop* ]]; then
if [[ -z $PROMPT_COMMAND ]]; then
PROMPT_COMMAND="timer_stop"
else
PROMPT_COMMAND="$PROMPT_COMMAND; timer_stop"
fi
fi
# Start with an empty prompt
PS1=""
# First part of the line drawing
PS1+="\n${c_token}┌ "
# HH:MM Time of day in 24-hour format
PS1+="${c_time}\A "
# [0s] Duration of last command; color reflects exit status
PS1+="\$(wrap '[] ' \$(color_timer $c_dur_exit_zero $c_dur_exit_nonzero))"
# <username@host> Color of username changes if root
PS1+="${c_token}<"
PS1+="\$(color_user $c_user_nonroot $c_user_root)"
PS1+="${c_token}@"
PS1+="${c_hostname}\h"
PS1+="${c_token}> "
# [.../dir/dir/dir] Current path trimmed (compat w/ bash3 and bash4)
PS1+="\$(wrap '[] ' \$(color_dirtrim 3 $c_dir_path))"
# (master) Git branch name
PS1+="\$(wrap '() ' \$(color_branch $c_git_branch))"
# <N> Number of jobs running and sleeping
PS1+="\$(wrap '<> ' \$(color_jobs $c_shell_jobs))"
# Second part of the line drawing
PS1+="\n${c_token}└─ "
# Color our text input; cmd output is sent to c_normal in TRAP above
PS1+="${c_text_input}"
}
function timer_start {
# timer will already be set if a user is invoking a set
# of commands such as cmd1 && cmd2. If we don't check, then
# we will not include the elapsed time of the first command.
timer=${timer:-$SECONDS}
}
function timer_stop {
timer_show=$(($SECONDS - $timer))
# We need to unset this as we use the existence of it to
# test whether or not multiple commands were executed in
# a manner such as cmd1 && cmd2.
unset timer
}
# Elapsed time for last command; colorize based on status.
# Pirst arg is success color, and second arg is failure color.
function color_timer {
local result=$? # Must capture before it is reset
local color=$1
if [[ $result -ne 0 ]]; then
color=$2
fi
printf "${color}${timer_show}s"
}
# Colorize username with first arg. If username is root, use
# the second arg as the color.
function color_user {
local color=$1
if [[ $USER = "root" ]]; then
local color="$2"
fi
printf "${color}${USER}"
}
# Colorize the number of running/sleeping jobs.
function color_jobs {
local color="$1"
local jobs=$(jobs -p | wc -l | tr -d '[:space:]')
if [[ $jobs -gt 0 ]]; then
printf "${color}${jobs}"
fi
}
# Colorize the current Git branch.
function color_branch {
local color=$1
local branch=$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
if [[ -n $branch ]]; then
printf "${color}${branch}"
fi
}
# Colorize the PWD, substituting tilde for $HOME, and trim to
# depth directories substituting excess with '...'. On newer
# versions of bash, you can use PROMPT_DIRTRIM, but this works
# with old school sed (no extended regexs) and bash3 which
# does not support PROMPT_DIRTERM.
function color_dirtrim {
local depth=$1
local color=$2
# Use only basic sed regex for compatibility across both
# MacOS and Linux. It makes it hard to read, but it does
# appear to work! Took me a while to get this working :-)
dirtrim=$(echo $PWD | sed -e "s%${HOME}%~%" -e "s%^~\{0,1\}\(/[^/]\{1,\}\)\{1,\}\(\(/[^/]\{1,\}\)\{${depth}\}\)$%...\2%")
printf "${color}${dirtrim}"
}
# Wrap text with tokens if text is not empty. The first arg
# must contain at least 2 characters. The first is used for
# the left token, and the rest are used for the right token.
# This allows the caller to insert a space following the
# wrapped text. By passing the space in here, it will only
# be printed if the wrapped text is not empty.
function wrap {
local beg_token="${1:0:1}"
local end_token="${1:1}"
local text="${@:2}"
if [[ -n $text ]]; then
printf "${c_token}${beg_token}${text}${c_token}${end_token}"
fi
}