]> git.rmz.io Git - dotfiles.git/blob - zsh/lib/prompt.zsh
zsh/prompt: add reminder to add more info on submodules
[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 $(virtualenv_prompt)%n@%{$fg[$hostcolor]%}%m$(jobs_prompt)%-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 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=" %{$fg_bold[green]%}"
79
80 # Format branch and commit
81 git_status+="$head%{$fg_no_bold[yellow]%}(${oid[1,8]})"
82
83 # Format upstream
84 local upstream_str
85 [[ -z "$upstream" ]] && upstream_str+="%{$fg[blue]%} Ɇ"
86 (( ahead > 0 )) && upstream_str+="%{$fg[blue]%} >$ahead"
87 (( behind > 0 )) && upstream_str+="%{$fg[blue]%} <$behind"
88 git_status+="$upstream_str"
89
90 # Format push
91 push_ab=( $(git rev-list --left-right --count @...@{push} 2>/dev/null) )
92 if (( $? == 0 )); then
93 (( push_ab[1] > 0 )) && git_status+="%{$fg_bold[blue]%} ⮝$push_ab[1]"
94 (( push_ab[2] > 0 )) && git_status+="%{$fg_bold[blue]%} ⮟$push_ab[2]"
95 fi
96
97 # Format stashed
98 stashed=$(git stash list | wc -l)
99 if (( stashed > 0 )) then
100 stashed_str+="%{$fg_bold[cyan]%} ⋎$stashed%{$reset_color%}"
101 fi
102 git_status+="$stashed_str"
103
104 # Format index
105 local index_str
106 (( updated > 0 )) && index_str+="%{$fg[green]%} *$updated"
107 (( added > 0 )) && index_str+="%{$fg[green]%} +$added"
108 (( deleted > 0 )) && index_str+="%{$fg[green]%} -$deleted"
109 (( renamed > 0 )) && index_str+="%{$fg[green]%} ≈$renamed"
110 git_status+="$index_str"
111
112 # Format working tree
113 local wt_str
114 (( modified > 0 )) && wt_str+="%{$fg[red]%} *$modified"
115 (( deleted_wt > 0 )) && wt_str+="%{$fg[red]%} -$deleted_wt"
116 (( untracked > 0 )) && wt_str+="%{$fg[red]%} +$untracked"
117 (( unmerged > 0 )) && wt_str+="%{$fg[magenta]%} ♒$unmerged"
118 git_status+="$wt_str"
119
120 git_status+="%{$reset_color%}"
121
122 echo $git_status
123 }
124
125 function virtualenv_prompt() {
126 if [[ -z $VIRTUAL_ENV ]] then
127 echo ""
128 else
129 echo "(${VIRTUAL_ENV##*/}) "
130 fi
131 }
132
133 function print_if_fits() {
134 local zero length
135
136 zero='%([BSUbfksu]|([FB]|){*})'
137 length=${#${(S%%)1//$~zero/}}
138 echo "%-$length(l.$1.)"
139 }