zsh/prompt_fresh_setup
Kenneth Benzie (Benie) 85d5d549a5 Add RPS1 support to fresh prompt theme
* Python virtualenv name
* Docker machine name
2017-11-29 15:51:39 +00:00

185 lines
5.2 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

prompt_fresh_setup() {
compile_git_prompt
autoload -U add-zsh-hook
add-zsh-hook precmd fresh_precmd
if [ "$USERNAME" = "root" ]; then
local user="%{%F{9}%}%n%{%f%}"
else
local user="%{%F{35}%}%n%{%f%}"
fi
if [ "$SSH_CONNECTION" != "" ]; then
local user="%{%F{35}%}$user%{%f%}@%{%F{244}%}%M%{%f%}"
fi
local length=`visible_length "$user"`
PS1="«$user» "
PS2="${(l:$length + 1:: :)}» "
RPS1='$(fresh_rprompt)'
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=$?
# Construct the time and directory portions of the prompt
local time_stamp="%{%F{244}%}%D{%H:%M:%S}%{%f%}"
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
# 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
}
fresh_rprompt() {
rprompt=""
if [[ ! -z "$DOCKER_MACHINE_NAME" ]]; then
rprompt="$rprompt %{%F{3}%}$DOCKER_MACHINE_NAME%{%f%}"
fi
if [[ ! -z "$VIRTUAL_ENV" ]]; then
rprompt="$rprompt %{%F{3}%}$(basename $VIRTUAL_ENV)%{%f%}"
fi
echo $rprompt
}
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 "$@"
# vim:ft=zsh