Última actividad 1789532044

Customization of synth-shell for personal use

dartokloning's Avatar dartokloning revisó este gist 1789532043. Ir a la revisión

1 file changed, 52 insertions, 1 deletion

shell-prompt.sh

@@ -272,6 +272,53 @@ font_color_input="45"
272 272 background_input="none"
273 273 texteffect_input="bold"
274 274
275 + ##==============================================================================
276 + ## ROOT WARNING PALETTE
277 + ##==============================================================================
278 + # Jika shell berjalan sebagai root, pertahankan layout/informasi prompt,
279 + # tetapi gunakan warna warning agar sesi privileged langsung terlihat.
280 + if [ "${EUID:-$(id -u)}" -eq 0 ]; then
281 + font_color_user="white"
282 + background_user="red"
283 + texteffect_user="bold"
284 +
285 + font_color_host="white"
286 + background_host="light-red"
287 + texteffect_host="bold"
288 +
289 + font_color_pwd="black"
290 + background_pwd="yellow"
291 + texteffect_pwd="bold"
292 +
293 + font_color_git="white"
294 + background_git="red"
295 + texteffect_git="bold"
296 +
297 + font_color_pyenv="white"
298 + background_pyenv="light-red"
299 + texteffect_pyenv="bold"
300 +
301 + font_color_kube="black"
302 + background_kube="light-yellow"
303 + texteffect_kube="bold"
304 +
305 + font_color_tf="white"
306 + background_tf="red"
307 + texteffect_tf="bold"
308 +
309 + font_color_date="white"
310 + background_date="light-red"
311 + texteffect_date="bold"
312 +
313 + font_color_clock="white"
314 + background_clock="red"
315 + texteffect_clock="bold"
316 +
317 + font_color_input="light-red"
318 + background_input="none"
319 + texteffect_input="bold"
320 + fi
321 +
275 322 ##==============================================================================
276 323 ## EXTERNAL DEPENDENCIES
277 324 ##==============================================================================
@@ -590,7 +637,11 @@ prompt_command_hook()
590 637 local new_line_link_top="╭"
591 638 local new_line_link_bottom="╰>"
592 639 local prompt_command_separation="\n"
593 - local bash_symbol="\$"
640 + if [ "${EUID:-$(id -u)}" -eq 0 ]; then
641 + local bash_symbol="#"
642 + else
643 + local bash_symbol="\$"
644 + fi
594 645 else
595 646 local new_line_link_top=""
596 647 local new_line_link_bottom=""

dartokloning's Avatar dartokloning revisó este gist 1788256026. Ir a la revisión

1 file changed, 330 insertions, 394 deletions

shell-prompt.sh

