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() {
|
||||
compile_git_prompt
|
||||
|
||||
autoload -U add-zsh-hook
|
||||
add-zsh-hook precmd fresh_precmd
|
||||
|
||||
@ -23,25 +21,151 @@ prompt_fresh_setup() {
|
||||
|
||||
# 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() {
|
||||
# First get the last commands exit code before doing anything
|
||||
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 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
|
||||
|
||||
# Construct the git prompt
|
||||
local git="%{%F{66}%}$branch%{%f%}$ahead$behind "
|
||||
|
||||
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 "$@"
|
||||
|
Loading…
x
Reference in New Issue
Block a user