Move entire git-prompt to C

This commit is contained in:
2018-09-11 17:57:40 +01:00
parent 2740f9bc8d
commit 5f2c5b58da
2 changed files with 217 additions and 112 deletions

View File

@@ -1,17 +1,18 @@
prompt_fresh_help() {
echo "\
options:
-a enable almostontop like behaviour"
-a enable almostontop like behaviour
-r recompile git-prompt executable"
}
prompt_fresh_setup() {
fresh_compile_git_prompt
# Parse options
local almostontop=0
while getopts 'a' opt; do
local recompile=0
while getopts 'ar' opt; do
case $opt in
a) local almostontop=1 ;;
r) local recompile=1 ;;
*) prompt -h fresh; return 1 ;;
esac
done
@@ -31,6 +32,9 @@ prompt_fresh_setup() {
add-zsh-hook -d preexec fresh_almostontop
fi
[ $recompile -eq 1 ] && prompt_cleanup
fresh_compile_git_prompt
if [ "$USER" = "root" ]; then
local user="%{%F{1}%}%n%{%f%}"
else
@@ -50,7 +54,7 @@ prompt_fresh_setup() {
}
prompt_cleanup() {
if [ -f ~/.cache/zsh/git-prompt ]; then rm ~/.cache/zsh/git-prompt; fi
[ -f ~/.cache/zsh/git-prompt ] && rm ~/.cache/zsh/git-prompt
}
fresh_line_one() {
@@ -64,58 +68,7 @@ fresh_line_one() {
local directory="%{%F{37}%}%~%{%f%}"
# 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
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
local git=`~/.cache/zsh/git-prompt`
# If the last command failed, display its error code at the right
if [[ $exit_code -ne 0 ]]; then
@@ -145,62 +98,11 @@ fresh_almostontop() {
fresh_compile_git_prompt() {
# Compile a simple C program which parses the output of `git status
# --procelain` to greatly decrease the time taken to draw the prompt
local cache=~/.cache/zsh; [ ! -d $cache ] && mkdir -p $cache
if [ ! -f $cache/git-prompt ]; then
cc -x c -std=gnu99 -O3 -DNDEBUG -o $cache/git-prompt - 2> /dev/null << 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
[ ! -d ~/.cache/zsh ] && mkdir -p ~/.cache/zsh
if [ ! -f ~/.cache/zsh/git-prompt ]; then
cc -std=gnu99 -O3 -DNDEBUG ~/.config/zsh/git-prompt.c -o ~/.cache/zsh/git-prompt
if [ $? -ne 0 ]; then
echo "git prompt disabled, are the system development headers installed?"
echo "git-prompt was not compiled, is a C99 toolchain installed?"
fi
fi
}