From 4cdbad53ae7da620e76d56439a6691d587b075d9 Mon Sep 17 00:00:00 2001 From: steffen Date: Sat, 24 Jan 2026 02:18:55 +0000 Subject: [PATCH] Add ps1.sh --- ps1.sh | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 ps1.sh diff --git a/ps1.sh b/ps1.sh new file mode 100644 index 0000000..be7249a --- /dev/null +++ b/ps1.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash +# ps1.sh - Bash PS1 with emoji + optional animation helpers +# Source this file: source /path/to/ps1.sh +# Then enable: ps1_on +# Optional animate: psanimate 0.5 +# Stop animation: psanimate_stop +# Disable: ps1_off + +# Only for interactive bash +case "$-" in + *i*) ;; + *) return 0 ;; +esac + +# ---- Emoji pools (edit these) ---- +# Keep them as simple strings; terminals must support the emoji glyphs. +__PS1_EMOJI_FUN=( "๐Ÿš€" "โœจ" "๐Ÿ”ฅ" "๐ŸŒˆ" "๐Ÿง " "๐Ÿ› ๏ธ" "๐Ÿ“ฆ" "๐Ÿงฉ" "๐Ÿงช" "โšก" "๐Ÿง" "๐Ÿ›ฐ๏ธ" ) + +# ---- Emoji function (simple random) ---- +_ps1_emoji() { + local n="${#__PS1_EMOJI_FUN[@]}" + # RANDOM is bash built-in + printf '%s' "${__PS1_EMOJI_FUN[RANDOM % n]}" +} + +# ---- Your PS1 core (edit to taste) ---- +# This is intentionally simple: time, jobs, host, cwd, emoji. +# Use \\[ \\] around non-printing escape sequences to keep line editing sane. +_ps1_build() { + local emoji="$(_ps1_emoji)" + # Colors: 35 (purple) + 38 (cyan-ish) from your earlier style + printf '%b' \ +"\[\e[0m\]\[\e[38;5;35m\]โ•ญโ”€(\[\e[38;5;38m\]\t\[\e[38;5;35m\])-(\[\e[38;5;38m\]\j\[\e[38;5;35m\])-(\[\e[38;5;38m\]\H\[\e[38;5;35m\])-(\[\e[38;5;38m\]\w\[\e[38;5;35m\])\n\[\e[38;5;35m\]โ•ฐโ”€โ”€${emoji} \[\e[0m\]" +} + +# ---- PROMPT_COMMAND hook (updates PS1 each prompt) ---- +# We add our updater without nuking an existing PROMPT_COMMAND. +__PS1_PREV_PROMPT_COMMAND="" + +_ps1_set_prompt_command() { + # Save existing PROMPT_COMMAND once + if [[ -z "${__PS1_PREV_PROMPT_COMMAND+x}" || -z "$__PS1_PREV_PROMPT_COMMAND" ]]; then + __PS1_PREV_PROMPT_COMMAND="${PROMPT_COMMAND-}" + fi + + local updater='_PS1=$(_ps1_build); export PS1="$_PS1"' + if [[ -z "${PROMPT_COMMAND-}" ]]; then + PROMPT_COMMAND="$updater" + else + # Avoid duplicating if user runs ps1_on multiple times + case "$PROMPT_COMMAND" in + *"_ps1_build"*) : ;; + *) + PROMPT_COMMAND="$updater; $PROMPT_COMMAND" + ;; + esac + fi +} + +_ps1_restore_prompt_command() { + PROMPT_COMMAND="${__PS1_PREV_PROMPT_COMMAND-}" +} + +# ---- Public controls ---- +ps1_on() { + _ps1_set_prompt_command + # Force immediate update + _PS1="$(_ps1_build)"; export PS1="$_PS1" +} + +ps1_off() { + psanimate_stop >/dev/null 2>&1 || true + _ps1_restore_prompt_command +} + +# ---- Animation helpers (simple loop that forces prompt refresh) ---- +# This follows the same basic idea as in the Medium post: background loop updates prompt periodically. :contentReference[oaicite:2]{index=2} +__PSANIMATE_PIDFILE="/tmp/psanimatepid-$$" + +psanimate() { + local interval="${1:-0.5}" + + # Stop existing animator for this shell, if any + psanimate_stop >/dev/null 2>&1 || true + + # Ensure prompt is enabled + ps1_on + + ( + while :; do + # Trigger a prompt rebuild by setting PS1; next prompt draw will use it. + _PS1="$(_ps1_build)"; export PS1="$_PS1" + sleep "$interval" + done + ) & + + echo "$!" > "$__PSANIMATE_PIDFILE" +} + +psanimate_stop() { + if [[ -f "$__PSANIMATE_PIDFILE" ]]; then + local pid + pid="$(cat "$__PSANIMATE_PIDFILE" 2>/dev/null || true)" + if [[ -n "${pid:-}" ]]; then + kill "$pid" 2>/dev/null || true + fi + rm -f "$__PSANIMATE_PIDFILE" + fi +}