zsh/.prompt.zsh

# zsh/.prompt.zsh -- a pure-prompt inspired two-line prompt in plain zsh.
#
# Why roll my own instead of using pure/starship/p10k:
#   * I want zero runtime dependencies on a fresh box.
#   * I want it to stay snappy over a laggy ssh.
# The prompt renders the last exit code, current dir, git branch + dirty
# marker, and a ' $ ' (red on failure). Async git probing keeps cd fast.

autoload -Uz add-zsh-hook vcs_info
setopt PROMPT_SUBST

zstyle ':vcs_info:*' enable git
zstyle ':vcs_info:git:*' formats       ' %F{244}%b%f'
zstyle ':vcs_info:git:*' actionformats ' %F{244}%b|%a%f'

typeset -g _dot_prompt_git=""

_dot_prompt_git_async() {
  # Runs in a subshell, writes status into a file; the precmd hook reads
  # the file and re-draws. Keeps the foreground prompt instant even in
  # huge monorepos.
  local repo_root status_line
  repo_root=$(command git rev-parse --show-toplevel 2>/dev/null) || return
  local dirty=""
  if ! command git diff --quiet --ignore-submodules=dirty 2>/dev/null; then
    dirty="*"
  elif ! command git diff --cached --quiet 2>/dev/null; then
    dirty="+"
  fi
  local branch
  branch=$(command git symbolic-ref --quiet --short HEAD 2>/dev/null || command git describe --tags --exact-match 2>/dev/null || command git rev-parse --short HEAD 2>/dev/null)
  printf '%s%s' "$branch" "$dirty" > "${_dot_prompt_cache:?}"
  kill -USR1 $$ 2>/dev/null || true
}

_dot_prompt_precmd() {
  local last=$?
  vcs_info
  _dot_prompt_last_exit=$last
  _dot_prompt_cache="${TMPDIR:-/tmp}/zsh-prompt-$$"
  # Launch async probe if inside a git repo.
  if command git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
    ( _dot_prompt_git_async & ) &!
  else
    _dot_prompt_git=""
  fi
}

_dot_prompt_on_usr1() {
  [[ -r "$_dot_prompt_cache" ]] || return
  _dot_prompt_git=" %F{244}$(<"$_dot_prompt_cache")%f"
  rm -f "$_dot_prompt_cache"
  zle -I
  zle reset-prompt 2>/dev/null || true
}

trap '_dot_prompt_on_usr1' USR1
add-zsh-hook precmd _dot_prompt_precmd

_dot_prompt_exit_badge() {
  if (( _dot_prompt_last_exit != 0 )); then
    print -n -- "%F{red}[$_dot_prompt_last_exit]%f "
  fi
}

_dot_prompt_venv() {
  [[ -n $VIRTUAL_ENV ]] || return
  print -n -- " %F{244}(${VIRTUAL_ENV:t})%f"
}

_dot_prompt_jobs() {
  # Show jobs count only when non-zero so the normal line stays tidy.
  jobs -l | awk 'END { if (NR) printf " %%F{244}⚙%d%%f", NR }'
}

# Arrow colour: green on success, red on failure. Plain ASCII '$' so the
# prompt still copies cleanly in terminals without a nerd font.
_dot_prompt_arrow() {
  if (( _dot_prompt_last_exit == 0 )); then
    print -n -- '%F{green}$%f '
  else
    print -n -- '%F{red}$%f '
  fi
}

PROMPT='$(_dot_prompt_exit_badge)%F{cyan}%~%f${vcs_info_msg_0_}${_dot_prompt_git}$(_dot_prompt_venv)$(_dot_prompt_jobs)
$(_dot_prompt_arrow)'

RPROMPT='%F{244}%*%f'

# Continuation prompt: show which construct we are inside (quote, brace...)
PROMPT2='%F{244}%_%f > '

# Select / menu prompt.
PROMPT3='?# '

# Shortcut for opting out on slow sshfs mounts.
if [[ -n ${DOT_PROMPT_PLAIN:-} ]]; then
  PROMPT='%n@%m:%~ %# '
  RPROMPT=""
fi