Add git support to fresh prompt theme
This commit is contained in:
		
							parent
							
								
									aa4d1ddd85
								
							
						
					
					
						commit
						8438118a87
					
				| @ -1,8 +1,6 @@ | |||||||
| visible_length() { |  | ||||||
|   echo $(( ${#${(S%%)1//(\%(KF1]|)\{*\}|\%[Bbkf])}} )) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| prompt_fresh_setup() { | prompt_fresh_setup() { | ||||||
|  |   compile_git_prompt | ||||||
|  | 
 | ||||||
|   autoload -U add-zsh-hook |   autoload -U add-zsh-hook | ||||||
|   add-zsh-hook precmd fresh_precmd |   add-zsh-hook precmd fresh_precmd | ||||||
| 
 | 
 | ||||||
| @ -23,25 +21,151 @@ prompt_fresh_setup() { | |||||||
| 
 | 
 | ||||||
|   # TODO: RPS1 |   # TODO: RPS1 | ||||||
| 
 | 
 | ||||||
|   prompt_opts=(cr sp subst percent) |   prompt_opts=(cr percent sp subst) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | prompt_cleanup() { | ||||||
|  |   if [ -f ~/.cache/zsh/git-prompt ]; then rm ~/.cache/zsh/git-prompt; fi | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fresh_precmd() { | fresh_precmd() { | ||||||
|  |   # First get the last commands exit code before doing anything | ||||||
|   local exit_code=$? |   local exit_code=$? | ||||||
|   if [[ $exit_code -ne 0 ]]; then |  | ||||||
|     local result="%{%B%F{1}%}$exit_code%{%f%b%}" |  | ||||||
|   fi |  | ||||||
| 
 | 
 | ||||||
|  |   # Construct the time and directory portions of the prompt | ||||||
|   local time_stamp="%{%F{244}%}%D{%H:%M:%S}%{%f%}" |   local time_stamp="%{%F{244}%}%D{%H:%M:%S}%{%f%}" | ||||||
|   local directory="%{%F{37}%}%~%{%f%}" |   local directory="%{%F{37}%}%~%{%f%}" | ||||||
| 
 | 
 | ||||||
|   # TODO: git status |   # Check we are in a git repository | ||||||
|  |   if `git rev-parse --git-dir > /dev/null 2>&1`; then | ||||||
|  |     # Get git branch name & exit early if not found | ||||||
|  |     local branch="`git symbolic-ref HEAD 2> /dev/null`" | ||||||
|  |     if [ "" = "$branch" ]; then | ||||||
|  |       local branch="`git rev-parse --abbrev-ref HEAD`" | ||||||
|  |       if [ "HEAD" = "$branch" ]; then | ||||||
|  |         local branch="`git rev-parse --short $branch`" | ||||||
|  |       fi | ||||||
|  |     fi | ||||||
| 
 | 
 | ||||||
|   local line="$time_stamp $directory" |     if [ "$branch" != "" ]; then | ||||||
|  |       local branch=${branch#refs/heads/} | ||||||
|  |       # Get the number of commits ahead/behind from the remote branch | ||||||
|  |       local remote="`git config branch.$branch.remote 2> /dev/null`" | ||||||
|  |       if [ "" != "remote" ]; then | ||||||
|  |         local branches="refs/remotes/$remote/$branch...HEAD" | ||||||
|  |         local nahead=`git rev-list --right-only $branches --count 2> /dev/null` | ||||||
|  |         if [ "0" -ne "$nahead" ]; then local ahead="↑$nahead"; fi | ||||||
|  |         local nbehind=`git rev-list --left-only $branches --count 2> /dev/null` | ||||||
|  |         if [ "0" -ne "$nbehind" ]; then local behind="↓$nbehind"; fi | ||||||
|  |       fi | ||||||
| 
 | 
 | ||||||
|   local length=`visible_length "$line$result"` |       # Construct the git prompt | ||||||
|  |       local git="%{%F{66}%}$branch%{%f%}$ahead$behind " | ||||||
| 
 | 
 | ||||||
|   print -P "$line${(l:COLUMNS - $length - 1:: :)}$result" |       if [ -f ~/.cache/zsh/git-prompt ]; then | ||||||
|  |         # Get the change counts from git-prompt | ||||||
|  |         local counts=(`~/.cache/zsh/git-prompt`) | ||||||
|  | 
 | ||||||
|  |         # Parse the results from git-prompt | ||||||
|  |         if [ 0 -eq ${#counts[@]} ]; then # clean | ||||||
|  |           local git="$git%{%B%F{2}%}✓%{%f%b%}"; | ||||||
|  |         else | ||||||
|  |           if [ 0 != $counts[1] ]; then  # indexed | ||||||
|  |             local git="$git%{%F{2}%}*$counts[1]%{%f%}" | ||||||
|  |           fi | ||||||
|  |           if [ 0 != $counts[2] ]; then  # modified | ||||||
|  |             local git="$git%{%F{1}%}+$counts[2]%{%f%}"; | ||||||
|  |           fi | ||||||
|  |           if [ 0 != $counts[3] ]; then  # deleted | ||||||
|  |             local git="$git%{%F{1}%}-$counts[3]%{%f%}"; | ||||||
|  |           fi | ||||||
|  |           if [ 0 != $counts[4] ]; then  # unmerged | ||||||
|  |             local git="$git%{%B%F{1}%}×$counts[4]%{%f%b%}"; | ||||||
|  |           fi | ||||||
|  |           if [ 0 != $counts[5] ]; then  # untracked | ||||||
|  |             local git="$git%{%F{1}%}…%{%f%}"; | ||||||
|  |           fi | ||||||
|  |         fi | ||||||
|  |       fi | ||||||
|  |     fi | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   # Construct the prompt string | ||||||
|  |   local line="$time_stamp $directory $git" | ||||||
|  | 
 | ||||||
|  |   # Print the first line of the prompt | ||||||
|  |   if [[ $exit_code -eq 0 ]]; then | ||||||
|  |     print -P "$line" | ||||||
|  |   else | ||||||
|  |     # The last command failed, display its error code at the right | ||||||
|  |     local result="%{%B%F{1}%}$exit_code%{%f%b%}" | ||||||
|  |     local length=`visible_length "$line$result"` | ||||||
|  |     print -P "$line${(l:COLUMNS - $length - 1:: :)}$result" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | visible_length() { | ||||||
|  |   echo $(( ${#${(S%%)1//(\%(KF1]|)\{*\}|\%[Bbkf])}} )) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | compile_git_prompt() { | ||||||
|  |   # Compile a simple C executable which parses the output of `git status | ||||||
|  |   # --procelain` to greatly decrease the time taken to render the prompt | ||||||
|  |   if [ ! -d ~/.cache/zsh ]; then mkdir -p ~/.cache/zsh; fi | ||||||
|  |   if [ ! -f ~/.cache/zsh/git-prompt ]; then | ||||||
|  |     cc -x c -std=gnu99 -O3 -DNDEBUG -o ~/.cache/zsh/git-prompt - << EOF | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | 
 | ||||||
|  | int main() { | ||||||
|  |   FILE *file = popen("git status --porcelain", "r"); | ||||||
|  |   if (NULL == file) { return 0; } | ||||||
|  | 
 | ||||||
|  |   char status[2048]; | ||||||
|  |   int indexed = 0, modified = 0, deleted = 0, untracked = 0, unmerged = 0; | ||||||
|  | 
 | ||||||
|  |   while (NULL != fgets(status, sizeof(status) - 1, file)) { | ||||||
|  |     char X = status[0]; | ||||||
|  |     char Y = status[1]; | ||||||
|  | 
 | ||||||
|  |     if (X == '?' && Y == '?') { | ||||||
|  |       ++untracked; | ||||||
|  |     } else if ((X == 'A' && (Y == 'A' || Y == 'U')) || | ||||||
|  |                (X == 'D' && (Y == 'D' || Y == 'U')) || | ||||||
|  |                (X == 'U' && (Y == 'A' || Y == 'D' || Y == 'D' || Y == 'U'))) { | ||||||
|  |       ++unmerged; | ||||||
|  |     } else { | ||||||
|  |       switch (X) { | ||||||
|  |       case ' ': | ||||||
|  |         switch (Y) { | ||||||
|  |           case 'M': ++modified; break; | ||||||
|  |           case 'D': ++deleted; break; | ||||||
|  |         } break; | ||||||
|  |       case 'D': ++indexed; | ||||||
|  |         switch (Y) { | ||||||
|  |           case ' ': break; | ||||||
|  |           case 'M': ++modified; break; | ||||||
|  |         } break; | ||||||
|  |       case 'M': case 'A': case 'R': case 'C': ++indexed; | ||||||
|  |         switch (Y) { | ||||||
|  |           case ' ': break; | ||||||
|  |           case 'M': ++modified; break; | ||||||
|  |           case 'D': ++deleted; break; | ||||||
|  |         } break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   pclose(file); | ||||||
|  | 
 | ||||||
|  |   if (indexed || modified || deleted || unmerged || untracked) { | ||||||
|  |     printf("%d %d %d %d %d", indexed, modified, deleted, unmerged, untracked); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | EOF | ||||||
|  |   fi | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| prompt_fresh_setup "$@" | prompt_fresh_setup "$@" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user