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