diff --git a/install-global-ps1.sh b/install-global-ps1.sh new file mode 100644 index 0000000..4ebb054 --- /dev/null +++ b/install-global-ps1.sh @@ -0,0 +1,179 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ "${EUID}" -ne 0 ]]; then + echo "KjΓΈr som root: sudo bash $0" + exit 1 +fi + +PS1_FILE="/etc/profile.d/ps1.sh" +BASH_BASHRC="/etc/bash.bashrc" + +MARKER_START="# >>> global ps1 (managed) >>>" +MARKER_END="# <<< global ps1 (managed) <<<" + +echo "Skriver global PS1 til: $PS1_FILE" + +# Write the PS1 module (global) +cat > "$PS1_FILE" <<'EOF' +#!/usr/bin/env bash + +# This file is loaded globally. It may be sourced from /etc/bash.bashrc. +# It must not exit the shell; only return when not interactive. + +case "$-" in + *i*) ;; + *) return 0 ;; +esac + +# ------------------------------------------------- +# Nerd Font detection + fallback controls +# Env overrides: +# PS1_FORCE_ASCII=1 -> always fallback separators +# PS1_FORCE_NF=1 -> always use Nerd Font separators +# ------------------------------------------------- +_ps1_has_nf() { + if [[ "${PS1_FORCE_ASCII:-0}" == "1" ]]; then return 1; fi + if [[ "${PS1_FORCE_NF:-0}" == "1" ]]; then return 0; fi + + if command -v fc-list >/dev/null 2>&1; then + if fc-list 2>/dev/null | grep -qi "Nerd Font"; then + return 0 + fi + fi + return 1 +} + +# ------------------------------------------------- +# Time-based emoji (Europe/Oslo) +# ------------------------------------------------- +_ps1_symbol() { + local hh mm h m + hh=$(TZ=Europe/Oslo date +%H); mm=$(TZ=Europe/Oslo date +%M) + h=$((10#$hh)); m=$((10#$mm)) + + if (( h >= 5 && h <= 8 )); then echo "πŸŒ…" + elif (( h >= 9 && h <= 10 )); then echo "β˜•" + elif (( h == 11 && m < 30 )); then echo "πŸ₯ͺ" + elif (( (h == 11 && m >= 30) || (h >= 12 && h <= 15) )); then echo "πŸ’»" + elif (( h == 16 )); then echo "🍲" + elif (( h >= 17 && h <= 22 )); then echo "πŸŒ†" + else echo "πŸŒ™" + fi +} + +# ------------------------------------------------- +# Path shortening (keeps /home/user visible) +# bash 3.2+ compatible (no negative array indexes) +# ------------------------------------------------- +_ps1_path() { + local p="$PWD" + local parts=() + IFS='/' read -ra parts <<< "$p" + + if ((${#parts[@]} < 6)); then + echo "$p" + return + fi + + local n=${#parts[@]} + local a="${parts[1]}" + local b="${parts[2]}" + local c="${parts[$((n-2))]}" + local d="${parts[$((n-1))]}" + + echo "/${a}/${b}/…/${c}/${d}" +} + +# ------------------------------------------------- +# Dynamic vars updated before each prompt +# ------------------------------------------------- +__PS1_SYM="" +__PS1_PATH="" +__PS1_STATUS=0 +__PS1_USE_NF=0 + +_ps1_update() { + __PS1_STATUS=$? + __PS1_SYM="$(_ps1_symbol)" + __PS1_PATH="$(_ps1_path)" + if _ps1_has_nf; then __PS1_USE_NF=1; else __PS1_USE_NF=0; fi +} + +# ------------------------------------------------- +# Public functions +# ------------------------------------------------- +ps1_on() { + PROMPT_COMMAND="_ps1_update" + + local RST="\[\e[0m\]" + + # Zone 1 (date/time/user): gray-blue pastel + local Z1_BG="\[\e[48;5;61m\]" + local Z1_FG="\[\e[38;5;255m\]" + + # Zone 2 (host/path): turquoise / cool green + local Z2_BG="\[\e[48;5;37m\]" + local Z2_FG="\[\e[38;5;255m\]" + local PATH_FG="\[\e[38;5;194m\]" + + # Frame + local FRAME="\[\e[38;5;60m\]" + + # Status colors + local OK="\[\e[38;5;76m\]" + local BAD="\[\e[38;5;203m\]" + + # Separators w/ fallback (NF vs non-NF) + local SEP_EXPR='\$( [ "$__PS1_USE_NF" -eq 1 ] && printf "ξ‚°" || printf "β–Ά" )' + local LEFT_EXPR='\$( [ "$__PS1_USE_NF" -eq 1 ] && printf "ξ‚Ά" || printf "[" )' + local RIGHT_EXPR='\$( [ "$__PS1_USE_NF" -eq 1 ] && printf "ξ‚΄" || printf "]" )' + + local PROMPT_SYM="\$( [ \$__PS1_STATUS -eq 0 ] && printf '${OK}' || printf '${BAD}' )➜${RST}" + + PS1="\ +${FRAME}╭─${RST}\ +${Z1_BG}${Z1_FG}${LEFT_EXPR} \d \A \u ${RST}${Z1_BG}${Z2_BG}${Z2_FG}${SEP_EXPR}${RST}\ +${Z2_BG}${Z2_FG} @\h ${PATH_FG}\${__PS1_PATH} ${RST}${Z2_BG}${Z2_FG}${RIGHT_EXPR}${RST}\ +\n${FRAME}╰── ${RST}${PROMPT_SYM} \${__PS1_SYM} " +} + +ps1_off() { + # no-op helper; users can override if needed + : +} + +# Enable by default (global standard) +ps1_on +EOF + +chmod 0644 "$PS1_FILE" + +echo "Oppdaterer $BASH_BASHRC for Γ₯ source $PS1_FILE (idempotent)" + +# Remove old managed block if present, then add +tmp="$(mktemp)" +awk -v s="$MARKER_START" -v e="$MARKER_END" ' + $0==s {inside=1; next} + $0==e {inside=0; next} + !inside {print} +' "$BASH_BASHRC" > "$tmp" +cat "$tmp" > "$BASH_BASHRC" +rm -f "$tmp" + +cat >> "$BASH_BASHRC" <