-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.bashrc
More file actions
735 lines (646 loc) · 24.7 KB
/
Copy path.bashrc
File metadata and controls
735 lines (646 loc) · 24.7 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
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
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
export CLI_OUTPUT=NONE
# =====================================================================
# Output filtering via $CLI_OUTPUT (case-insensitive)
# Categories: success | warning | error | info
# Presets: ALL (default) | NONE
#
# Examples:
# export CLI_OUTPUT=warning|success
# export CLI_OUTPUT="ERROR, SUCCESS"
# export CLI_OUTPUT="success error" # space-separated
# export CLI_OUTPUT=NONE # only final completed message
# export CLI_OUTPUT=ALL # show everything
__cli_out_raw="${CLI_OUTPUT:-}"
__cli_out_norm="$(printf '%s' "$__cli_out_raw" | tr '[:upper:]' '[:lower:]')"
# Split by | , or whitespace into an array of tokens
# Shell-safe tokenizer: translate separators to spaces, then read into array.
__cli_tokens=()
if [ -n "$__cli_out_norm" ]; then
__cli_out_seps="$(printf '%s' "$__cli_out_norm" | tr ',|' ' ')"
# trim extra spaces
# shellcheck disable=SC2086
set -- $__cli_out_seps
for t in "$@"; do
[ -n "$t" ] && __cli_tokens+=("$t")
done
fi
# Resolve preset: default ALL unless explicitly NONE or ALL provided,
# but if specific categories are given, switch to CUSTOM.
__cli_preset="all"
for t in "${__cli_tokens[@]}"; do
case "$t" in
none) __cli_preset="none" ;;
all) __cli_preset="all" ;;
esac
done
# Build an allow-list set only when not NONE
# We use a simple "contains" function against a normalized list
__cli_allow_list=""
if [ "$__cli_preset" = "none" ]; then
__cli_allow_list="" # nothing allowed
else
# If tokens include specific categories, use them; otherwise ALL
__has_specific=0
for t in "${__cli_tokens[@]}"; do
case "$t" in
success|warning|error|info)
__has_specific=1
# de-duplicate
case "$__cli_allow_list" in
*" $t "* ) ;; # already present
* ) __cli_allow_list="$__cli_allow_list $t " ;;
esac
;;
esac
done
if [ "$__has_specific" -eq 1 ]; then
# Specific categories provided → CUSTOM preset
__cli_preset="custom"
else
# No specific categories → ALL categories allowed
__cli_allow_list=" success warning error info "
__cli_preset="all"
fi
fi
# Predicate: is a category enabled?
cli_enabled() {
# $1: category name (success|warning|error|info)
case "$__cli_preset" in
none) return 1 ;; # nothing allowed
all) return 0 ;; # everything allowed
custom)
case "$__cli_allow_list" in
*" $1 "* ) return 0 ;;
* ) return 1 ;;
esac
;;
*) return 0 ;; # safety: treat unknown as ALL
esac
}
# Log helpers: route messages through these instead of echo
# (Keep icons; warnings/errors go to stderr.)
cli_success() { cli_enabled success && printf '✅ %b\n' "$*"; }
cli_warning() { cli_enabled warning && printf '⚠️ %b\n' "$*" >&2; }
cli_error() { cli_enabled error && printf '🛑 %b\n' "$*" >&2; }
cli_info() { cli_enabled info && printf 'ℹ️ %b\n' "$*"; }
cli_blank() { printf '%b\n' "$*"; }
cli_completed(){ printf '🧐 %s\n' "BashRC executed and Aliases added"; } # single final line
# Force-print helpers (ignore CLI_OUTPUT filter)
# Primary use: --help / -h
cli_success_f() { printf '✅ %b\n' "$*"; }
cli_warning_f() { printf '⚠️ %b\n' "$*" >&2; }
cli_error_f() { printf '🛑 %b\n' "$*" >&2; }
cli_info_f() { printf 'ℹ️ %b\n' "$*"; }
cli_blank_f() { printf '%b\n' "$*"; }
# =====================================================================
# Function definitions used by shell
# ---------------------------------------------------------------------
# Function to safely append to PATH
add_to_path() {
local force=0
local show_help=0
local path=""
for arg in "$@"; do
case "$arg" in
--force) force=1 ;;
--help|-h) show_help=1 ;;
*) path="$arg" ;;
esac
done
if [ "$show_help" -eq 1 ] || [ -z "$path" ]; then
cli_info_f "Usage: add_to_path [--force] <path>"
cli_blank_f " "
cli_info_f "Adds <path> to the PATH environment variable."
cli_blank_f " "
cli_info_f "Options:"
cli_info_f " --force Add the path even if it does not exist."
cli_info_f " --help, -h Show this help message."
cli_blank_f " "
cli_info_f "Examples:"
cli_info_f " add_to_path ./vendor/bin"
cli_info_f " add_to_path --force ./vendor/bin"
return 0
fi
if [ "$force" -eq 1 ] || [ -d "$path" ]; then
PATH="$path:$PATH"
cli_success "Added '$path' to PATH."
else
cli_warning "Warning: '$path' does not exist. Use --force to add it anyway."
fi
}
# ---------------------------------------------------------------------
# Add_Alias function that adds aliases as well
# as verifying commands/folders exist before creating the alias
#
# Examples of how to use:
#
# add_alias 'alias-edit' 'nano /c/Users/$USERNAME/.aliases'
# add_alias laragon 'cd /c/ProgramData/Laragon/'
# add_alias emqx-stop 'cd /c/Laragon/bin/mqtt/emqx/bin && emqx stop'
# add_alias makeapi 'artisan make:model -acs --api'
add_alias() {
# Help option
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
cli_info_f "Usage: add_alias [--force|-f] <alias_name> <alias_command>"
cli_blank_f " "
cli_info_f "Options:"
cli_info_f " --force, -f Force creation of alias even if command or path is invalid"
cli_info_f " --help, -h Show this help message"
cli_blank_f " "
cli_info_f "Examples:"
cli_info_f " add_alias cls 'clear'"
cli_info_f " add_alias laragon 'cd /c/ProgramData/Laragon/'"
cli_info_f " add_alias --force emqx-start 'cd /c/Laragon/bin/mqtt/emqx/bin && ./emqx foreground'"
return 0
fi
local force=false
local alias_name
local alias_command
# Check for --force or -f flag
if [[ "$1" == "--force" || "$1" == "-f" ]]; then
force=true
alias_name="$2"
alias_command="$3"
else
alias_name="$1"
alias_command="$2"
fi
# Check if the command starts with 'cd'
if [[ "$alias_command" =~ ^cd[[:space:]]+([^&]+) ]]; then
local path="${BASH_REMATCH[1]}"
eval path="$path"
if [ ! -d "$path" ]; then
if [ "$force" = false ]; then
cli_error "Directory '$path' does not exist. Alias '$alias_name' not created."
return 1
else
cli_warning "Directory '$path' not found. Alias '$alias_name' forced."
fi
fi
fi
# Check for executable in the command (e.g., './emqx', './mosquitto.exe')
if [[ "$alias_command" =~ \&\&[[:space:]]+\./([a-zA-Z0-9._-]+) ]]; then
local exec_file="${BASH_REMATCH[1]}"
local exec_path="${path}/${exec_file}"
if [ ! -x "$exec_path" ]; then
if [ "$force" = false ]; then
cli_error "Executable '$exec_file' not found or not executable at '$exec_path'. Alias '$alias_name' not created."
return 1
else
cli_warning "Executable '$exec_file' not found. Alias '$alias_name' forced."
fi
fi
else
# Extract the first command word
local cmd="${alias_command%% *}"
if ! command -v "$cmd" &> /dev/null; then
if [ "$force" = false ]; then
cli_error "Command '$cmd' not found. Alias '$alias_name' not created."
return 1
else
cli_warning "Command '$cmd' not found. Alias '$alias_name' forced."
fi
fi
fi
# Create the alias
alias "$alias_name"="$alias_command"
cli_success "Alias '$alias_name' created for: $alias_command"
}
# =====================================================================
# Show a folder tree (default: current directory).
# Options:
# --dir <path> Render the given directory (absolute or relative)
# --path Render PATH entries as a component tree (legacy mode)
# --show-hidden Include dotfiles/hidden items (names beginning with '.')
# --max-depth=N Limit depth (directory mode only; 0/omit = unlimited)
# --delimiter=CHAR Separator used in --path mode (default: ':')
# --help, -h Show detailed help and exit
#
# Examples:
# pathtree # current dir
# pathtree --dir /c/Laragon/bin # specific dir
# pathtree --dir . --show-hidden # current dir, include hidden
# pathtree --dir /c/Projects --max-depth=2
# pathtree --path # PATH as component tree (normalized)
# pathtree --path --delimiter=';' # if PATH uses ';' as separator
pathtree() {
local mode="dir" # dir | path
local target="$PWD"
local show_hidden=false
local max_depth=0 # 0 = unlimited
local delimiter=":" # used only in --path mode
local target_given=0
# Parse options
while [ $# -gt 0 ]; do
case "$1" in
--dir)
shift
target="${1:-$PWD}"
target_given=1
;;
--path)
mode="path"
;;
--show-hidden)
show_hidden=true
;;
--max-depth=*)
max_depth="${1#*=}"
;;
--delimiter=*)
delimiter="${1#*=}"
;;
--help|-h)
# Extended help text
cli_blank_f " "
cli_info_f "Usage: pathtree [OPTIONS] [<path>]"
cli_blank_f " "
cli_info_f "Description:"
cli_info_f " Render a simple ASCII tree. By default, pathtree prints the tree of"
cli_info_f " the current working directory. You can also render a specific directory"
cli_info_f " or visualize your PATH as a component tree (legacy mode)."
cli_blank_f " "
cli_info_f "Options:"
cli_info_f " --dir <path> Render the given directory (absolute or relative)."
cli_info_f " If a bare path (without --dir) is supplied and is a"
cli_info_f " valid directory, it is treated as --dir <path>."
cli_info_f " --path Render PATH entries as a hierarchical component tree."
cli_info_f " Useful to inspect how PATH is composed; drive letters"
cli_info_f " like /C/... are normalized to /c/... to avoid duplicates."
cli_info_f " --show-hidden Include hidden files/directories (names beginning with '.')."
cli_info_f " Default behavior prunes hidden directories for readability."
cli_info_f " --max-depth=N Limit the depth in directory mode to N levels."
cli_info_f " Defaults to unlimited (0 or omitted)."
cli_info_f " --delimiter=CHAR Character that separates PATH entries in --path mode."
cli_info_f " Default is ':'. On Windows shells, you may prefer ';'."
cli_info_f " --help, -h Show this help and exit."
cli_blank_f " "
cli_info_f "Behavior & Notes:"
cli_info_f " • Default mode is directory mode, using \$PWD."
cli_info_f " • PATH mode does not walk the filesystem; it splits PATH and displays"
cli_info_f " the segments as nested components for a quick visual overview."
cli_info_f " • Hidden entries are pruned unless --show-hidden is given."
cli_info_f " • On mixed-case Windows paths, drive letters are normalized (e.g., /C → /c)."
cli_info_f " • Output respects CLI_OUTPUT filters (success|warning|error|info|none|all)."
cli_info_f " Help text uses 'info' and 'blank' lines."
cli_blank_f " "
cli_info_f "Examples:"
cli_info_f " pathtree"
cli_info_f " Show the tree of the current directory."
cli_info_f " pathtree --dir /c/Laragon/bin"
cli_info_f " Show the tree of a specific directory."
cli_info_f " pathtree --dir . --show-hidden --max-depth=2"
cli_info_f " Show current directory, include dotfiles, limit to 2 levels."
cli_info_f " pathtree --path"
cli_info_f " Visualize PATH entries as a normalized component tree."
cli_info_f " pathtree --path --delimiter=';'"
cli_info_f " Use ';' as the PATH entry separator."
cli_blank_f " "
return 0
;;
*)
# If a bare path is given without --dir, treat it as target
if [ "$target_given" -eq 0 ] && [ -d "$1" ]; then
target="$1"
target_given=1
else
cli_warning "Unknown option or non-directory: $1"
fi
;;
esac
shift
done
if [ "$mode" = "path" ]; then
# ---- PATH MODE (legacy) ---------------------------------------------------
local tree=()
local IFS="$delimiter"
# shellcheck disable=SC2206
local paths=($PATH)
IFS=" "
for p in "${paths[@]}"; do
# normalize Windows drive letters: /C/... -> /c/...
p="$(printf '%s' "$p" | sed -E 's|^/([A-Z])|/\L\1|')"
IFS='/' read -r -a parts <<< "$p"
local current=""
for part in "${parts[@]}"; do
[ -z "$part" ] && continue
if [ "$show_hidden" = false ] && printf '%s' "$part" | grep -qE '^\.'; then
continue
fi
current="$current/$part"
tree+=("$current")
done
IFS=" "
done
if [ ${#tree[@]} -eq 0 ]; then
cli_info "PATH appears empty."
return 0
fi
# de-duplicate + sort
printf "%s\n" "${tree[@]}" | awk '!seen[$0]++' | sort |
awk -F'/' '
{
depth=NF-1; name=$NF; indent="";
for (i=1; i<depth; i++) indent=indent " |";
printf("|%s +-- %s\n", indent, name);
}
'
return 0
fi
# ---- DIRECTORY MODE (default) ----------------------------------------------
if [ ! -d "$target" ]; then
cli_error "Directory not found: $target"
return 1
fi
local find_opts=()
find_opts+=("$target")
find_opts+=(-type d)
if [ "$show_hidden" = false ]; then
# prune hidden dirs
find_opts+=("(" -name ".*" -prune ")" -o -type d -print)
else
find_opts+=(-print)
fi
if [ "$max_depth" -gt 0 ] 2>/dev/null; then
find_opts+=(-maxdepth "$max_depth")
fi
# shellcheck disable=SC2207
local dirs=($(find "${find_opts[@]}" 2>/dev/null | sed -E 's|^/([A-Z])|/\L\1|' | sort))
if [ ${#dirs[@]} -eq 0 ]; then
cli_info "(empty)"
return 0
fi
local base_parts
IFS='/' read -r -a base_parts <<< "$target"
local base_depth=${#base_parts[@]}
IFS=" "
for d in "${dirs[@]}"; do
IFS='/' read -r -a parts <<< "$d"
local depth=$(( ${#parts[@]} - base_depth ))
[ "$depth" -lt 0 ] && depth=0
local name="${parts[-1]}"
local indent=""
for ((i=0; i<depth; i++)); do
indent="$indent| "
done
printf "%s+-- %s\n" "$indent" "$name"
IFS=" "
done
}
# ---------------------------------------------------------------------
# Convert MSYS/Git Bash path to Windows path for cmd.exe
_to_win_path() {
# Prefer cygpath if available; otherwise do a simple transform
if command -v cygpath >/dev/null 2>&1; then
cygpath -w "$1"
else
# /c/Program Files/Python311/python.exe -> C:\Program Files\Python311\python.exe
printf '%s' "$1" | sed -E 's,^/([a-zA-Z])/,\\U\1:\\,; s,/,\\,g'
fi
}
# ---------------------------------------------------------------------
_probe_python_version() {
local exe="$1"
local line version
# Try direct (works in your output)
line=$("$exe" --version 2>&1 | tr -d '\r' | head -n 1) || line=""
if [[ ! "$line" =~ ^Python[[:space:]] ]]; then
# Convert path for cmd.exe and then quote it
local win_exe=$(_to_win_path "$exe")
line=$(cmd.exe /c "\"$win_exe\" --version" 2>&1 | tr -d '\r' | head -n 1) || line=""
fi
if [[ "$line" =~ ^Python[[:space:]]+([0-9][0-9.]+) ]]; then
version="${BASH_REMATCH[1]}"
printf '%s' "$version"
return 0
fi
return 1
}
# ---------------------------------------------------------------------
# Locate latest version of Python and add to path
find_latest_python() {
local META_FILE="$HOME/.python_version"
local SEARCH_DIRS=("/c/Program Files" "/c/Program Files (x86)" "/c/Laragon/bin")
local FORCE=false
local SHOW=false
local PERSIST=false
local REMOVE=false
cli_info " "
cli_info "Searching for Python, and checking for latest version"
cli_info " "
cli_info "First run may take several minutes"
# Parse flags
for arg in "$@"; do
case "$arg" in
--force) FORCE=true ;;
--show) SHOW=true ;;
--set-persistent) PERSIST=true ;;
--remove-persistent) REMOVE=true ;;
--help)
cli_info_f "Usage: find_latest_python [options]"
cli_blank_f " "
cli_info_f "Options:"
cli_info_f " --force Force rescan even if cached this month"
cli_info_f " --show Show all detected Python versions and paths"
cli_info_f " --set-persistent Add or update latest Python path in ~/.bashrc"
cli_info_f " --remove-persistent Remove any Python PATH entry from ~/.bashrc"
cli_info_f " --help Show this help message"
return 0
;;
esac
done
# Handle remove persistent
if [ "$REMOVE" = true ]; then
_remove_bashrc
return 0
fi
local TODAY=$(date +%Y-%m)
local LAST_SCAN=""
local LAST_VERSION=""
local LAST_PATH=""
if [ -f "$META_FILE" ]; then
LAST_SCAN=$(awk -F= '/last_scan/{print $2}' "$META_FILE")
LAST_VERSION=$(awk -F= '/version/{print $2}' "$META_FILE")
LAST_PATH=$(awk -F= '/path/{print $2}' "$META_FILE")
fi
# Skip scan if same month and not forced
if [ "$FORCE" = false ] && [ "$LAST_SCAN" == "$TODAY" ] && [ -n "$LAST_VERSION" ]; then
cli_info_f "Using cached Python version: $LAST_VERSION"
export PATH="$(dirname "$LAST_PATH"):$PATH"
cli_success_f "Current Python: $(python --version)"
if ! python -m pip --version &>/dev/null; then
cli_error "pip is not installed for this Python."
fi
if [ "$PERSIST" = true ]; then
_update_bashrc "$(dirname "$LAST_PATH")"
fi
return 0
fi
# Scan for python.exe, ignoring venv folders
local PYTHON_PATHS=()
for dir in "${SEARCH_DIRS[@]}"; do
if [ -d "$dir" ]; then
while IFS= read -r path; do
PYTHON_PATHS+=("$path")
done < <(find "$dir" -type f -iname "python.exe" \
-not -path "*/venv/*" -not -path "*/.venv/*" 2>/dev/null)
fi
done
if [ ${#PYTHON_PATHS[@]} -eq 0 ]; then
cli_error_f "No Python installation found."
return 1
fi
# Map versions to paths
declare -A VERSION_MAP
for path in "${PYTHON_PATHS[@]}"; do
# Try to get a version string robustly
version=$(_probe_python_version "$path") || version=""
if [[ -n "$version" ]]; then
VERSION_MAP["$version"]="$path"
if [ "$SHOW" = true ]; then
cli_info_f " ✔ $version -> $path"
fi
else
if [ "$SHOW" = true ]; then
cli_warning_f " ✖ unable to read version -> $path"
fi
continue
fi
done
if [[ ${#VERSION_MAP[@]} -eq 0 ]]; then
cli_error_f "Found python.exe candidates, but could not read any version strings."
return 1
fi
# Show all versions if requested
if [ "$SHOW" = true ]; then
cli_info_f "Detected Python installations:"
for v in $(printf "%s\n" "${!VERSION_MAP[@]}" | sort -V); do
cli_info_f " $v -> ${VERSION_MAP[$v]}"
done
fi
# Sort versions and pick latest
local LATEST_VERSION=$(printf "%s\n" "${!VERSION_MAP[@]}" | sort -V | tail -n 1)
local LATEST_PATH="${VERSION_MAP[$LATEST_VERSION]}"
local PYTHON_DIR=$(dirname "$LATEST_PATH")
# Update PATH
export PATH="$PYTHON_DIR:$PATH"
cli_success "Added Python $LATEST_VERSION from $PYTHON_DIR to PATH."
cli_info "Current Python: $(python --version)"
# Check pip
if ! python -m pip --version &>/dev/null; then
cli_error "pip is not installed for this Python."
else
cli_info "pip is available."
fi
# Save metadata
cat > "$META_FILE" <<EOF
last_scan=$TODAY
version=$LATEST_VERSION
path=$LATEST_PATH
EOF
# Persist if requested
if [ "$PERSIST" = true ]; then
_update_bashrc "$PYTHON_DIR"
fi
}
# Helper: Update ~/.bashrc with latest Python path
_update_bashrc() {
cli_info " "
local PYTHON_DIR="$1"
local BASHRC="$HOME/.bashrc"
if grep -q "export PATH=.*python" "$BASHRC"; then
sed -i "s|export PATH=.*python.*|export PATH=\"$PYTHON_DIR:\$PATH\"|" "$BASHRC"
cli_info "Updated Python path in $BASHRC"
else
cli_info "export PATH=\"$PYTHON_DIR:\$PATH\"" >> "$BASHRC"
cli_info "Added Python path to $BASHRC"
fi
}
# Helper: Remove Python PATH from ~/.bashrc
_remove_bashrc() {
cli_info " "
local BASHRC="$HOME/.bashrc"
if grep -q "export PATH=.*python" "$BASHRC"; then
sed -i "/export PATH=.*python.*/d" "$BASHRC"
cli_info "Removed Python path from $BASHRC"
else
cli_error "No Python path entry found in $BASHRC"
fi
}
# =====================================================================
# Add JRE location as environment variable
export EXE4J_JAVA_HOME="/c/laragon/bin/Java/jdk-25.0.1+8-jre/bin"
# =====================================================================
# Required basic aliases. Others added tot he .aliases file
add_alias la 'ls -ah'
add_alias ll 'ls -lah'
add_alias ls 'ls -F --color=auto --show-control-chars'
# =====================================================================
# Add tools and environments to PATH
# ---------------------------------------------------------------------
# All Computers
add_to_path --force "./vendor/bin"
add_to_path --force "./.venv/Scripts"
add_to_path --force "./.venv/bin"
add_to_path "$HOME/appdata/roaming/python/python311/site-packages"
# ---------------------------------------------------------------------
# TAFE Computers
add_to_path "/c/ProgramData/Laragon/bin/mailpit"
add_to_path "/c/ProgramData/Laragon/bin/gh/bin"
add_to_path "/c/ProgramData/Laragon/bin/pie"
add_to_path "/c/ProgramData/Laragon/bin/mongodb/mongodb-8.0.8/bin"
add_to_path "/c/ProgramData/Laragon/bin/mongodb/mongodb-shell"
add_to_path "/c/ProgramData/Laragon/usr/bin/"
add_to_path "/c/ProgramData/Laragon/bin/mqtt/emqx/bin"
add_to_path "/c/ProgramData/Laragon/bin/utils"
add_to_path "/c/ProgramData/Laragon/bin/mqtt/mosquitto"
add_to_path "/c/ProgramData/Laragon/bin/marp"
add_to_path "/c/ProgramData/Laragon/bin/mqtt/nanomq/bin"
# ---------------------------------------------------------------------
# TDM and Home Computers
add_to_path /c/Laragon/bin/mailpit
add_to_path /c/Laragon/bin/gh/bin
add_to_path /c/Laragon/bin/pie
add_to_path /c/Laragon/bin/mongodb/mongodb-8.0.8/bin
add_to_path /c/Laragon/bin/mongodb/mongodb-shell
add_to_path /c/Laragon/usr/bin
add_to_path /c/Laragon/bin/utils
add_to_path /c/Laragon/bin/marp
add_to_path /c/Laragon/bin/mqtt/emqx/bin
add_to_path /c/Laragon/bin/mqtt/mosquitto
add_to_path /c/Laragon/bin/mqtt/nanomq/bin
add_to_path "/c/Program\ Files/Erlang\ OTP/bin/"
add_to_path "/C/laragon/bin/DbVisualizer"
add_to_path "/C/laragon/bin/Java/jdk-25.0.1+8-jre/bin"
#
# Any Windows PC
add_to_path "/c/Program Files/7-Zip"
# =====================================================================
# Source aliases if available
[ -f "$HOME/.aliases" ] && source "$HOME/.aliases"
# =====================================================================
cli_blank_f " "
find_latest_python
cli_blank_f " "
# =====================================================================
# End-of-initialization message (single line) and cleanup
cli_blank " "
cli_completed
# =====================================================================
# Greetings
# ---------------------------------------------------------------------
# Time-based greeting
cli_blank " "
HOUR=$(date "+%H")
case $HOUR in
[0-9]|1[0-1]) cli_info "Good morning" ;;
1[2-7]) cli_info "Good afternoon" ;;
*) cli_info "Good evening" ;;
esac
# ---------------------------------------------------------------------
# Welcome message
cli_blank "Welcome ${USER:-$USERNAME}, to Bash on $HOSTNAME."
cli_blank "Today's date is: $(date +"%A, %d-%m-%Y")"
cli_blank " "
unset CLI_OUTPUT
unset __cli_out_raw __cli_out_norm __cli_tokens __cli_preset __cli_allow_list