| 1 | #!/bin/bash |
| 2 | |
| 3 | # Parrot shell hook - source this in your .bashrc or .zshrc |
| 4 | |
| 5 | # Path to parrot binary - update this if needed |
| 6 | PARROT_BIN="parrot" |
| 7 | |
| 8 | # Function to check if parrot binary exists |
| 9 | parrot_check() { |
| 10 | if ! command -v "$PARROT_BIN" &> /dev/null; then |
| 11 | echo "⚠️ Parrot binary not found. Make sure 'parrot' is in your PATH." |
| 12 | return 1 |
| 13 | fi |
| 14 | return 0 |
| 15 | } |
| 16 | |
| 17 | # Function called after each command in bash |
| 18 | parrot_prompt_command() { |
| 19 | local exit_code=$? |
| 20 | local last_cmd=$(history 1 | sed 's/^[ ]*[0-9]*[ ]*//') |
| 21 | |
| 22 | # Only mock if command failed and we have a command |
| 23 | if [ $exit_code -ne 0 ] && [ -n "$last_cmd" ] && parrot_check; then |
| 24 | # Run parrot in background to avoid blocking shell if PARROT_ASYNC is set |
| 25 | if [ "${PARROT_ASYNC:-}" = "true" ]; then |
| 26 | "$PARROT_BIN" mock "$last_cmd" "$exit_code" & |
| 27 | else |
| 28 | "$PARROT_BIN" mock "$last_cmd" "$exit_code" |
| 29 | fi |
| 30 | fi |
| 31 | } |
| 32 | |
| 33 | # Function called before each command in zsh |
| 34 | parrot_preexec() { |
| 35 | PARROT_LAST_CMD="$1" |
| 36 | } |
| 37 | |
| 38 | # Function called after each command in zsh |
| 39 | parrot_precmd() { |
| 40 | local exit_code=$? |
| 41 | |
| 42 | # Only mock if command failed and we have a command |
| 43 | if [ $exit_code -ne 0 ] && [ -n "$PARROT_LAST_CMD" ] && parrot_check; then |
| 44 | # Run parrot in background to avoid blocking shell if PARROT_ASYNC is set |
| 45 | if [ "${PARROT_ASYNC:-}" = "true" ]; then |
| 46 | "$PARROT_BIN" mock "$PARROT_LAST_CMD" "$exit_code" & |
| 47 | else |
| 48 | "$PARROT_BIN" mock "$PARROT_LAST_CMD" "$exit_code" |
| 49 | fi |
| 50 | fi |
| 51 | } |
| 52 | |
| 53 | # Setup based on shell type (only show messages if not already initialized) |
| 54 | if [ -z "$PARROT_INITIALIZED" ]; then |
| 55 | if [ -n "$BASH_VERSION" ]; then |
| 56 | # Bash setup |
| 57 | PROMPT_COMMAND="parrot_prompt_command${PROMPT_COMMAND:+;$PROMPT_COMMAND}" |
| 58 | echo "🦜 Parrot is now watching your bash commands..." |
| 59 | elif [ -n "$ZSH_VERSION" ]; then |
| 60 | # Zsh setup |
| 61 | autoload -Uz add-zsh-hook |
| 62 | add-zsh-hook preexec parrot_preexec |
| 63 | add-zsh-hook precmd parrot_precmd |
| 64 | echo "🦜 Parrot is now watching your zsh commands..." |
| 65 | else |
| 66 | echo "⚠️ Parrot: Unsupported shell. Only bash, zsh, and fish are supported." |
| 67 | echo "💡 For fish shell, use parrot-hook.fish instead." |
| 68 | fi |
| 69 | |
| 70 | # Show performance tip |
| 71 | if [ "${PARROT_ASYNC:-}" != "true" ]; then |
| 72 | echo "💡 Tip: Set PARROT_ASYNC=true to prevent terminal hangs on slow networks" |
| 73 | fi |
| 74 | |
| 75 | # Mark as initialized for this shell session |
| 76 | export PARROT_INITIALIZED=1 |
| 77 | else |
| 78 | # Silent re-initialization (e.g., when sourcing .zshrc again) |
| 79 | if [ -n "$BASH_VERSION" ]; then |
| 80 | PROMPT_COMMAND="parrot_prompt_command${PROMPT_COMMAND:+;$PROMPT_COMMAND}" |
| 81 | elif [ -n "$ZSH_VERSION" ]; then |
| 82 | autoload -Uz add-zsh-hook |
| 83 | add-zsh-hook preexec parrot_preexec |
| 84 | add-zsh-hook precmd parrot_precmd |
| 85 | fi |
| 86 | fi |