Translate parse_git_branch function to zsh from bash (for prompt)

Posted by yar on Stack Overflow See other posts from Stack Overflow or by yar
Published on 2010-05-17T15:32:55Z Indexed on 2010/05/22 9:20 UTC
Read the original article Hit count: 213

Filed under:
|
|

I am using this function in Bash

function parse_git_branch {
  git_status="$(git status 2> /dev/null)"
  pattern="^# On branch ([^${IFS}]*)"
  if [[ ! ${git_status}} =~ "working directory clean" ]]; then
    state="*"
  fi
  # add an else if or two here if you want to get more specific

  if [[ ${git_status} =~ ${pattern} ]]; then
    branch=${BASH_REMATCH[1]}
    echo "(${branch}${state})"
  fi
}

but I'm determined to use zsh. While I can use this perfectly as a shell script (even without a shebang) in my .zshrc the error is a parse error on this line if [[ ! ${git_status}}...

What do I need to do to get it ready for zshell?

Edit: The "actual error" I'm getting is " parse error near } and it refers to the line with the strange double }}, which works on Bash.

Edit: Here's the final code, just for fun:

parse_git_branch() {
    git_status="$(git status 2> /dev/null)"
pattern="^# On branch ([^[:space:]]*)"
    if [[ ! ${git_status} =~ "working directory clean" ]]; then
        state="*"
    fi
    if [[ ${git_status} =~ ${pattern} ]]; then
      branch=${match[1]}
      echo "(${branch}${state})"
    fi
}

setopt PROMPT_SUBST
PROMPT='$PR_GREEN%n@$PR_GREEN%m%u$PR_NO_COLOR:$PR_BLUE%2c$PR_NO_COLOR%(!.#.$)'
RPROMPT='$PR_GREEN$(parse_git_branch)$PR_NO_COLOR'

Thanks to everybody for your patience and help.

Edit: The best answer has schooled us all: git status is porcelain (UI). Good scripting goes against GIT plumbing. Here's the final function:

parse_git_branch() {
    in_wd="$(git rev-parse --is-inside-work-tree 2>/dev/null)" || return
    test "$in_wd" = true || return
    state=''
    git diff-index HEAD --quiet 2>/dev/null || state='*'
    branch="$(git symbolic-ref HEAD 2>/dev/null)"
    test -z "$branch" && branch='<detached-HEAD>'
    echo "(${branch#refs/heads/}${state})"
}

PROMPT='$PR_GREEN%n@$PR_GREEN%m%u$PR_NO_COLOR:$PR_BLUE%2c$PR_NO_COLOR%(!.#.$)'
RPROMPT='$PR_GREEN$(parse_git_branch)$PR_NO_COLOR'

Note that only the prompt is zsh-specific. In Bash it would be your prompt plus "\$(parse_git_branch)".

This might be slower (more calls to GIT, but that's an empirical question) but it won't be broken by changes in GIT (they don't change the plumbing). And that is very important for a good script moving forward.

Days Later: Ugh, it turns out that diff-index HEAD is NOT the same as checking status against working directory clean. So will this mean another plumbing call? I surely don't have time/expertise to write my own porcelain....

© Stack Overflow or respective owner

Related posts about git

Related posts about bash