]> git.rmz.io Git - dotfiles.git/blob - zsh/lib/prompt.zsh
zsh/prompt: don't try to populate git prompt if not in git repo
[dotfiles.git] / zsh / lib / prompt.zsh
1 # Setup the prompt with pretty colors
2 setopt prompt_subst
3 autoload colors; colors;
4
5 hostcolor=green
6 [[ $(hostname) == "tardis" ]] && hostcolor=red
7
8 precmd() {
9 PROMPT='%T $(virtualenv_prompt)%n@%{$fg[$hostcolor]%}%m%(1j. $fg_bold[white]↵%{$fg_bold[red]%}%j.)%{$reset_color%}%-0>..>$(git_prompt_status)%>>
10 %(?..%{$fg_bold[white]%}%?)%{$reset_color%}$(vi_prompt_info)%{%(!.$fg[red]❰.$fg[green]❱)%1G%} '
11 RPROMPT='%{$fg[green]%}%~%{$reset_color%}'
12 }
13
14 vi_prompt_info() {
15 local vicmd="$fg_bold[green]❰$reset_color%1G"
16 local viins="$fg_bold[blue]❱$reset_color%1G"
17 local map=${KEYMAP:-viins}
18 printf '%s' "%{${${map/vicmd/$vicmd}/(main|viins)/$viins}%}"
19 }
20
21 function zle-line-init zle-line-finish zle-keymap-select {
22 zle reset-prompt
23 zle -R
24 }
25
26 # zle -N zle-line-init
27 # zle -N zle-line-finish
28 zle -N zle-keymap-select
29
30 # reset zle on resize
31 TRAPWINCH() {
32 zle && { zle reset-prompt; zle -R }
33 }
34
35 # Get the status of the working tree
36 git_prompt_status() {
37 if ! git rev-parse --is-inside-work-tree &>/dev/null; then
38 return
39 fi
40 local branch ahead behind
41 local added deleted modified renamed unmerged untracked dirty
42 # Use porcelain status for easy parsing.
43 local status_cmd="git status --porcelain -b"
44
45 # Get current status.
46 while IFS=$'\n' read line; do
47 if [[ "$line" == \#\#\ * ]]; then
48 [[ "$line" =~ '## (.*?)(\.\.\.|$)' ]] && branch=$match[1]
49 [[ "$line" =~ 'ahead ([0-9]+)' ]] && ahead=$match[1]
50 [[ "$line" =~ 'behind ([0-9]+)' ]] && behind=$match[1]
51 else
52 # Count added, deleted, modified, renamed, unmerged, untracked, dirty.
53 # T (type change) is undocumented, see http://git.io/FnpMGw.
54 # index
55 [[ "$line" == M[\ MTD]\ * ]] && (( updated++ ))
56 [[ "$line" == [AC][\ MTD]\ * ]] && (( added++ ))
57 [[ "$line" == D[\ MT]\ * ]] && (( deleted++ ))
58 [[ "$line" == R[\ MTD]\ * ]] && (( renamed++ ))
59
60 # work tree
61 [[ "$line" == [\ MARCT]M\ * ]] && (( modified++ ))
62 [[ "$line" == [\ MARCT]D\ * ]] && (( deleted_wt++ ))
63 [[ "$line" == \?\?\ * ]] && (( untracked++ ))
64
65 # morge conflicts
66 [[ "$line" == (AA|DD|U?|?U)\ * ]] && (( unmerged++ ))
67 fi
68 done < <(${(z)status_cmd} 2> /dev/null)
69
70 local git_status=" %{$fg[yellow]%}"
71
72 # Format branch
73 if [[ -n $branch ]]; then
74 git_status+="$branch"
75 else
76 git_status+="$(git rev-parse --short HEAD 2> /dev/null)"
77 [[ $? -ne 0 ]] && return
78 fi
79
80 # Format upstream
81 local upstream_str
82 (( ahead > 0 )) && upstream_str+="%{$fg[blue]%} >$ahead"
83 (( behind > 0 )) && upstream_str+="%{$fg[blue]%} <$behind"
84 git_status+="$upstream_str"
85
86 # Format stashed
87 stashed=$(git stash list | wc -l)
88 if (( stashed > 0 )) then
89 stashed_str+="%{$fg_bold[cyan]%} ⋎$stashed%{$reset_color%}"
90 fi
91 git_status+="$stashed_str"
92
93 # Format index
94 local index_str
95 (( updated > 0 )) && index_str+="%{$fg[green]%} *$updated"
96 (( added > 0 )) && index_str+="%{$fg[green]%} +$added"
97 (( deleted > 0 )) && index_str+="%{$fg[green]%} -$deleted"
98 (( renamed > 0 )) && index_str+="%{$fg[green]%} ≈$renamed"
99 git_status+="$index_str"
100
101 # Format working tree
102 local wt_str
103 (( modified > 0 )) && wt_str+="%{$fg[red]%} *$modified"
104 (( deleted_wt > 0 )) && wt_str+="%{$fg[red]%} -$deleted_wt"
105 (( untracked > 0 )) && wt_str+="%{$fg[red]%} +$untracked"
106 (( unmerged > 0 )) && wt_str+="%{$fg[magenta]%} ♒$unmerged"
107 git_status+="$wt_str"
108
109 git_status+="%{$reset_color%}"
110
111 echo $git_status
112 }
113
114 function virtualenv_prompt() {
115 if [[ -z $VIRTUAL_ENV ]] then
116 echo ""
117 else
118 echo "(${VIRTUAL_ENV##*/}) "
119 fi
120 }
121
122 function print_if_fits() {
123 local zero length
124
125 zero='%([BSUbfksu]|([FB]|){*})'
126 length=${#${(S%%)1//$~zero/}}
127 echo "%-$length(l.$1.)"
128 }