Translate the parse_git_branch function to zsh from bash (for a hint)

I use 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 decided to use zsh. Although I can use this as a shell script (even without shebang) in my .zshrc, the error is a parse error on this line if [[ ! ${git_status}} if [[ ! ${git_status}} ...

What do I need to do to prepare it for zshell?

Edit: The "actual error" I get is " parse error near } , and it refers to a weird double }} that runs on Bash.

Edit: Here is the last 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' 

Thank you all for your patience and help.

Edit: The best answer taught us all: git status is china (UI). Good scenarios go against GIT plumbing. Here's the final function:

 # The latest version of Chris' function below 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' 

Please note that only the invitation is zsh specific. In Bash, this will be your invitation plus "\$(parse_git_branch)" .

It may be slower (more GIT calls, but this is an empirical question), but it will not be violated by changes in GIT (they do not change the plumbing). And this is very important for a good forward script.

+7
git bash zsh
source share
7 answers

You must really use the git "plumbing" commands to extract the information you need. The output from porcelain teams (for example, git status ) may change over time, but the behavior of the plumbing teams is much more stable.

With porcelain interfaces, this can also be done without "basisms" or "zshisms" (ie, the correspondence operator =~ ):

 parse_git_branch() { in_wd="$(git rev-parse --is-inside-work-tree 2>/dev/null)" || return test "$in_wd" = true || return state='' git update-index --refresh -q >/dev/null # avoid false positives with diff-index if git rev-parse --verify HEAD >/dev/null 2>&1; then git diff-index HEAD --quiet 2>/dev/null || state='*' else state='#' fi ( d="$(git rev-parse --show-cdup)" && cd "$d" && test -z "$(git ls-files --others --exclude-standard .)" ) >/dev/null 2>&1 || state="${state}+" branch="$(git symbolic-ref HEAD 2>/dev/null)" test -z "$branch" && branch='<detached-HEAD>' echo "${branch#refs/heads/}${state}" } 

The integration of the output into the prompt still depends on the shell (i.e. escape or quote $ (for bash and zsh) and for setting PROMPT_SUBST (for zsh)).

+5
source share

Get rid of extra } ? ${git_status}} must be ${git_status} .


After removing the optional } only potential problem that I see is the use of ${BASH_REMATCH[1]} . You can use this in zsh, but you need to enable this option to do this. Since zsh docs on conditional expressions show, you will need to use something like

 if [[ ${git_status} =~ ${pattern} ]]; then branch=${match[1]} echo "(${branch}${state})" fi 
+2
source share

You can use the match array instead of $BASH_REMATCH . You can also avoid the extra closing braces.

Unverified:

 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=${match[1]} echo "(${branch}${state})" fi } 

Give a try and see if it helps.

+2
source share

If you do not want to learn zsh, I would suggest you use a different language, such as Python, for such a parsing.

Check out the git status of the Python analyzer and the zsh-git -prompt project on github to find out how to get a nice zsh prompt for git.

+1
source share

If you get an error failed to compile regex: illegal byte sequence , then remove NULL from IFS. (Replace ${IFS} with ${IFS//$'\0'/} ).

+1
source share

Perhaps this zsh git repository will contain tests that may give you some hints:

0
source share

Just in case, if anyone is interested in seeing an alternative solution to the git -prompt function, I posted this script on github.com, but to make it easier, you can get it here.

It works great for me, hope he does the same with you.

 ## Setting Prompt Colour(s): invColor="$(tput rev)"; ## tput rev - Inverse resColor="$(tput sgr0)"; ## tput sgr0 - Reset ## Custom Prompt Colour(s): _BlackBG="$(tput setab 0)"; bGreenFG="$(tput bold; tput setaf 2)"; bMagentaFG="$(tout bold; tput setaf 5)"; bRedFG="$(tput bold; tput setaf 1)"; bBlueFG="$(tput bold; tput setaf 4)"; bCyanFG="$(tput bold; tput setaf 6)"; bWhiteFG="$(tput bold; tput setaf 7)"; ## Define Enclosing-character(s): _Bracket="${resColor}${_BlackBG}${bWhiteFG}"; oBracket="${_Bracket}["; cBracket="${_Bracket}]${resColor}"; ## Bold-Foreground Color(s): ## tput bold - Bold function git_branch () { # git_branch() { git name-rev HEAD 2> /dev/null | sed 's#HEAD\ \(.*\)#git::\1#'; } git branch --no-color 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/git::\1/'; return 0; } ## Version Control System - Active Working Copy: function get_branch () { xBranch="`git_branch`"; if [[ "${xBranch}" =~ "git::master" ]]; then xBranch="git::${bWhiteFG}master"; else xBranch="`echo ${xBranch}|sed -e 's/git:://g'`"; xBranch="branch::${bGreenFG}${xBranch}"; fi if git rev-parse --git-dir >/dev/null 2>&1; then _pVCS=""; if git diff --quiet 2>/dev/null >&2; then if [[ "${xBranch}" =~ "git::" ]]; then _pVCS="${bGreenFG}${xBranch}"; else _pVCS="${bMagentaFG}${xBranch}"; fi else _pVCS="${bRedFG}${xBranch}"; fi else return 0; fi if [[ "${_pVCS}" =~ "no branch" ]]; then xTAG="`git tags|awk '{print $3}'|sed -e 's/[,;)]//g'`"; _pVCS="${bBlueFG}tag::${bCyanFG}${xTAG}"; fi ## Output Git Active-Repo ID: if [[ "${_pVCS}" =~ [::] ]]; then echo -ne "${oBracket}${_BlackBG}${_pVCS}${cBracket}"; fi # return 0; } 

Using:

 declare PS1='\[\033[01;36m\]\u\[\033[01;31m\]@\[\033[01;32m\]\h\[\033[00m\]:\[\033[01;33m\]\w $(get_branch) \[\033[01;31m\]${XPT}\[\033[00m\] ' 
0
source share

All Articles