@@ -17,145 +17,77 @@ get8bitCode()
17 17 {
18 18 CODE=$1
19 19 case $CODE in
20 - default)
21 - echo 9
22 - ;;
23 - none)
24 - echo 9
25 - ;;
26 - black)
27 - echo 0
28 - ;;
29 - red)
30 - echo 1
31 - ;;
32 - green)
33 - echo 2
34 - ;;
35 - yellow)
36 - echo 3
37 - ;;
38 - blue)
39 - echo 4
40 - ;;
41 - magenta|purple|pink)
42 - echo 5
43 - ;;
44 - cyan)
45 - echo 6
46 - ;;
47 - light-gray)
48 - echo 7
49 - ;;
50 - dark-gray)
51 - echo 60
52 - ;;
53 - light-red)
54 - echo 61
55 - ;;
56 - light-green)
57 - echo 62
58 - ;;
59 - light-yellow)
60 - echo 63
61 - ;;
62 - light-blue)
63 - echo 64
64 - ;;
65 - light-magenta|light-purple)
66 - echo 65
67 - ;;
68 - light-cyan)
69 - echo 66
70 - ;;
71 - white)
72 - echo 67
73 - ;;
74 - *)
75 - echo 0
20 + default) echo 9 ;;
21 + none) echo 9 ;;
22 + black) echo 0 ;;
23 + red) echo 1 ;;
24 + green) echo 2 ;;
25 + yellow) echo 3 ;;
26 + blue) echo 4 ;;
27 + magenta|purple|pink) echo 5 ;;
28 + cyan) echo 6 ;;
29 + light-gray) echo 7 ;;
30 + dark-gray) echo 60 ;;
31 + light-red) echo 61 ;;
32 + light-green) echo 62 ;;
33 + light-yellow) echo 63 ;;
34 + light-blue) echo 64 ;;
35 + light-magenta|light-purple) echo 65 ;;
36 + light-cyan) echo 66 ;;
37 + white) echo 67 ;;
38 + *) echo 0 ;;
76 39 esac
77 40 }
78 - ##------------------------------------------------------------------------------
79 - ##
41 +
80 42 getColorCode()
81 43 {
82 44 COLOR=$1
83 - ## Check if color is a 256-color code
84 - if [ $COLOR -eq $COLOR ] 2> /dev/null; then
85 - if [ $COLOR -gt 0 -a $COLOR -lt 256 ]; then
45 + if [ "$COLOR" -eq "$COLOR" ] 2>/dev/null; then
46 + if [ "$COLOR" -gt 0 ] && [ "$COLOR" -lt 256 ]; then
86 47 echo "38;5;$COLOR"
87 48 else
88 49 echo 0
89 50 fi
90 - ## Or if color key-workd
91 51 else
92 - BITCODE=$(get8bitCode $COLOR)
93 - COLORCODE=$(($BITCODE + 30))
94 - echo $COLORCODE
52 + BITCODE=$(get8bitCode "$COLOR")
53 + COLORCODE=$((BITCODE + 30))
54 + echo "$COLORCODE"
95 55 fi
96 56 }
97 - ##------------------------------------------------------------------------------
98 - ##
57 +
99 58 getBackgroundCode()
100 59 {
101 60 COLOR=$1
102 - ## Check if color is a 256-color code
103 - if [ $COLOR -eq $COLOR ] 2> /dev/null; then
104 - if [ $COLOR -gt 0 -a $COLOR -lt 256 ]; then
61 + if [ "$COLOR" -eq "$COLOR" ] 2>/dev/null; then
62 + if [ "$COLOR" -gt 0 ] && [ "$COLOR" -lt 256 ]; then
105 63 echo "48;5;$COLOR"
106 64 else
107 65 echo 0
108 66 fi
109 - ## Or if color key-workd
110 67 else
111 - BITCODE=$(get8bitCode $COLOR)
112 - COLORCODE=$(($BITCODE + 40))
113 - echo $COLORCODE
68 + BITCODE=$(get8bitCode "$COLOR")
69 + COLORCODE=$((BITCODE + 40))
70 + echo "$COLORCODE"
114 71 fi
115 72 }
116 - ##------------------------------------------------------------------------------
117 - ##
73 +
118 74 getEffectCode()
119 75 {
120 76 EFFECT=$1
121 77 NONE=0
122 78 case $EFFECT in
123 - none)
124 - echo $NONE
125 - ;;
126 - default)
127 - echo $NONE
128 - ;;
129 - bold)
130 - echo 1
131 - ;;
132 - bright)
133 - echo 1
134 - ;;
135 - dim)
136 - echo 2
137 - ;;
138 - underline)
139 - echo 4
140 - ;;
141 - blink)
142 - echo 5
143 - ;;
144 - reverse)
145 - echo 7
146 - ;;
147 - hidden)
148 - echo 8
149 - ;;
150 - strikeout)
151 - echo 9
152 - ;;
153 - *)
154 - echo $NONE
79 + none|default) echo "$NONE" ;;
80 + bold|bright) echo 1 ;;
81 + dim) echo 2 ;;
82 + underline) echo 4 ;;
83 + blink) echo 5 ;;
84 + reverse) echo 7 ;;
85 + hidden) echo 8 ;;
86 + strikeout) echo 9 ;;
87 + *) echo "$NONE" ;;
155 88 esac
156 89 }
157 - ##------------------------------------------------------------------------------
158 - ##
90 +
159 91 getFormattingSequence()
160 92 {
161 93 START='\e[0;'
@@ -163,114 +95,114 @@ getFormattingSequence()
163 95 END='m'
164 96 echo -n "$START$MIDLE$END"
165 97 }
98 +
166 99 ##==================================================================================================
167 100 ## AUX
168 101 ##==================================================================================================
169 102 applyCodeToText()
170 103 {
171 - local RESET=$(getFormattingSequence $(getEffectCode none))
104 + local RESET
105 + RESET=$(getFormattingSequence "$(getEffectCode none)")
172 106 TEXT=$1
173 107 CODE=$2
174 108 echo -n "$CODE$TEXT$RESET"
175 109 }
110 +
176 111 ##==================================================================================================
177 112 ## MAIN FUNCTIONS
178 113 ##==================================================================================================
179 - ##------------------------------------------------------------------------------
180 - ##
181 114 getFormatCode()
182 115 {
183 - local RESET=$(getFormattingSequence $(getEffectCode none))
184 - ## NO ARGUMENT PROVIDED
116 + local RESET
117 + RESET=$(getFormattingSequence "$(getEffectCode none)")
118 +
185 119 if [ "$#" -eq 0 ]; then
186 120 echo -n "$RESET"
187 - ## 1 ARGUMENT -> ASSUME TEXT COLOR
188 121 elif [ "$#" -eq 1 ]; then
189 - TEXT_COLOR=$(getFormattingSequence $(getColorCode $1))
122 + TEXT_COLOR=$(getFormattingSequence "$(getColorCode "$1")")
190 123 echo -n "$TEXT_COLOR"
191 - ## ARGUMENTS PROVIDED
192 124 else
193 125 FORMAT=""
194 126 while [ "$1" != "" ]; do
195 - ## PROCESS ARGUMENTS
196 127 TYPE=$1
197 128 ARGUMENT=$2
198 129 case $TYPE in
199 - -c)
200 - CODE=$(getColorCode $ARGUMENT)
201 - ;;
202 - -b)
203 - CODE=$(getBackgroundCode $ARGUMENT)
204 - ;;
205 - -e)
206 - CODE=$(getEffectCode $ARGUMENT)
207 - ;;
208 - *)
209 - CODE=""
130 + -c) CODE=$(getColorCode "$ARGUMENT") ;;
131 + -b) CODE=$(getBackgroundCode "$ARGUMENT") ;;
132 + -e) CODE=$(getEffectCode "$ARGUMENT") ;;
133 + *) CODE="" ;;
210 134 esac
211 - ## ADD CODE SEPARATOR IF NEEDED
135 +
212 136 if [ "$FORMAT" != "" ]; then
213 137 FORMAT="$FORMAT;"
214 138 fi
215 - ## APPEND CODE
216 139 FORMAT="$FORMAT$CODE"
217 - # Remove arguments from stack
218 140 shift
219 141 shift
220 142 done
221 - ## APPLY FORMAT TO TEXT
222 - FORMAT_CODE=$(getFormattingSequence $FORMAT)
143 +
144 + FORMAT_CODE=$(getFormattingSequence "$FORMAT")
223 145 echo -n "${FORMAT_CODE}"
224 146 fi
225 147 }
226 - ##------------------------------------------------------------------------------
227 - ##
148 +
228 149 formatText()
229 150 {
230 - local RESET=$(getFormattingSequence $(getEffectCode none))
231 - ## NO ARGUMENT PROVIDED
151 + local RESET
152 + RESET=$(getFormattingSequence "$(getEffectCode none)")
153 +
232 154 if [ "$#" -eq 0 ]; then
233 155 echo -n "${RESET}"
234 - ## ONLY A STRING PROVIDED -> Append reset sequence
235 156 elif [ "$#" -eq 1 ]; then
236 157 TEXT=$1
237 158 echo -n "${TEXT}${RESET}"
238 - ## ARGUMENTS PROVIDED
239 159 else
240 160 TEXT=$1
241 161 FORMAT_CODE=$(getFormatCode "${@:2}")
242 162 applyCodeToText "$TEXT" "$FORMAT_CODE"
243 163 fi
244 164 }
245 - ##------------------------------------------------------------------------------
246 - ##
165 +
247 166 removeColorCodes()
248 167 {
249 - printf "$1" | sed 's/\x1b\[[0-9;]*m//g'
168 + printf "%s" "$1" | sed 's/\x1b\[[0-9;]*m//g'
250 169 }
251 170
252 171 ##==============================================================================
253 172 ## MAIN FORMAT
254 173 ##==============================================================================
255 174 format="USER HOST PWD GIT PYENV TF KUBE DATE CLOCK"
256 - separator_char='\uE0B0' # Separation character, '\uE0B0'=triangle
257 - separator_padding_left='' # Add char or string to the left of the separator
258 - separator_padding_right='' # Add char or string to the right of the separator
259 - segment_padding=' ' # Add char or string around segment text
260 - enable_vertical_padding=true # Add extra new line over prompt
261 - enable_command_on_new_line=true # Add new line between prompt and command
175 + separator_char='\uE0B0'
176 + separator_padding_left=''
177 + separator_padding_right=''
178 + segment_padding=' '
179 + enable_vertical_padding=true
180 + enable_command_on_new_line=true
181 +
182 + # Nerd Font icons.
183 + # Font hanya perlu tersedia pada terminal/client yang merender sesi SSH
184 + # (misalnya Termius). Tidak perlu install Nerd Font di setiap server Debian.
185 + icon_user=$'\uf007'
186 + icon_folder=$'\uf07b'
187 + icon_calendar=$'\uf073'
188 + icon_clock=$'\uf017'
189 + icon_debian=$'\ue77d'
190 + icon_linux=$'\uf17c'
191 +
262 192 ##==============================================================================
263 193 ## USER
264 194 ##==============================================================================
265 195 font_color_user="black"
266 196 background_user="green"
267 197 texteffect_user="bold"
198 +
268 199 ##==============================================================================
269 200 ## HOST
270 201 ##==============================================================================
271 202 font_color_host="white"
272 203 background_host="light-blue"
273 204 texteffect_host="bold"
205 +
274 206 ##==============================================================================
275 207 ## PWD (working dir)
276 208 ##==============================================================================
@@ -278,6 +210,7 @@ font_color_pwd="dark-gray"
278 210 background_pwd="white"
279 211 texteffect_pwd="bold"
280 212 max_pwd_char="25"
213 +
281 214 ##==============================================================================
282 215 ## GIT
283 216 ##==============================================================================
@@ -293,25 +226,29 @@ git_symbol_dirty_unpushed=' ◔ △'
293 226 git_symbol_dirty_unpulled=' ◔ ▽'
294 227 git_symbol_dirty_unpushedunpulled=' ◔ ◇'
295 228 git_symbol_stash='🗎'
296 - git_update_period_minutes=15 # Use -1 to disable automatic updates
229 + git_update_period_minutes=15
230 +
297 231 ##==============================================================================
298 232 ## PYENV
299 233 ##==============================================================================
300 234 font_color_pyenv="white"
301 235 background_pyenv="blue"
302 236 texteffect_pyenv="bold"
237 +
303 238 ##==============================================================================
304 239 ## KUBERNETES
305 240 ##==============================================================================
306 241 font_color_kube="white"
307 242 background_kube="purple"
308 243 texteffect_kube="bold"
244 +
309 245 ##==============================================================================
310 246 ## TERRAFORM WORKSPACE
311 247 ##==============================================================================
312 248 font_color_tf="purple"
313 249 background_tf="light-purple"
314 250 texteffect_tf="bold"
251 +
315 252 ##==============================================================================
316 253 ## CLOCK
317 254 ##==============================================================================
@@ -319,6 +256,7 @@ font_color_clock="white"
319 256 background_clock="black"
320 257 texteffect_clock="bold"
321 258 clock_format="%H:%M:%S"
259 +
322 260 ##==============================================================================
323 261 ## DATE
324 262 ##==============================================================================
@@ -326,6 +264,7 @@ font_color_date="white"
326 264 background_date="light-purple"
327 265 texteffect_date="bold"
328 266 date_format="${hari}, %d ${bulan} %Y"
267 +
329 268 ##==============================================================================
330 269 ## INPUT (user typed command)
331 270 ##==============================================================================
@@ -336,221 +275,222 @@ texteffect_input="bold"
336 275 ##==============================================================================
337 276 ## EXTERNAL DEPENDENCIES
338 277 ##==============================================================================
339 - [ "$(type -t include)" != 'function' ]&&{ include(){ { [ -z "$_IR" ]&&_IR="$PWD"&&cd "$(dirname "${BASH_SOURCE[0]}")"&&include "$1"&&cd "$_IR"&&unset _IR;}||{ local d="$PWD"&&cd "$(dirname "$PWD/$1")"&&. "$(basename "$1")"&&cd "$d";}||{ echo "Include failed $PWD->$1"&&exit 1;};};}
278 + [ "$(type -t include)" != 'function' ] && {
279 + include() {
280 + {
281 + [ -z "$_IR" ] &&
282 + _IR="$PWD" &&
283 + cd "$(dirname "${BASH_SOURCE[0]}")" &&
284 + include "$1" &&
285 + cd "$_IR" &&
286 + unset _IR
287 + } || {
288 + local d="$PWD" &&
289 + cd "$(dirname "$PWD/$1")" &&
290 + . "$(basename "$1")" &&
291 + cd "$d"
292 + } || {
293 + echo "Include failed $PWD->$1" &&
294 + exit 1
295 + }
296 + }
297 + }
298 +
340 299 synth_shell_prompt()
341 300 {
342 301 ##==============================================================================
343 302 ## FUNCTIONS
344 303 ##==============================================================================
345 - ##------------------------------------------------------------------------------
346 - ##
347 - ## Returns current git branch for current directory, if (and only if)
348 - ## the current directory is part of a git repository, and git is installed.
349 - ##
350 - ## In addition, it adds a symbol to indicate the state of the repository.
351 - ## By default, these symbols and their meaning are (set globally):
352 - ##
353 - ## UPSTREAM NO CHANGE DIRTY
354 - ## up to date SSP_GIT_SYNCED SSP_GIT_DIRTY
355 - ## ahead SSP_GIT_AHEAD SSP_GIT_DIRTY_AHEAD
356 - ## behind SSP_GIT_BEHIND SSP_GIT_DIRTY_BEHIND
357 - ## diverged SSP_GIT_DIVERGED SSP_GIT_DIRTY_DIVERGED
358 - ##
359 - ## Returns an empty string otherwise.
360 - ##
361 - ## Inspired by twolfson's sexy-bash-prompt:
362 - ## https://github.com/twolfson/sexy-bash-prompt
363 - ##
304 +
305 + getOSIcon()
306 + {
307 + if [ -r /etc/os-release ]; then
308 + local os_id
309 + os_id=$(. /etc/os-release; printf '%s' "${ID:-}")
310 +
311 + case "$os_id" in
312 + debian)
313 + printf '%s' "$SSP_ICON_DEBIAN"
314 + ;;
315 + *)
316 + printf '%s' "$SSP_ICON_LINUX"
317 + ;;
318 + esac
319 + else
320 + printf '%s' "$SSP_ICON_LINUX"
321 + fi
322 + }
323 +
364 324 getGitBranch()
365 325 {
366 - ## Check if git is installed, otherwise skip this function so as to not
367 - ## generate any errors.
368 - if ! ( which git > /dev/null 2>&1 ); then
369 - echo ""
370 - return
371 - fi
372 - ## Check if in a git respository, otherwise skip since there is no info
373 - ## to print.
374 - local branch=$(git branch 2> /dev/null |\
375 - sed -n '/^[^*]/d;s/*\s*\(.*\)/\1/p')
376 - if [[ -z "$branch" ]]; then
377 - echo ""
378 - return
379 - fi
380 - ## Fetch branch, required to later determine if the local dir is up to date.
381 - ## Because doing so for every terminal prompt can be slow, the script will
382 - ## do so only if its globaly enabled (see config) and only periodically in
383 - ## the background.
384 - if [ "$SSP_GIT_UPDATE_PERIOD_MINUTES" -ge 0 ]; then
385 - ## Find .git, i.e., the root of the repository.
386 - local d="$PWD"
387 - local max_lvls=25
388 - while [ ! -e "./.git" -a $max_lvls -gt 0 ]; do
389 - cd .. # Go up 1 level
390 - max_lvls=$((max_lvls - 1))
391 - done
392 - local dot_git="${PWD}/.git"
393 - cd "$d"
394 - ## Check if submodule.
395 - if [ -f "$dot_git" ]; then
396 - local dot_git=$(cat $dot_git | grep 'gitdir' | sed 's/gitdir:\ //g')
397 - fi
398 - ## Get timestamp.
399 - if [ -d "$dot_git" -a -e "${dot_git}/FETCH_HEAD" ]; then
400 - local git_last_update=$(stat -c "%Y" "${dot_git}/FETCH_HEAD")
401 - fi
402 - ## Update if it's time to do so.
403 - if [ ! -z $git_last_update ]; then
404 - local current_timestamp=$(date +%s)
405 - local elapsed_minutes=$(((current_timestamp-git_last_update)/60))
406 - if [ "$elapsed_minutes" -ge "$SSP_GIT_UPDATE_PERIOD_MINUTES" ]; then
407 - git fetch --recurse-submodules > /dev/null 2>&1 &
408 - fi
409 - fi
410 - fi
411 - ## Get repository status.
412 - ## This information contains whether the current branch is ahead, behind or
413 - ## diverged (ahead & behind), as well as whether any file has been modified
414 - ## locally (is dirty).
415 - ## @note The repository must be fetched for this information to be accurate.
416 - ## @note The following git flags are used:
417 - ## --porcelain: script friendly output.
418 - ## -b: show branch tracking info.
419 - ## -u no: do not list untracked/dirty files.
420 - local is_dirty=false &&\
421 - [[ -n "$(git status --porcelain)" ]] &&\
422 - is_dirty=true
423 - local is_ahead=false &&\
424 - [[ "$(git status --porcelain -u no -b)" == *"ahead"* ]] &&\
425 - is_ahead=true
426 - local is_behind=false &&\
427 - [[ "$(git status --porcelain -u no -b)" == *"behind"* ]] &&\
428 - is_behind=true
429 - ## Determine symbol to show in prompt according to git status.
430 - if $is_dirty && $is_ahead && $is_behind; then
431 - local symbol=$SSP_GIT_DIRTY_DIVERGED
432 - elif $is_dirty && $is_ahead; then
433 - local symbol=$SSP_GIT_DIRTY_AHEAD
434 - elif $is_dirty && $is_behind; then
435 - local symbol=$SSP_GIT_DIRTY_BEHIND
436 - elif $is_dirty; then
437 - local symbol=$SSP_GIT_DIRTY
438 - elif $is_ahead && $is_behind; then
439 - local symbol=$SSP_GIT_DIVERGED
440 - elif $is_ahead; then
441 - local symbol=$SSP_GIT_AHEAD
442 - elif $is_behind; then
443 - local symbol=$SSP_GIT_BEHIND
444 - else
445 - local symbol=$SSP_GIT_SYNCED
446 - fi
447 - ## Get commit tag (if any).
448 - [[ -n "$(git tag --points-at HEAD)" ]] &&\
449 - local tag=" $(git tag --points-at HEAD)" || local tag=""
450 - ## Get stash count (if any).
451 - local git_stash=""
452 - local stashed_elements=$(git stash list 2> /dev/null | wc -l)
453 - if [ "$stashed_elements" -gt 0 ]; then
454 - git_stash=" ${stashed_elements}${SSP_GIT_STASH}"
455 - fi
456 - ## Return assembled prompt segmet with git info.
457 - echo "${branch}$symbol${git_stash}${tag}"
326 + if ! command -v git >/dev/null 2>&1; then
327 + echo ""
328 + return
329 + fi
330 +
331 + local branch
332 + branch=$(git branch 2>/dev/null | sed -n '/^[^*]/d;s/*\s*\(.*\)/\1/p')
333 + if [[ -z "$branch" ]]; then
334 + echo ""
335 + return
336 + fi
337 +
338 + if [ "$SSP_GIT_UPDATE_PERIOD_MINUTES" -ge 0 ]; then
339 + local d="$PWD"
340 + local max_lvls=25
341 +
342 + while [ ! -e "./.git" ] && [ "$max_lvls" -gt 0 ]; do
343 + cd ..
344 + max_lvls=$((max_lvls - 1))
345 + done
346 +
347 + local dot_git="${PWD}/.git"
348 + cd "$d" || return
349 +
350 + if [ -f "$dot_git" ]; then
351 + dot_git=$(grep 'gitdir' "$dot_git" | sed 's/gitdir:\ //g')
352 + fi
353 +
354 + local git_last_update=""
355 + if [ -d "$dot_git" ] && [ -e "${dot_git}/FETCH_HEAD" ]; then
356 + git_last_update=$(stat -c "%Y" "${dot_git}/FETCH_HEAD")
357 + fi
358 +
359 + if [ -n "$git_last_update" ]; then
360 + local current_timestamp
361 + local elapsed_minutes
362 + current_timestamp=$(date +%s)
363 + elapsed_minutes=$(((current_timestamp-git_last_update)/60))
364 +
365 + if [ "$elapsed_minutes" -ge "$SSP_GIT_UPDATE_PERIOD_MINUTES" ]; then
366 + git fetch --recurse-submodules >/dev/null 2>&1 &
367 + fi
368 + fi
369 + fi
370 +
371 + local is_dirty=false
372 + [[ -n "$(git status --porcelain 2>/dev/null)" ]] && is_dirty=true
373 +
374 + local is_ahead=false
375 + [[ "$(git status --porcelain -u no -b 2>/dev/null)" == *"ahead"* ]] && is_ahead=true
376 +
377 + local is_behind=false
378 + [[ "$(git status --porcelain -u no -b 2>/dev/null)" == *"behind"* ]] && is_behind=true
379 +
380 + local symbol
381 + if $is_dirty && $is_ahead && $is_behind; then
382 + symbol=$SSP_GIT_DIRTY_DIVERGED
383 + elif $is_dirty && $is_ahead; then
384 + symbol=$SSP_GIT_DIRTY_AHEAD
385 + elif $is_dirty && $is_behind; then
386 + symbol=$SSP_GIT_DIRTY_BEHIND
387 + elif $is_dirty; then
388 + symbol=$SSP_GIT_DIRTY
389 + elif $is_ahead && $is_behind; then
390 + symbol=$SSP_GIT_DIVERGED
391 + elif $is_ahead; then
392 + symbol=$SSP_GIT_AHEAD
393 + elif $is_behind; then
394 + symbol=$SSP_GIT_BEHIND
395 + else
396 + symbol=$SSP_GIT_SYNCED
397 + fi
398 +
399 + local tag=""
400 + if [[ -n "$(git tag --points-at HEAD 2>/dev/null)" ]]; then
401 + tag=" $(git tag --points-at HEAD 2>/dev/null)"
402 + fi
403 +
404 + local git_stash=""
405 + local stashed_elements
406 + stashed_elements=$(git stash list 2>/dev/null | wc -l)
407 +
408 + if [ "$stashed_elements" -gt 0 ]; then
409 + git_stash=" ${stashed_elements}${SSP_GIT_STASH}"
410 + fi
411 +
412 + echo "${branch}${symbol}${git_stash}${tag}"
458 413 }
459 - ##------------------------------------------------------------------------------
460 - ##
461 - ##
414 +
462 415 getTerraform()
463 416 {
464 - ## Check if terraform is installed, otherwise skip this function.
465 - if ! ( which terraform > /dev/null 2>&1 ); then
466 - echo ""
467 - return
468 - fi
469 - ## Check if we are in a terraform directory, otherwise skip.
470 - if [ ! -d .terraform ]; then
471 - echo ""
472 - return
473 - fi
474 - ## Get the terraform workspace
475 - local tf="$(terraform workspace show 2> /dev/null | tr -d '\n')"
476 - echo "$tf"
417 + if ! command -v terraform >/dev/null 2>&1; then
418 + echo ""
419 + return
420 + fi
421 +
422 + if [ ! -d .terraform ]; then
423 + echo ""
424 + return
425 + fi
426 +
427 + local tf
428 + tf="$(terraform workspace show 2>/dev/null | tr -d '\n')"
429 + echo "$tf"
477 430 }
478 - ##------------------------------------------------------------------------------
479 - ##
480 - ##
431 +
481 432 getPyenv()
482 433 {
483 - ## Conda environment
484 - if [ -n "$CONDA_DEFAULT_ENV" ]; then
434 + if [ -n "${CONDA_DEFAULT_ENV:-}" ]; then
485 435 echo "$CONDA_DEFAULT_ENV"
486 - ## Python virtual environment
487 436 elif [ -n "${VIRTUAL_ENV:-}" ]; then
488 - local regex='PS1=\"\((.*?)\)\s\$\{PS1'
489 - local pyenv=$(cat $VIRTUAL_ENV/bin/activate |\
490 - perl -n -e"/$regex/ && print \$1" 2> /dev/null)
491 - if [ -z "${pyenv}" ]; then
492 - local pyenv=$(basename ${VIRTUAL_ENV})
493 - fi
437 + local regex='PS1=\"\((.*?)\)\s\$\{PS1'
438 + local pyenv
439 + pyenv=$(perl -n -e"/$regex/ && print \$1" "$VIRTUAL_ENV/bin/activate" 2>/dev/null)
440 +
441 + if [ -z "${pyenv}" ]; then
442 + pyenv=$(basename "$VIRTUAL_ENV")
443 + fi
444 +
494 445 echo "$pyenv"
495 446 fi
496 447 }
497 - ##------------------------------------------------------------------------------
498 - ##
499 - ##
448 +
500 449 getKube()
501 450 {
502 - type kubectl &>/dev/null && \
503 - type yq &>/dev/null && \
451 + type kubectl &>/dev/null &&
452 + type yq &>/dev/null &&
504 453 echo -n "$(kubectl config view | yq '.contexts[].context.cluster |select(.contexts[].name == .current-context)' | head -n 1)"
505 454 }
506 - ##------------------------------------------------------------------------------
507 - ##
508 - ## Print each word of the propmpt, i.e., a small text acompanied by the
509 - ## separator character and formated with colors and background.
510 - ##
455 +
511 456 printSegment()
512 457 {
513 - ## GET PARAMETERS
514 458 local text=$1
515 459 local font_color=$2
516 460 local background_color=$3
517 - local next_background_color=$4 # needed for the separator, it participates in this and the next text segment
461 + local next_background_color=$4
518 462 local font_effect=$5
519 - ## COMPUTE COLOR FORMAT CODES
463 +
520 464 local no_color="\[$(getFormatCode -e reset)\]"
521 - local text_format="\[$(getFormatCode -c $font_color -b $background_color -e $font_effect)\]"
522 - local separator_format="\[$(getFormatCode -c $background_color -b $next_background_color)\]"
523 - ## GENERATE TEXT
465 + local text_format="\[$(getFormatCode -c "$font_color" -b "$background_color" -e "$font_effect")\]"
466 + local separator_format="\[$(getFormatCode -c "$background_color" -b "$next_background_color")\]"
467 +
524 468 printf "${text_format}${segment_padding}${text}${segment_padding}${separator_padding_left}${separator_format}${separator_char}${separator_padding_right}${no_color}"
525 469 }
526 - ##------------------------------------------------------------------------------
527 - ##
528 - ##
470 +
529 471 get_colors_for_element()
530 472 {
531 473 case $1 in
532 474 "USER") echo "${SSP_COLORS_USER[@]}" ;;
533 475 "HOST") echo "${SSP_COLORS_HOST[@]}" ;;
534 - "PWD") echo "${SSP_COLORS_PWD[@]}" ;;
535 - "GIT") echo "${SSP_COLORS_GIT[@]}" ;;
536 - "PYENV") echo "${SSP_COLORS_PYENV[@]}";;
537 - "KUBE") echo "${SSP_COLORS_KUBE[@]}";;
538 - "TF") echo "${SSP_COLORS_TF[@]}" ;;
539 - "CLOCK") echo "${SSP_COLORS_CLOCK[@]}";;
540 - "DATE") echo "${SSP_COLORS_DATE[@]}";;
541 - "INPUT") echo "${SSP_COLORS_INPUT[@]}";;
542 - *)
476 + "PWD") echo "${SSP_COLORS_PWD[@]}" ;;
477 + "GIT") echo "${SSP_COLORS_GIT[@]}" ;;
478 + "PYENV") echo "${SSP_COLORS_PYENV[@]}" ;;
479 + "KUBE") echo "${SSP_COLORS_KUBE[@]}" ;;
480 + "TF") echo "${SSP_COLORS_TF[@]}" ;;
481 + "CLOCK") echo "${SSP_COLORS_CLOCK[@]}" ;;
482 + "DATE") echo "${SSP_COLORS_DATE[@]}" ;;
483 + "INPUT") echo "${SSP_COLORS_INPUT[@]}" ;;
543 484 esac
544 485 }
545 - ##------------------------------------------------------------------------------
546 - ##
547 - ##
486 +
548 487 combine_elements()
549 488 {
550 489 local first=$1
551 490 local second=$2
552 - local colors_first=($(get_colors_for_element $first))
553 - local colors_second=($(get_colors_for_element $second))
491 + local colors_first=($(get_colors_for_element "$first"))
492 + local colors_second=($(get_colors_for_element "$second"))
493 +
554 494 case $first in
555 495 "USER") local text="$user" ;;
556 496 "HOST") local text="$host" ;;
@@ -564,91 +504,88 @@ combine_elements()
564 504 "INPUT") local text="" ;;
565 505 *) local text="" ;;
566 506 esac
507 +
567 508 local text_color=${colors_first[0]}
568 509 local bg_color=${colors_first[1]}
569 510 local next_bg_color=${colors_second[1]}
570 511 local text_effect=${colors_first[2]}
512 +
571 513 printSegment "$text" "$text_color" "$bg_color" "$next_bg_color" "$text_effect"
572 514 }
573 - ##==============================================================================
574 - ## HOOK
575 - ##==============================================================================
515 +
576 516 prompt_command_hook()
577 517 {
578 - ## GET PARAMETERS
579 - ## This might be a bit redundant, but it makes it easier to maintain
580 518 local elements=(${SSP_ELEMENTS[@]})
581 - local user=$USER
582 - local host=$HOSTNAME
583 - local path=$PWD
584 - local git_branch="$(getGitBranch)"
585 - local pyenv="$(getPyenv)"
586 - local kube="$(getKube)"
587 - local tf="$(getTerraform)"
588 - local clock="$(date +"${SSP_CLOCK_FORMAT}")"
589 - local date="$(date +"${SSP_DATE_FORMAT}")"
590 - ## ADAPT DYNAMICALLY ELEMENTS TO BE SHOWN
591 - ## Check if elements such as GIT and the Python environment should be
592 - ## shown and adapt the variables as needed. This usually implies removing
593 - ## the appropriate field from the "elements" array if the user set them
519 +
520 + local user="${SSP_ICON_USER} ${USER}"
521 + local host="$(getOSIcon) ${HOSTNAME}"
522 + local path="${SSP_ICON_FOLDER} ${PWD}"
523 +
524 + local git_branch
525 + local pyenv
526 + local kube
527 + local tf
528 + local clock
529 + local date
530 +
531 + git_branch="$(getGitBranch)"
532 + pyenv="$(getPyenv)"
533 + kube="$(getKube)"
534 + tf="$(getTerraform)"
535 + clock="${SSP_ICON_CLOCK} $(date +"${SSP_CLOCK_FORMAT}")"
536 + date="${SSP_ICON_CALENDAR} $(date +"${SSP_DATE_FORMAT}")"
537 +
594 538 if [ -z "$git_branch" ]; then
595 - elements=( ${elements[@]/"GIT"} ) # Remove GIT from elements to be shown
539 + elements=( ${elements[@]/"GIT"} )
596 540 fi
597 541 if [ -z "$pyenv" ]; then
598 - elements=( ${elements[@]/"PYENV"} ) # Remove PYENV from elements to be shown
542 + elements=( ${elements[@]/"PYENV"} )
599 543 fi
600 544 if [ -z "$tf" ]; then
601 - elements=( ${elements[@]/"TF"} ) # Remove TF from elements to be shown
545 + elements=( ${elements[@]/"TF"} )
602 546 fi
603 547 if [ -z "$kube" ]; then
604 - elements=( ${elements[@]/"KUBE"} ) # Remove KUBE from elements to be shown
548 + elements=( ${elements[@]/"KUBE"} )
605 549 fi
606 - ## WINDOW TITLE
607 - ## Prevent messed up terminal-window titles, must be set in the PS1 variable
550 +
608 551 case $TERM in
609 - xterm*|rxvt*)
610 - SSP_PWD="$path"
611 - local titlebar="\[\033]0;\${USER}@\${HOSTNAME}: \${SSP_PWD}\007\]"
612 - ;;
613 - *)
614 - local titlebar=""
615 - ;;
552 + xterm*|rxvt*)
553 + SSP_PWD="$PWD"
554 + local titlebar="\[\033]0;\${USER}@\${HOSTNAME}: \${SSP_PWD}\007\]"
555 + ;;
556 + *)
557 + local titlebar=""
558 + ;;
616 559 esac
617 - ## CONSTRUCT PROMPT ITERATIVELY
618 - ## Iterate through all elements to be shown and combine them. Stop once only
619 - ## 1 element is left, which should be the "INPUT" element; then apply the
620 - ## INPUT formatting.
621 - ## Notice that this reuses the PS1 variables over and over again, and appends
622 - ## all extra formatting elements to the end of it.
560 +
623 561 PS1="${titlebar}${SSP_VERTICAL_PADDING}${SSP_NEW_LINE_LINK_TOP}"
562 +
624 563 while [ "${#elements[@]}" -gt 1 ]; do
625 564 local current=${elements[0]}
626 565 local next=${elements[1]}
627 - local elements=("${elements[@]:1}") #remove the 1st element
628 - PS1="$PS1$(combine_elements $current $next)"
566 + elements=("${elements[@]:1}")
567 + PS1="$PS1$(combine_elements "$current" "$next")"
629 568 done
630 - local input_colors=($(get_colors_for_element ${elements[0]}))
569 +
570 + local input_colors=($(get_colors_for_element "${elements[0]}"))
631 571 local input_color=${input_colors[0]}
632 572 local input_bg=${input_colors[1]}
633 573 local input_effect=${input_colors[2]}
634 - local input_format="\[$(getFormatCode -c $input_color -b $input_bg -e $input_effect)\]"
574 + local input_format="\[$(getFormatCode -c "$input_color" -b "$input_bg" -e "$input_effect")\]"
635 575 local command_start_symbol="${input_format}${SSP_BASH_SYMBOL}"
636 - ## the prompt is then the prompt we build above, the separation between prompt and command and in
637 - ## the case of a new line inbetween, the corresponding link and $ symbol to start the command.
576 +
638 577 PS1="${PS1}${SSP_PROMPT_COMM_SEP}${SSP_NEW_LINE_LINK_BOTTOM}${command_start_symbol} $input_format"
639 - ## Once this point is reached, PS1 is formatted and set. The terminal session
640 - ## will then use that variable to prompt the user :)
641 578 }
579 +
642 580 ##==============================================================================
643 581 ## MAIN
644 582 ##==============================================================================
645 - ## PADDING
646 583 if $enable_vertical_padding; then
647 584 local vertical_padding="\n"
648 585 else
649 586 local vertical_padding=""
650 587 fi
651 - ## NEW LINE
588 +
652 589 if $enable_command_on_new_line; then
653 590 local new_line_link_top="╭"
654 591 local new_line_link_bottom="╰>"
@@ -656,12 +593,13 @@ prompt_command_hook()
656 593 local bash_symbol="\$"
657 594 else
658 595 local new_line_link_top=""
659 - local new_line_link_top=""
596 + local new_line_link_bottom=""
660 597 local prompt_command_separation=""
661 598 local bash_symbol=""
662 599 fi
663 - ## CONFIG FOR "prompt_command_hook()"
664 - SSP_ELEMENTS=($format "INPUT") # Append INPUT to elements that have to be shown
600 +
601 + SSP_ELEMENTS=($format "INPUT")
602 +
665 603 SSP_COLORS_USER=($font_color_user $background_user $texteffect_user)
666 604 SSP_COLORS_HOST=($font_color_host $background_host $texteffect_host)
667 605 SSP_COLORS_PWD=($font_color_pwd $background_pwd $texteffect_pwd)
@@ -672,12 +610,14 @@ prompt_command_hook()
672 610 SSP_COLORS_CLOCK=($font_color_clock $background_clock $texteffect_clock)
673 611 SSP_COLORS_DATE=($font_color_date $background_date $texteffect_date)
674 612 SSP_COLORS_INPUT=($font_color_input $background_input $texteffect_input)
613 +
675 614 SSP_VERTICAL_PADDING=$vertical_padding
676 615 SSP_NEW_LINE_LINK_TOP=$new_line_link_top
677 616 SSP_NEW_LINE_LINK_BOTTOM=$new_line_link_bottom
678 617 SSP_PROMPT_COMM_SEP=$prompt_command_separation
679 618 SSP_BASH_SYMBOL=$bash_symbol
680 619 SSP_MAX_PWD_CHAR=${max_pwd_char:-25}
620 +
681 621 SSP_GIT_SYNCED=$git_symbol_synced
682 622 SSP_GIT_AHEAD=$git_symbol_unpushed
683 623 SSP_GIT_BEHIND=$git_symbol_unpulled
@@ -688,32 +628,28 @@ prompt_command_hook()
688 628 SSP_GIT_DIRTY_DIVERGED=$git_symbol_dirty_unpushedunpulled
689 629 SSP_GIT_STASH=$git_symbol_stash
690 630 SSP_GIT_UPDATE_PERIOD_MINUTES=$git_update_period_minutes
631 +
691 632 SSP_CLOCK_FORMAT=${clock_format:-"%H:%M:%S"}
692 633 SSP_DATE_FORMAT=${date_format:-"%A, %d %B %Y"}
693 - ## For terminal line coloring, leaving the rest standard
634 +
635 + SSP_ICON_USER=$icon_user
636 + SSP_ICON_FOLDER=$icon_folder
637 + SSP_ICON_CALENDAR=$icon_calendar
638 + SSP_ICON_CLOCK=$icon_clock
639 + SSP_ICON_DEBIAN=$icon_debian
640 + SSP_ICON_LINUX=$icon_linux
641 +
694 642 none="$(tput sgr0)"
695 643 trap 'echo -ne "${none}"' DEBUG
696 - ## ADD HOOK TO UPDATE PS1 AFTER EACH COMMAND
697 - ## Bash provides an environment variable called PROMPT_COMMAND.
698 - ## The contents of this variable are executed as a regular Bash command
699 - ## just before Bash displays a prompt.
700 - ## We want it to call our own command to truncate PWD and store it in NEW_PWD
644 +
701 645 PROMPT_COMMAND=prompt_command_hook
702 - } # synth_shell_prompt()
703 - ##------------------------------------------------------------------------------
704 - ##
705 - ## CALL SCRIPT FUNCTION
706 - ## - CHECK IF SCRIPT IS _NOT_ BEING SOURCED
707 - ## - CHECK IF COLOR SUPPORTED
708 - ## - Check if compliant with Ecma-48 (ISO/IEC-6429)
709 - ## - Call script
710 - ## - Unset script
711 - ## If not running interactively, don't do anything
646 + }
647 +
712 648 if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
713 - echo -e "Do not run this script, it will do nothing.\nPlease source it instead by running:\n"
714 - echo -e "\t. ${BASH_SOURCE[0]}\n"
715 - exit
716 - elif [ -n "$( echo $- | grep i )" ]; then
649 + echo -e "Do not run this script, it will do nothing.\nPlease source it instead by running:\n"
650 + echo -e "\t. ${BASH_SOURCE[0]}\n"
651 + exit
652 + elif [[ $- == *i* ]]; then
717 653 if command -v tput >/dev/null 2>&1 && tput setaf 1 >&/dev/null; then
718 654 synth_shell_prompt
719 655 fi

