diff --git a/dotfiles/install/install-linux-global.sh b/dotfiles/install/install-linux-global.sh index bb3ede8..b4cb126 100644 --- a/dotfiles/install/install-linux-global.sh +++ b/dotfiles/install/install-linux-global.sh @@ -23,6 +23,8 @@ MARKER_END="# <<< dotfiles (managed) <<<" # Select install mode (PS1, banner, or both) install_ps1=1 install_banner=1 +season_mode="dynamic" +season_choice="" if [[ -t 0 ]]; then echo "Install options:" echo " 1) PS1 only" @@ -35,6 +37,39 @@ if [[ -t 0 ]]; then ""|3) install_ps1=1; install_banner=1 ;; *) echo "Invalid choice, using both."; install_ps1=1; install_banner=1 ;; esac + + if [[ "$install_ps1" -eq 1 ]]; then + echo + echo "Season mode:" + echo " 1) Dynamic (auto by date)" + echo " 2) Static (pick one season)" + read -r -p "Choose [1]: " season_mode_choice + case "${season_mode_choice}" in + 2) + season_mode="static" + echo "Pick a season:" + echo " 1) Winter" + echo " 2) Spring" + echo " 3) Summer" + echo " 4) Autumn" + read -r -p "Choose [1]: " season_pick + case "${season_pick}" in + 2) season_choice="spring" ;; + 3) season_choice="summer" ;; + 4) season_choice="autumn" ;; + ""|1) season_choice="winter" ;; + *) echo "Invalid choice, using winter."; season_choice="winter" ;; + esac + ;; + ""|1) + season_mode="dynamic" + ;; + *) + echo "Invalid choice, using dynamic." + season_mode="dynamic" + ;; + esac + fi fi if [[ "$install_banner" -eq 1 ]]; then @@ -94,8 +129,17 @@ fi if [[ "$install_ps1" -eq 1 ]]; then cp -f "$SRC_PS1" "$DST_PS1" chmod 0644 "$DST_PS1" + + { + printf 'PS1_SEASON_MODE=%s\n' "$season_mode" + if [[ "$season_mode" == "static" && -n "$season_choice" ]]; then + printf 'PS1_SEASON=%s\n' "$season_choice" + fi + } > /etc/ps1-season + chmod 0644 /etc/ps1-season else rm -f "$DST_PS1" + rm -f /etc/ps1-season fi if [[ "$install_banner" -eq 1 ]]; then diff --git a/dotfiles/install/install-macos-user.sh b/dotfiles/install/install-macos-user.sh index e029999..8730a0e 100644 --- a/dotfiles/install/install-macos-user.sh +++ b/dotfiles/install/install-macos-user.sh @@ -7,14 +7,57 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" SRC_PS1="$REPO_ROOT/ps1/ps1.sh" DST_DIR="$HOME/.config/ps1" DST_PS1="$DST_DIR/ps1.sh" +SEASON_FILE="$DST_DIR/season" MARKER_START="# >>> user ps1 (managed) >>>" MARKER_END="# <<< user ps1 (managed) <<<" +season_mode="dynamic" +season_choice="" +if [[ -t 0 ]]; then + echo "Season mode:" + echo " 1) Dynamic (auto by date)" + echo " 2) Static (pick one season)" + read -r -p "Choose [1]: " season_mode_choice + case "${season_mode_choice}" in + 2) + season_mode="static" + echo "Pick a season:" + echo " 1) Winter" + echo " 2) Spring" + echo " 3) Summer" + echo " 4) Autumn" + read -r -p "Choose [1]: " season_pick + case "${season_pick}" in + 2) season_choice="spring" ;; + 3) season_choice="summer" ;; + 4) season_choice="autumn" ;; + ""|1) season_choice="winter" ;; + *) echo "Invalid choice, using winter."; season_choice="winter" ;; + esac + ;; + ""|1) + season_mode="dynamic" + ;; + *) + echo "Invalid choice, using dynamic." + season_mode="dynamic" + ;; + esac +fi + mkdir -p "$DST_DIR" cp -f "$SRC_PS1" "$DST_PS1" chmod 0644 "$DST_PS1" +{ + printf 'PS1_SEASON_MODE=%s\n' "$season_mode" + if [[ "$season_mode" == "static" && -n "$season_choice" ]]; then + printf 'PS1_SEASON=%s\n' "$season_choice" + fi +} > "$SEASON_FILE" +chmod 0644 "$SEASON_FILE" + add_source_block() { local file="$1" [[ -f "$file" ]] || touch "$file" diff --git a/dotfiles/ps1/ps1.sh b/dotfiles/ps1/ps1.sh index 0ca9140..b36f1fc 100644 --- a/dotfiles/ps1/ps1.sh +++ b/dotfiles/ps1/ps1.sh @@ -37,6 +37,58 @@ _ps1_has_nf() { return 1 } +# Season selection (dynamic or static) +# PS1_SEASON_MODE=dynamic|static +# PS1_SEASON= winter|spring|summer|autumn +# Also reads config from /etc/ps1-season or ~/.config/ps1/season +_ps1_season_config() { + local cfg="" + if [[ -r /etc/ps1-season ]]; then + cfg="/etc/ps1-season" + elif [[ -r "$HOME/.config/ps1/season" ]]; then + cfg="$HOME/.config/ps1/season" + fi + + if [[ -n "$cfg" ]]; then + while IFS='=' read -r k v; do + k="${k//[[:space:]]/}" + v="${v//[[:space:]]/}" + case "$k" in + PS1_SEASON_MODE) export PS1_SEASON_MODE="$v" ;; + PS1_SEASON) export PS1_SEASON="$v" ;; + esac + done < "$cfg" + fi +} + +_ps1_season_dynamic() { + local mm dd m d + mm=$(TZ=Europe/Oslo date +%m); dd=$(TZ=Europe/Oslo date +%d) + m=$((10#$mm)); d=$((10#$dd)) + + if (( m >= 3 && m <= 5 )); then + echo "spring" + elif (( m >= 6 && m <= 8 )); then + echo "summer" + elif (( m == 9 || m == 10 || (m == 11 && d < 15) )); then + echo "autumn" + else + echo "winter" + fi +} + +_ps1_season() { + _ps1_season_config + local mode="${PS1_SEASON_MODE:-dynamic}" + local season="${PS1_SEASON:-}" + + if [[ "$mode" == "static" && -n "$season" ]]; then + echo "$season" + else + _ps1_season_dynamic + fi +} + # Time-based emoji (Europe/Oslo) _ps1_symbol() { local hh mm h m @@ -73,22 +125,48 @@ __PS1_SYM="" __PS1_PATH="" __PS1_STATUS=0 __PS1_USE_NF=0 +__PS1_SEASON="winter" _ps1_set_prompt() { local RST="\[\e[0m\]" - # Two-zone palette - # Zone 1: gray-blue pastel (date/time/user) - local Z1_BG="\[\e[48;5;61m\]" - local Z1_FG="\[\e[38;5;255m\]" - - # Zone 2: turquoise / cool green (host/path) - 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\]" + # Seasonal palettes (Z1 is darker than Z2) + local Z1_BG Z1_FG Z2_BG Z2_FG PATH_FG FRAME + case "$__PS1_SEASON" in + spring) + Z1_BG="\[\e[48;5;71m\]" + Z1_FG="\[\e[38;5;255m\]" + Z2_BG="\[\e[48;5;120m\]" + Z2_FG="\[\e[38;5;255m\]" + PATH_FG="\[\e[38;5;193m\]" + FRAME="\[\e[38;5;65m\]" + ;; + summer) + Z1_BG="\[\e[48;5;142m\]" + Z1_FG="\[\e[38;5;255m\]" + Z2_BG="\[\e[48;5;214m\]" + Z2_FG="\[\e[38;5;0m\]" + PATH_FG="\[\e[38;5;223m\]" + FRAME="\[\e[38;5;130m\]" + ;; + autumn) + Z1_BG="\[\e[48;5;95m\]" + Z1_FG="\[\e[38;5;255m\]" + Z2_BG="\[\e[48;5;173m\]" + Z2_FG="\[\e[38;5;255m\]" + PATH_FG="\[\e[38;5;223m\]" + FRAME="\[\e[38;5;95m\]" + ;; + *) + # winter (default) + Z1_BG="\[\e[48;5;61m\]" + Z1_FG="\[\e[38;5;255m\]" + Z2_BG="\[\e[48;5;37m\]" + Z2_FG="\[\e[38;5;255m\]" + PATH_FG="\[\e[38;5;194m\]" + FRAME="\[\e[38;5;60m\]" + ;; + esac # Status colors local OK="\[\e[38;5;76m\]" @@ -122,6 +200,7 @@ _ps1_update() { __PS1_STATUS=$? __PS1_SYM="$(_ps1_symbol)" __PS1_PATH="$(_ps1_path)" + __PS1_SEASON="$(_ps1_season)" if _ps1_has_nf; then __PS1_USE_NF=1; else __PS1_USE_NF=0; fi _ps1_set_prompt }