prompt_fresh_help() { echo "\ options: -a enable almostontop like behaviour" } prompt_fresh_setup() { fresh_compile_git_prompt # Parse options local almostontop=0 while getopts 'a' opt; do case $opt in a) local almostontop=1 ;; *) prompt -h fresh; return 1 ;; esac done autoload -U add-zsh-hook # Hook to print the first line of the "two line" prompt, this line is not # actually part of the prompt so does not get redrawn which can sometimes # cause lines before the prompt to disappear. add-zsh-hook precmd fresh_line_one if [ $almostontop -eq 1 ]; then # Hook to clear the screen then prints the prompt with previous command at # the top of the screen. add-zsh-hook preexec fresh_almostontop else add-zsh-hook -d preexec fresh_almostontop fi if [ "$USER" = "root" ]; then local user="%{%F{1}%}%n%{%f%}" else local user="%{%F{35}%}%n%{%f%}" fi local userhost=$USER if [ "$SSH_CONNECTION" != "" ]; then local user="$user@%{%F{244}%}%M%{%f%}" local userhost="$userhost@`hostname`" fi PS1="«$user» " PS2="«${(l:${#userhost}:: :)}» " RPS1='$(fresh_rprompt)' prompt_opts=(percent sp subst) } prompt_cleanup() { if [ -f ~/.cache/zsh/git-prompt ]; then rm ~/.cache/zsh/git-prompt; fi } fresh_line_one() { # 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%}" [[ -n $SANDBOX_HOME ]] && \ local directory="%{%F{3}%}$SANDBOX_NAME${PWD#$SANDBOX_HOME}%{%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 # Print the first line of the prompt if [[ $exit_code -ne 0 ]]; then # The last command failed, display its error code at the right local result=" %{%B%F{1}%}$exit_code%{%f%b%}" fi # Construct the prompt string local line="$time_stamp $directory $git$result" print -P "$line" } 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 } fresh_almostontop() { clear fresh_line_one print -P "$PROMPT"'$1' } fresh_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 local cache=~/.cache/zsh if [ ! -d $cache ]; then mkdir -p $cache; fi if [ ! -f $cache/git-prompt ]; then cc -x c -std=gnu99 -O3 -DNDEBUG -o $cache/git-prompt - 2> /dev/null << EOF #include #include 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 if [ $? -ne 0 ]; then echo "git prompt disabled, are the system development headers installed?" fi fi } prompt_fresh_setup "$@" # vim:ft=zsh