dartokloning's Avatar dartokloning revisó este gist 1739614570. Ir a la revisión

1 file changed, 3 insertions, 3 deletions

shell-prompt.sh

@@ -262,8 +262,8 @@ enable_command_on_new_line=true # Add new line between prompt and command
262 262 ##==============================================================================
263 263 ## USER
264 264 ##==============================================================================
265 - font_color_user="white"
266 - background_user="blue"
265 + font_color_user="black"
266 + background_user="green"
267 267 texteffect_user="bold"
268 268 ##==============================================================================
269 269 ## HOST
@@ -316,7 +316,7 @@ texteffect_tf="bold"
316 316 ## CLOCK
317 317 ##==============================================================================
318 318 font_color_clock="white"
319 - background_clock="light-blue"
319 + background_clock="black"
320 320 texteffect_clock="bold"
321 321 clock_format="%H:%M:%S"
322 322 ##==============================================================================

dartokloning's Avatar dartokloning revisó este gist 1737995157. Ir a la revisión

1 file changed, 722 insertions

shell-prompt.sh(archivo creado)

@@ -0,0 +1,722 @@
1 + #!/usr/bin/env bash
2 +
3 + ##
4 + ##
5 + ## Visit for instructions and more information:
6 + ## https://github.com/andresgongora/synth-shell/
7 + ##
8 + ##
9 +
10 + ##
11 + ##==================================================================================================
12 + ## CODE PARSERS
13 + ##==================================================================================================
14 + ##------------------------------------------------------------------------------
15 + ##
16 + get8bitCode()
17 + {
18 + CODE=$1
19 + case $CODE in
20 + default)
21 + echo 9
22 + ;;
23 + none)
24 + echo 9
25 + ;;
26 + black)
27 + echo 0
28 + ;;
29 + red)
30 + echo 1
31 + ;;
32 + green)
33 + echo 2
34 + ;;
35 + yellow)
36 + echo 3
37 + ;;
38 + blue)
39 + echo 4
40 + ;;
41 + magenta|purple|pink)
42 + echo 5
43 + ;;
44 + cyan)
45 + echo 6
46 + ;;
47 + light-gray)
48 + echo 7
49 + ;;
50 + dark-gray)
51 + echo 60
52 + ;;
53 + light-red)
54 + echo 61
55 + ;;
56 + light-green)
57 + echo 62
58 + ;;
59 + light-yellow)
60 + echo 63
61 + ;;
62 + light-blue)
63 + echo 64
64 + ;;
65 + light-magenta|light-purple)
66 + echo 65
67 + ;;
68 + light-cyan)
69 + echo 66
70 + ;;
71 + white)
72 + echo 67
73 + ;;
74 + *)
75 + echo 0
76 + esac
77 + }
78 + ##------------------------------------------------------------------------------
79 + ##
80 + getColorCode()
81 + {
82 + COLOR=$1
83 + ## Check if color is a 256-color code
84 + if [ $COLOR -eq $COLOR ] 2> /dev/null; then
85 + if [ $COLOR -gt 0 -a $COLOR -lt 256 ]; then
86 + echo "38;5;$COLOR"
87 + else
88 + echo 0
89 + fi
90 + ## Or if color key-workd
91 + else
92 + BITCODE=$(get8bitCode $COLOR)
93 + COLORCODE=$(($BITCODE + 30))
94 + echo $COLORCODE
95 + fi
96 + }
97 + ##------------------------------------------------------------------------------
98 + ##
99 + getBackgroundCode()
100 + {
101 + COLOR=$1
102 + ## Check if color is a 256-color code
103 + if [ $COLOR -eq $COLOR ] 2> /dev/null; then
104 + if [ $COLOR -gt 0 -a $COLOR -lt 256 ]; then
105 + echo "48;5;$COLOR"
106 + else
107 + echo 0
108 + fi
109 + ## Or if color key-workd
110 + else
111 + BITCODE=$(get8bitCode $COLOR)
112 + COLORCODE=$(($BITCODE + 40))
113 + echo $COLORCODE
114 + fi
115 + }
116 + ##------------------------------------------------------------------------------
117 + ##
118 + getEffectCode()
119 + {
120 + EFFECT=$1
121 + NONE=0
122 + case $EFFECT in
123 + none)
124 + echo $NONE
125 + ;;
126 + default)
127 + echo $NONE
128 + ;;
129 + bold)
130 + echo 1
131 + ;;
132 + bright)
133 + echo 1
134 + ;;
135 + dim)
136 + echo 2
137 + ;;
138 + underline)
139 + echo 4
140 + ;;
141 + blink)
142 + echo 5
143 + ;;
144 + reverse)
145 + echo 7
146 + ;;
147 + hidden)
148 + echo 8
149 + ;;
150 + strikeout)
151 + echo 9
152 + ;;
153 + *)
154 + echo $NONE
155 + esac
156 + }
157 + ##------------------------------------------------------------------------------
158 + ##
159 + getFormattingSequence()
160 + {
161 + START='\e[0;'
162 + MIDLE=$1
163 + END='m'
164 + echo -n "$START$MIDLE$END"
165 + }
166 + ##==================================================================================================
167 + ## AUX
168 + ##==================================================================================================
169 + applyCodeToText()
170 + {
171 + local RESET=$(getFormattingSequence $(getEffectCode none))
172 + TEXT=$1
173 + CODE=$2
174 + echo -n "$CODE$TEXT$RESET"
175 + }
176 + ##==================================================================================================
177 + ## MAIN FUNCTIONS
178 + ##==================================================================================================
179 + ##------------------------------------------------------------------------------
180 + ##
181 + getFormatCode()
182 + {
183 + local RESET=$(getFormattingSequence $(getEffectCode none))
184 + ## NO ARGUMENT PROVIDED
185 + if [ "$#" -eq 0 ]; then
186 + echo -n "$RESET"
187 + ## 1 ARGUMENT -> ASSUME TEXT COLOR
188 + elif [ "$#" -eq 1 ]; then
189 + TEXT_COLOR=$(getFormattingSequence $(getColorCode $1))
190 + echo -n "$TEXT_COLOR"
191 + ## ARGUMENTS PROVIDED
192 + else
193 + FORMAT=""
194 + while [ "$1" != "" ]; do
195 + ## PROCESS ARGUMENTS
196 + TYPE=$1
197 + ARGUMENT=$2
198 + case $TYPE in
199 + -c)
200 + CODE=$(getColorCode $ARGUMENT)
201 + ;;
202 + -b)
203 + CODE=$(getBackgroundCode $ARGUMENT)
204 + ;;
205 + -e)
206 + CODE=$(getEffectCode $ARGUMENT)
207 + ;;
208 + *)
209 + CODE=""
210 + esac
211 + ## ADD CODE SEPARATOR IF NEEDED
212 + if [ "$FORMAT" != "" ]; then
213 + FORMAT="$FORMAT;"
214 + fi
215 + ## APPEND CODE
216 + FORMAT="$FORMAT$CODE"
217 + # Remove arguments from stack
218 + shift
219 + shift
220 + done
221 + ## APPLY FORMAT TO TEXT
222 + FORMAT_CODE=$(getFormattingSequence $FORMAT)
223 + echo -n "${FORMAT_CODE}"
224 + fi
225 + }
226 + ##------------------------------------------------------------------------------
227 + ##
228 + formatText()
229 + {
230 + local RESET=$(getFormattingSequence $(getEffectCode none))
231 + ## NO ARGUMENT PROVIDED
232 + if [ "$#" -eq 0 ]; then
233 + echo -n "${RESET}"
234 + ## ONLY A STRING PROVIDED -> Append reset sequence
235 + elif [ "$#" -eq 1 ]; then
236 + TEXT=$1
237 + echo -n "${TEXT}${RESET}"
238 + ## ARGUMENTS PROVIDED
239 + else
240 + TEXT=$1
241 + FORMAT_CODE=$(getFormatCode "${@:2}")
242 + applyCodeToText "$TEXT" "$FORMAT_CODE"
243 + fi
244 + }
245 + ##------------------------------------------------------------------------------
246 + ##
247 + removeColorCodes()
248 + {
249 + printf "$1" | sed 's/\x1b\[[0-9;]*m//g'
250 + }
251 +
252 + ##==============================================================================
253 + ## MAIN FORMAT
254 + ##==============================================================================
255 + format="USER HOST PWD GIT PYENV TF KUBE DATE CLOCK"
256 + separator_char='\uE0B0' # Separation character, '\uE0B0'=triangle
257 + separator_padding_left='' # Add char or string to the left of the separator
258 + separator_padding_right='' # Add char or string to the right of the separator
259 + segment_padding=' ' # Add char or string around segment text
260 + enable_vertical_padding=true # Add extra new line over prompt
261 + enable_command_on_new_line=true # Add new line between prompt and command
262 + ##==============================================================================
263 + ## USER
264 + ##==============================================================================
265 + font_color_user="white"
266 + background_user="blue"
267 + texteffect_user="bold"
268 + ##==============================================================================
269 + ## HOST
270 + ##==============================================================================
271 + font_color_host="white"
272 + background_host="light-blue"
273 + texteffect_host="bold"
274 + ##==============================================================================
275 + ## PWD (working dir)
276 + ##==============================================================================
277 + font_color_pwd="dark-gray"
278 + background_pwd="white"
279 + texteffect_pwd="bold"
280 + max_pwd_char="25"
281 + ##==============================================================================
282 + ## GIT
283 + ##==============================================================================
284 + font_color_git="light-gray"
285 + background_git="dark-gray"
286 + texteffect_git="bold"
287 + git_symbol_synced=''
288 + git_symbol_unpushed=' ▲'
289 + git_symbol_unpulled=' ▼'
290 + git_symbol_unpushedunpulled=' ◆'
291 + git_symbol_dirty=' ◔'
292 + git_symbol_dirty_unpushed=' ◔ △'
293 + git_symbol_dirty_unpulled=' ◔ ▽'
294 + git_symbol_dirty_unpushedunpulled=' ◔ ◇'
295 + git_symbol_stash='🗎'
296 + git_update_period_minutes=15 # Use -1 to disable automatic updates
297 + ##==============================================================================
298 + ## PYENV
299 + ##==============================================================================
300 + font_color_pyenv="white"
301 + background_pyenv="blue"
302 + texteffect_pyenv="bold"
303 + ##==============================================================================
304 + ## KUBERNETES
305 + ##==============================================================================
306 + font_color_kube="white"
307 + background_kube="purple"
308 + texteffect_kube="bold"
309 + ##==============================================================================
310 + ## TERRAFORM WORKSPACE
311 + ##==============================================================================
312 + font_color_tf="purple"
313 + background_tf="light-purple"
314 + texteffect_tf="bold"
315 + ##==============================================================================
316 + ## CLOCK
317 + ##==============================================================================
318 + font_color_clock="white"
319 + background_clock="light-blue"
320 + texteffect_clock="bold"
321 + clock_format="%H:%M:%S"
322 + ##==============================================================================
323 + ## DATE
324 + ##==============================================================================
325 + font_color_date="white"
326 + background_date="light-purple"
327 + texteffect_date="bold"
328 + date_format="${hari}, %d ${bulan} %Y"
329 + ##==============================================================================
330 + ## INPUT (user typed command)
331 + ##==============================================================================
332 + font_color_input="45"
333 + background_input="none"
334 + texteffect_input="bold"
335 +
336 + ##==============================================================================
337 + ## EXTERNAL DEPENDENCIES
338 + ##==============================================================================
339 + [ "$(type -t include)" != 'function' ]&&{ include(){ { [ -z "$_IR" ]&&_IR="$PWD"&&cd "$(dirname "${BASH_SOURCE[0]}")"&&include "$1"&&cd "$_IR"&&unset _IR;}||{ local d="$PWD"&&cd "$(dirname "$PWD/$1")"&&. "$(basename "$1")"&&cd "$d";}||{ echo "Include failed $PWD->$1"&&exit 1;};};}
340 + synth_shell_prompt()
341 + {
342 + ##==============================================================================
343 + ## FUNCTIONS
344 + ##==============================================================================
345 + ##------------------------------------------------------------------------------
346 + ##
347 + ## Returns current git branch for current directory, if (and only if)
348 + ## the current directory is part of a git repository, and git is installed.
349 + ##
350 + ## In addition, it adds a symbol to indicate the state of the repository.
351 + ## By default, these symbols and their meaning are (set globally):
352 + ##
353 + ## UPSTREAM NO CHANGE DIRTY
354 + ## up to date SSP_GIT_SYNCED SSP_GIT_DIRTY
355 + ## ahead SSP_GIT_AHEAD SSP_GIT_DIRTY_AHEAD
356 + ## behind SSP_GIT_BEHIND SSP_GIT_DIRTY_BEHIND
357 + ## diverged SSP_GIT_DIVERGED SSP_GIT_DIRTY_DIVERGED
358 + ##
359 + ## Returns an empty string otherwise.
360 + ##
361 + ## Inspired by twolfson's sexy-bash-prompt:
362 + ## https://github.com/twolfson/sexy-bash-prompt
363 + ##
364 + getGitBranch()
365 + {
366 + ## Check if git is installed, otherwise skip this function so as to not
367 + ## generate any errors.
368 + if ! ( which git > /dev/null 2>&1 ); then
369 + echo ""
370 + return
371 + fi
372 + ## Check if in a git respository, otherwise skip since there is no info
373 + ## to print.
374 + local branch=$(git branch 2> /dev/null |\
375 + sed -n '/^[^*]/d;s/*\s*\(.*\)/\1/p')
376 + if [[ -z "$branch" ]]; then
377 + echo ""
378 + return
379 + fi
380 + ## Fetch branch, required to later determine if the local dir is up to date.
381 + ## Because doing so for every terminal prompt can be slow, the script will
382 + ## do so only if its globaly enabled (see config) and only periodically in
383 + ## the background.
384 + if [ "$SSP_GIT_UPDATE_PERIOD_MINUTES" -ge 0 ]; then
385 + ## Find .git, i.e., the root of the repository.
386 + local d="$PWD"
387 + local max_lvls=25
388 + while [ ! -e "./.git" -a $max_lvls -gt 0 ]; do
389 + cd .. # Go up 1 level
390 + max_lvls=$((max_lvls - 1))
391 + done
392 + local dot_git="${PWD}/.git"
393 + cd "$d"
394 + ## Check if submodule.
395 + if [ -f "$dot_git" ]; then
396 + local dot_git=$(cat $dot_git | grep 'gitdir' | sed 's/gitdir:\ //g')
397 + fi
398 + ## Get timestamp.
399 + if [ -d "$dot_git" -a -e "${dot_git}/FETCH_HEAD" ]; then
400 + local git_last_update=$(stat -c "%Y" "${dot_git}/FETCH_HEAD")
401 + fi
402 + ## Update if it's time to do so.
403 + if [ ! -z $git_last_update ]; then
404 + local current_timestamp=$(date +%s)
405 + local elapsed_minutes=$(((current_timestamp-git_last_update)/60))
406 + if [ "$elapsed_minutes" -ge "$SSP_GIT_UPDATE_PERIOD_MINUTES" ]; then
407 + git fetch --recurse-submodules > /dev/null 2>&1 &
408 + fi
409 + fi
410 + fi
411 + ## Get repository status.
412 + ## This information contains whether the current branch is ahead, behind or
413 + ## diverged (ahead & behind), as well as whether any file has been modified
414 + ## locally (is dirty).
415 + ## @note The repository must be fetched for this information to be accurate.
416 + ## @note The following git flags are used:
417 + ## --porcelain: script friendly output.
418 + ## -b: show branch tracking info.
419 + ## -u no: do not list untracked/dirty files.
420 + local is_dirty=false &&\
421 + [[ -n "$(git status --porcelain)" ]] &&\
422 + is_dirty=true
423 + local is_ahead=false &&\
424 + [[ "$(git status --porcelain -u no -b)" == *"ahead"* ]] &&\
425 + is_ahead=true
426 + local is_behind=false &&\
427 + [[ "$(git status --porcelain -u no -b)" == *"behind"* ]] &&\
428 + is_behind=true
429 + ## Determine symbol to show in prompt according to git status.
430 + if $is_dirty && $is_ahead && $is_behind; then
431 + local symbol=$SSP_GIT_DIRTY_DIVERGED
432 + elif $is_dirty && $is_ahead; then
433 + local symbol=$SSP_GIT_DIRTY_AHEAD
434 + elif $is_dirty && $is_behind; then
435 + local symbol=$SSP_GIT_DIRTY_BEHIND
436 + elif $is_dirty; then
437 + local symbol=$SSP_GIT_DIRTY
438 + elif $is_ahead && $is_behind; then
439 + local symbol=$SSP_GIT_DIVERGED
440 + elif $is_ahead; then
441 + local symbol=$SSP_GIT_AHEAD
442 + elif $is_behind; then
443 + local symbol=$SSP_GIT_BEHIND
444 + else
445 + local symbol=$SSP_GIT_SYNCED
446 + fi
447 + ## Get commit tag (if any).
448 + [[ -n "$(git tag --points-at HEAD)" ]] &&\
449 + local tag=" $(git tag --points-at HEAD)" || local tag=""
450 + ## Get stash count (if any).
451 + local git_stash=""
452 + local stashed_elements=$(git stash list 2> /dev/null | wc -l)
453 + if [ "$stashed_elements" -gt 0 ]; then
454 + git_stash=" ${stashed_elements}${SSP_GIT_STASH}"
455 + fi
456 + ## Return assembled prompt segmet with git info.
457 + echo "${branch}$symbol${git_stash}${tag}"
458 + }
459 + ##------------------------------------------------------------------------------
460 + ##
461 + ##
462 + getTerraform()
463 + {
464 + ## Check if terraform is installed, otherwise skip this function.
465 + if ! ( which terraform > /dev/null 2>&1 ); then
466 + echo ""
467 + return
468 + fi
469 + ## Check if we are in a terraform directory, otherwise skip.
470 + if [ ! -d .terraform ]; then
471 + echo ""
472 + return
473 + fi
474 + ## Get the terraform workspace
475 + local tf="$(terraform workspace show 2> /dev/null | tr -d '\n')"
476 + echo "$tf"
477 + }
478 + ##------------------------------------------------------------------------------
479 + ##
480 + ##
481 + getPyenv()
482 + {
483 + ## Conda environment
484 + if [ -n "$CONDA_DEFAULT_ENV" ]; then
485 + echo "$CONDA_DEFAULT_ENV"
486 + ## Python virtual environment
487 + elif [ -n "${VIRTUAL_ENV:-}" ]; then
488 + local regex='PS1=\"\((.*?)\)\s\$\{PS1'
489 + local pyenv=$(cat $VIRTUAL_ENV/bin/activate |\
490 + perl -n -e"/$regex/ && print \$1" 2> /dev/null)
491 + if [ -z "${pyenv}" ]; then
492 + local pyenv=$(basename ${VIRTUAL_ENV})
493 + fi
494 + echo "$pyenv"
495 + fi
496 + }
497 + ##------------------------------------------------------------------------------
498 + ##
499 + ##
500 + getKube()
501 + {
502 + type kubectl &>/dev/null && \
503 + type yq &>/dev/null && \
504 + echo -n "$(kubectl config view | yq '.contexts[].context.cluster |select(.contexts[].name == .current-context)' | head -n 1)"
505 + }
506 + ##------------------------------------------------------------------------------
507 + ##
508 + ## Print each word of the propmpt, i.e., a small text acompanied by the
509 + ## separator character and formated with colors and background.
510 + ##
511 + printSegment()
512 + {
513 + ## GET PARAMETERS
514 + local text=$1
515 + local font_color=$2
516 + local background_color=$3
517 + local next_background_color=$4 # needed for the separator, it participates in this and the next text segment
518 + local font_effect=$5
519 + ## COMPUTE COLOR FORMAT CODES
520 + local no_color="\[$(getFormatCode -e reset)\]"
521 + local text_format="\[$(getFormatCode -c $font_color -b $background_color -e $font_effect)\]"
522 + local separator_format="\[$(getFormatCode -c $background_color -b $next_background_color)\]"
523 + ## GENERATE TEXT
524 + printf "${text_format}${segment_padding}${text}${segment_padding}${separator_padding_left}${separator_format}${separator_char}${separator_padding_right}${no_color}"
525 + }
526 + ##------------------------------------------------------------------------------
527 + ##
528 + ##
529 + get_colors_for_element()
530 + {
531 + case $1 in
532 + "USER") echo "${SSP_COLORS_USER[@]}" ;;
533 + "HOST") echo "${SSP_COLORS_HOST[@]}" ;;
534 + "PWD") echo "${SSP_COLORS_PWD[@]}" ;;
535 + "GIT") echo "${SSP_COLORS_GIT[@]}" ;;
536 + "PYENV") echo "${SSP_COLORS_PYENV[@]}";;
537 + "KUBE") echo "${SSP_COLORS_KUBE[@]}";;
538 + "TF") echo "${SSP_COLORS_TF[@]}" ;;
539 + "CLOCK") echo "${SSP_COLORS_CLOCK[@]}";;
540 + "DATE") echo "${SSP_COLORS_DATE[@]}";;
541 + "INPUT") echo "${SSP_COLORS_INPUT[@]}";;
542 + *)
543 + esac
544 + }
545 + ##------------------------------------------------------------------------------
546 + ##
547 + ##
548 + combine_elements()
549 + {
550 + local first=$1
551 + local second=$2
552 + local colors_first=($(get_colors_for_element $first))
553 + local colors_second=($(get_colors_for_element $second))
554 + case $first in
555 + "USER") local text="$user" ;;
556 + "HOST") local text="$host" ;;
557 + "PWD") local text="$path" ;;
558 + "GIT") local text="$git_branch" ;;
559 + "PYENV") local text="$pyenv" ;;
560 + "KUBE") local text="$kube" ;;
561 + "TF") local text="$tf" ;;
562 + "CLOCK") local text="$clock" ;;
563 + "DATE") local text="$date" ;;
564 + "INPUT") local text="" ;;
565 + *) local text="" ;;
566 + esac
567 + local text_color=${colors_first[0]}
568 + local bg_color=${colors_first[1]}
569 + local next_bg_color=${colors_second[1]}
570 + local text_effect=${colors_first[2]}
571 + printSegment "$text" "$text_color" "$bg_color" "$next_bg_color" "$text_effect"
572 + }
573 + ##==============================================================================
574 + ## HOOK
575 + ##==============================================================================
576 + prompt_command_hook()
577 + {
578 + ## GET PARAMETERS
579 + ## This might be a bit redundant, but it makes it easier to maintain
580 + local elements=(${SSP_ELEMENTS[@]})
581 + local user=$USER
582 + local host=$HOSTNAME
583 + local path=$PWD
584 + local git_branch="$(getGitBranch)"
585 + local pyenv="$(getPyenv)"
586 + local kube="$(getKube)"
587 + local tf="$(getTerraform)"
588 + local clock="$(date +"${SSP_CLOCK_FORMAT}")"
589 + local date="$(date +"${SSP_DATE_FORMAT}")"
590 + ## ADAPT DYNAMICALLY ELEMENTS TO BE SHOWN
591 + ## Check if elements such as GIT and the Python environment should be
592 + ## shown and adapt the variables as needed. This usually implies removing
593 + ## the appropriate field from the "elements" array if the user set them
594 + if [ -z "$git_branch" ]; then
595 + elements=( ${elements[@]/"GIT"} ) # Remove GIT from elements to be shown
596 + fi
597 + if [ -z "$pyenv" ]; then
598 + elements=( ${elements[@]/"PYENV"} ) # Remove PYENV from elements to be shown
599 + fi
600 + if [ -z "$tf" ]; then
601 + elements=( ${elements[@]/"TF"} ) # Remove TF from elements to be shown
602 + fi
603 + if [ -z "$kube" ]; then
604 + elements=( ${elements[@]/"KUBE"} ) # Remove KUBE from elements to be shown
605 + fi
606 + ## WINDOW TITLE
607 + ## Prevent messed up terminal-window titles, must be set in the PS1 variable
608 + case $TERM in
609 + xterm*|rxvt*)
610 + SSP_PWD="$path"
611 + local titlebar="\[\033]0;\${USER}@\${HOSTNAME}: \${SSP_PWD}\007\]"
612 + ;;
613 + *)
614 + local titlebar=""
615 + ;;
616 + esac
617 + ## CONSTRUCT PROMPT ITERATIVELY
618 + ## Iterate through all elements to be shown and combine them. Stop once only
619 + ## 1 element is left, which should be the "INPUT" element; then apply the
620 + ## INPUT formatting.
621 + ## Notice that this reuses the PS1 variables over and over again, and appends
622 + ## all extra formatting elements to the end of it.
623 + PS1="${titlebar}${SSP_VERTICAL_PADDING}${SSP_NEW_LINE_LINK_TOP}"
624 + while [ "${#elements[@]}" -gt 1 ]; do
625 + local current=${elements[0]}
626 + local next=${elements[1]}
627 + local elements=("${elements[@]:1}") #remove the 1st element
628 + PS1="$PS1$(combine_elements $current $next)"
629 + done
630 + local input_colors=($(get_colors_for_element ${elements[0]}))
631 + local input_color=${input_colors[0]}
632 + local input_bg=${input_colors[1]}
633 + local input_effect=${input_colors[2]}
634 + local input_format="\[$(getFormatCode -c $input_color -b $input_bg -e $input_effect)\]"
635 + local command_start_symbol="${input_format}${SSP_BASH_SYMBOL}"
636 + ## the prompt is then the prompt we build above, the separation between prompt and command and in
637 + ## the case of a new line inbetween, the corresponding link and $ symbol to start the command.
638 + PS1="${PS1}${SSP_PROMPT_COMM_SEP}${SSP_NEW_LINE_LINK_BOTTOM}${command_start_symbol} $input_format"
639 + ## Once this point is reached, PS1 is formatted and set. The terminal session
640 + ## will then use that variable to prompt the user :)
641 + }
642 + ##==============================================================================
643 + ## MAIN
644 + ##==============================================================================
645 + ## PADDING
646 + if $enable_vertical_padding; then
647 + local vertical_padding="\n"
648 + else
649 + local vertical_padding=""
650 + fi
651 + ## NEW LINE
652 + if $enable_command_on_new_line; then
653 + local new_line_link_top="╭"
654 + local new_line_link_bottom="╰>"
655 + local prompt_command_separation="\n"
656 + local bash_symbol="\$"
657 + else
658 + local new_line_link_top=""
659 + local new_line_link_top=""
660 + local prompt_command_separation=""
661 + local bash_symbol=""
662 + fi
663 + ## CONFIG FOR "prompt_command_hook()"
664 + SSP_ELEMENTS=($format "INPUT") # Append INPUT to elements that have to be shown
665 + SSP_COLORS_USER=($font_color_user $background_user $texteffect_user)
666 + SSP_COLORS_HOST=($font_color_host $background_host $texteffect_host)
667 + SSP_COLORS_PWD=($font_color_pwd $background_pwd $texteffect_pwd)
668 + SSP_COLORS_GIT=($font_color_git $background_git $texteffect_git)
669 + SSP_COLORS_PYENV=($font_color_pyenv $background_pyenv $texteffect_pyenv)
670 + SSP_COLORS_KUBE=($font_color_kube $background_kube $texteffect_kube)
671 + SSP_COLORS_TF=($font_color_tf $background_tf $texteffect_tf)
672 + SSP_COLORS_CLOCK=($font_color_clock $background_clock $texteffect_clock)
673 + SSP_COLORS_DATE=($font_color_date $background_date $texteffect_date)
674 + SSP_COLORS_INPUT=($font_color_input $background_input $texteffect_input)
675 + SSP_VERTICAL_PADDING=$vertical_padding
676 + SSP_NEW_LINE_LINK_TOP=$new_line_link_top
677 + SSP_NEW_LINE_LINK_BOTTOM=$new_line_link_bottom
678 + SSP_PROMPT_COMM_SEP=$prompt_command_separation
679 + SSP_BASH_SYMBOL=$bash_symbol
680 + SSP_MAX_PWD_CHAR=${max_pwd_char:-25}
681 + SSP_GIT_SYNCED=$git_symbol_synced
682 + SSP_GIT_AHEAD=$git_symbol_unpushed
683 + SSP_GIT_BEHIND=$git_symbol_unpulled
684 + SSP_GIT_DIVERGED=$git_symbol_unpushedunpulled
685 + SSP_GIT_DIRTY=$git_symbol_dirty
686 + SSP_GIT_DIRTY_AHEAD=$git_symbol_dirty_unpushed
687 + SSP_GIT_DIRTY_BEHIND=$git_symbol_dirty_unpulled
688 + SSP_GIT_DIRTY_DIVERGED=$git_symbol_dirty_unpushedunpulled
689 + SSP_GIT_STASH=$git_symbol_stash
690 + SSP_GIT_UPDATE_PERIOD_MINUTES=$git_update_period_minutes
691 + SSP_CLOCK_FORMAT=${clock_format:-"%H:%M:%S"}
692 + SSP_DATE_FORMAT=${date_format:-"%A, %d %B %Y"}
693 + ## For terminal line coloring, leaving the rest standard
694 + none="$(tput sgr0)"
695 + trap 'echo -ne "${none}"' DEBUG
696 + ## ADD HOOK TO UPDATE PS1 AFTER EACH COMMAND
697 + ## Bash provides an environment variable called PROMPT_COMMAND.
698 + ## The contents of this variable are executed as a regular Bash command
699 + ## just before Bash displays a prompt.
700 + ## We want it to call our own command to truncate PWD and store it in NEW_PWD
701 + PROMPT_COMMAND=prompt_command_hook
702 + } # synth_shell_prompt()
703 + ##------------------------------------------------------------------------------
704 + ##
705 + ## CALL SCRIPT FUNCTION
706 + ## - CHECK IF SCRIPT IS _NOT_ BEING SOURCED
707 + ## - CHECK IF COLOR SUPPORTED
708 + ## - Check if compliant with Ecma-48 (ISO/IEC-6429)
709 + ## - Call script
710 + ## - Unset script
711 + ## If not running interactively, don't do anything
712 + if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
713 + echo -e "Do not run this script, it will do nothing.\nPlease source it instead by running:\n"
714 + echo -e "\t. ${BASH_SOURCE[0]}\n"
715 + exit
716 + elif [ -n "$( echo $- | grep i )" ]; then
717 + if command -v tput >/dev/null 2>&1 && tput setaf 1 >&/dev/null; then
718 + synth_shell_prompt
719 + fi
720 + unset synth_shell_prompt
721 + unset include
722 + fi
Siguiente Anterior