X-Git-Url: https://git.rmz.io/dotfiles.git/blobdiff_plain/4e706f7cc88631ea2da12d8a786dc71924193c98..2bb3c600f31aa7e1af1fbef3656ab6947a7585e3:/zsh/lib/prompt.zsh diff --git a/zsh/lib/prompt.zsh b/zsh/lib/prompt.zsh new file mode 100644 index 0000000..4f31348 --- /dev/null +++ b/zsh/lib/prompt.zsh @@ -0,0 +1,112 @@ +hostcolor=green +[[ $(hostname) == "tardis" ]] && hostcolor=red + +precmd() { + PROMPT='%T %n@%{$fg[$hostcolor]%}%m%{$reset_color%}%-0>..>$(git_prompt_status)%>> +%(?..%{$fg_bold[white]%}%?%{$reset_color%})$(vi_prompt_info)%{%(!.$fg[red]❰.$fg[green]❱)%1G%} ' + RPROMPT='%{$fg[green]%}%~%{$reset_color%}' +} + +vi_prompt_info() { + local vicmd="$fg_bold[green]❰$reset_color%1G" + local viins="$fg_bold[blue]❱$reset_color%1G" + printf '%s' "%{${${KEYMAP/vicmd/$vicmd}/(main|viins)/$viins}%}" +} + +function zle-line-init zle-line-finish zle-keymap-select { + zle reset-prompt + zle -R +} + +zle -N zle-line-init +zle -N zle-line-finish +zle -N zle-keymap-select + +# reset zle on resize +TRAPWINCH() { + zle && { zle reset-prompt; zle -R } +} + +# Get the status of the working tree +git_prompt_status() { + local branch ahead behind + local added deleted modified renamed unmerged untracked dirty + # Use porcelain status for easy parsing. + local status_cmd="git status --porcelain -b" + + # Get current status. + while IFS=$'\n' read line; do + if [[ "$line" == \#\#\ * ]]; then + [[ "$line" =~ '## ([^.]*)\.\.\.(.*)' ]] && branch=$match[1] + [[ "$line" =~ 'ahead ([0-9]+)' ]] && ahead=$match[1] + [[ "$line" =~ 'behind ([0-9]+)' ]] && behind=$match[1] + else + # Count added, deleted, modified, renamed, unmerged, untracked, dirty. + # T (type change) is undocumented, see http://git.io/FnpMGw. + # index + [[ "$line" == M[\ MTD]\ * ]] && (( updated++ )) + [[ "$line" == [AC][\ MTD]\ * ]] && (( added++ )) + [[ "$line" == D[\ MT]\ * ]] && (( deleted++ )) + [[ "$line" == R[\ MTD]\ * ]] && (( renamed++ )) + + # work tree + [[ "$line" == [\ MARCT]M\ * ]] && (( modified++ )) + [[ "$line" == [\ MARCT]D\ * ]] && (( deleted_wt++ )) + [[ "$line" == \?\?\ * ]] && (( untracked++ )) + + # morge conflicts + [[ "$line" == (AA|DD|U?|?U)\ * ]] && (( unmerged++ )) + fi + done < <(${(z)status_cmd} 2> /dev/null) + + local git_status=" %{$fg[yellow]%}" + + # Format branch + if [[ -n $branch ]]; then + git_status+="$branch" + else + git_status+="$(git rev-parse --short HEAD 2> /dev/null)" + [[ $? -ne 0 ]] && return + fi + + # Format upstream + local upstream_str + (( ahead > 0 )) && upstream_str+="%{$fg[blue]%} >$ahead" + (( behind > 0 )) && upstream_str+="%{$fg[blue]%} <$behind" + git_status+="$upstream_str" + + # Format stashed + stashed=$(git stash list | wc -l) + if (( stashed > 0 )) then + stashed_str+="%{$fg_bold[cyan]%} ⋎$stashed%{$reset_color%}" + fi + git_status+="$stashed_str" + + # Format index + local index_str + (( updated > 0 )) && index_str+="%{$fg[green]%} *$updated" + (( added > 0 )) && index_str+="%{$fg[green]%} +$added" + (( deleted > 0 )) && index_str+="%{$fg[green]%} -$deleted" + (( renamed > 0 )) && index_str+="%{$fg[green]%} ≈$renamed" + git_status+="$index_str" + + # Format working tree + local wt_str + (( modified > 0 )) && wt_str+="%{$fg[red]%} *$modified" + (( deleted_wt > 0 )) && wt_str+="%{$fg[red]%} -$deleted_wt" + (( untracked > 0 )) && wt_str+="%{$fg[red]%} +$untracked" + (( unmerged > 0 )) && wt_str+="%{$fg[magenta]%} ♒$unmerged" + git_status+="$wt_str" + + git_status+="%{$reset_color%}" + + echo $git_status +} + +function print_if_fits() { + local zero length + + zero='%([BSUbfksu]|([FB]|){*})' + length=${#${(S%%)1//$~zero/}} + echo "%-$length(l.$1.)" +}