|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +##################################################################################### |
| 4 | +# COLORS & ICONS |
| 5 | +##################################################################################### |
| 6 | +# you might need to install icon fonts and make them available to terminal |
| 7 | +# https://github.com/gabrielelana/awesome-terminal-fonts/wiki/OS-X |
| 8 | +: ${os_icon:=''} |
| 9 | +: ${node_icon:=''} |
| 10 | +: ${branch_icon:=''} |
| 11 | +: ${clean_icon:='✔'} |
| 12 | +: ${merge_icon:=''} |
| 13 | +: ${ahead_icon:='↑'} |
| 14 | +: ${behind_icon:='↓'} |
| 15 | +: ${staged_icon:='✚'} |
| 16 | +: ${untracked_icon:='✘'} |
| 17 | +: ${alert_icon:=''} |
| 18 | + |
| 19 | +Red="$(tput setaf 1)" |
| 20 | +Green="$(tput setaf 2)" |
| 21 | +Yellow="$(tput setaf 3)" |
| 22 | +Blue="$(tput setaf 4)" |
| 23 | +RESET="$(tput sgr0)" |
| 24 | + |
| 25 | +##################################################################################### |
| 26 | +# PROMPT |
| 27 | +##################################################################################### |
| 28 | +dev_jump() { |
| 29 | + echo "\n ${Yellow}└─" |
| 30 | +} |
| 31 | + |
| 32 | +dev_start() { |
| 33 | + echo "${Yellow}(" |
| 34 | +} |
| 35 | + |
| 36 | +dev_end() { |
| 37 | + echo "${Yellow})" |
| 38 | +} |
| 39 | + |
| 40 | +# https://stackoverflow.com/a/24067243 |
| 41 | +function version_gt() { |
| 42 | + test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; |
| 43 | +} |
| 44 | + |
| 45 | +node_v() { |
| 46 | + if hash node 2>/dev/null; then |
| 47 | + nv=$(node -v | tr -d '[v]') |
| 48 | + fi |
| 49 | + |
| 50 | + # do we have a .nvmrc to compare against |
| 51 | + if [ -r ".nvmrc" ] && [ -f ".nvmrc" ]; then |
| 52 | + expected="$(cat .nvmrc | tr -d '[:space:]' | tr -d '[v]')" |
| 53 | + if version_gt $expected $nv; then |
| 54 | + [ "$nv" != "" ] && echo -ne "${Red}${node_icon} ${nv}${alert_icon} " |
| 55 | + else |
| 56 | + [ "$nv" != "" ] && echo -ne "${Green}${node_icon} ${nv}" |
| 57 | + fi |
| 58 | + else |
| 59 | + [ "$nv" != "" ] && echo -ne "${Green}${node_icon} ${nv}" |
| 60 | + fi |
| 61 | +} |
| 62 | + |
| 63 | +git_dirty() { |
| 64 | + local repo_status=$(git status 2>&1 | tail -n1) |
| 65 | + [[ $repo_status != "nothing to commit, working directory clean" ]] && echo " ${Red}*" |
| 66 | +} |
| 67 | + |
| 68 | +git_branch() { |
| 69 | + # show either the branch name or the detached HEAD |
| 70 | + _branch="$(git symbolic-ref --short HEAD)" |
| 71 | + if [[ $_branch != "" ]]; then |
| 72 | + echo -ne "${Yellow} ${branch_icon}$_branch" |
| 73 | + else |
| 74 | + hd="$(git rev-parse --short HEAD | head -n 1)" |
| 75 | + echo -ne "${Red} ${branch_icon} detached HEAD $hd" |
| 76 | + fi |
| 77 | +} |
| 78 | + |
| 79 | +staged() { |
| 80 | + count="$(git diff --cached --name-only | wc -l)" |
| 81 | + count=`echo $count | xargs` |
| 82 | + if [[ $count != "0" ]]; then |
| 83 | + echo -ne "${Green} ${staged_icon}${count}" |
| 84 | + else |
| 85 | + echo "" |
| 86 | + fi |
| 87 | +} |
| 88 | + |
| 89 | +unstaged() { |
| 90 | + count="$(git diff --name-status | wc -l)" |
| 91 | + count=`echo $count | xargs` |
| 92 | + if [[ $count != "0" ]]; then |
| 93 | + echo -ne "${Red} ?${count}" |
| 94 | + else |
| 95 | + echo "" |
| 96 | + fi |
| 97 | +} |
| 98 | + |
| 99 | +untracked() { |
| 100 | + count="$(git ls-files --others --exclude-standard | wc -l)"`echo $count | sed 's/ *$//g'` |
| 101 | + count=`echo $count | xargs` |
| 102 | + if [[ $count != "0" ]]; then |
| 103 | + echo -ne "${Red} ${untracked_icon}${count}" |
| 104 | + else |
| 105 | + echo "" |
| 106 | + fi |
| 107 | +} |
| 108 | + |
| 109 | +behindahead() { |
| 110 | + # current branch name |
| 111 | + br="$(git rev-parse --abbrev-ref HEAD)" |
| 112 | + if [[ $br != "HEAD" ]]; then |
| 113 | + # check if remote 'origin' exists |
| 114 | + # yes, for simplicity we assume our remote is 'origin' |
| 115 | + r="$(git remote get-url origin 2>&1 | tail -n1)" |
| 116 | + if [[ $r != "fatal: No such remote 'origin'" ]]; then |
| 117 | + # check if remote branch exists |
| 118 | + # master & squashed branches compare to their remotes |
| 119 | + # all other branches compare to origin/develop |
| 120 | + if [[ $br != "master" ]] && [[ $br != "squashed" ]] && [[ $br != "develop" ]]; then |
| 121 | + rbr="develop" |
| 122 | + else |
| 123 | + rbr="${br}" |
| 124 | + fi |
| 125 | + |
| 126 | + ub="$(git ls-remote --heads ${r} ${rbr} 2>&1 | sed -n 2p)" |
| 127 | + if [[ $ub != 0 ]] && [[ $ub != "fatal: Could not read from remote repository." ]]; then |
| 128 | + #echo "we have upstream branch in remote origin" |
| 129 | + upstream="origin/${rbr}" |
| 130 | + bh=`git rev-list ${br}..${upstream} --count `; |
| 131 | + bh=`echo $bh | xargs` |
| 132 | + ah=`git rev-list ${upstream}..${br} --count `; |
| 133 | + ah=`echo $ah | xargs` |
| 134 | + |
| 135 | + if [[ $bh != "0" ]] || [[ $ah != "0" ]]; then |
| 136 | + if [[ $bh != "0" ]]; then |
| 137 | + echo -ne "${Red} ${merge_icon}" |
| 138 | + else |
| 139 | + echo -ne "${Green} ${merge_icon}" |
| 140 | + fi |
| 141 | + fi |
| 142 | + if [[ $bh != "0" ]]; then |
| 143 | + echo -ne "${Red} ${behind_icon}${bh}" |
| 144 | + fi |
| 145 | + if [[ $ah != "0" ]]; then |
| 146 | + echo -ne "${Green} ${ahead_icon}${ah}" |
| 147 | + fi |
| 148 | + if [[ $bh == "0" ]] && [[ $ah == "0" ]]; then |
| 149 | + echo -ne "${Green} ${clean_icon}" |
| 150 | + fi |
| 151 | + fi |
| 152 | + fi |
| 153 | + fi |
| 154 | +} |
| 155 | + |
| 156 | +real_time_prompt() { |
| 157 | + PS1="\[\033]0;\W\007\]"; |
| 158 | + PS1+="\n\[${os_icon}\] \u \[${Blue}\]\w " |
| 159 | + |
| 160 | + # modify prompt adding development info if we are in a git repo folder |
| 161 | + if `git status &> /dev/null`; then |
| 162 | + PS1+="\[$(dev_jump)\]\[${Yellow}\]\[$(dev_start)\]" |
| 163 | + PS1+="\[$(node_v)\]" |
| 164 | + PS1+="\[$(git_branch)\]\[$(git_dirty)\]\[$(staged)\]\[$(unstaged)\]\[$(untracked)\]" |
| 165 | + |
| 166 | + # show behind/ahead info if branches count>0 (maybe we just init'ed git repo) |
| 167 | + bc="$(git branch --list | wc -l | xargs)" |
| 168 | + if [[ $bc != "0" ]]; then |
| 169 | + PS1+="\[$(behindahead)\]" |
| 170 | + fi |
| 171 | + |
| 172 | + PS1+="\[$(dev_end)\]" |
| 173 | + fi |
| 174 | + |
| 175 | + PS1+="\[${RESET}\]$ " |
| 176 | + |
| 177 | + export PS1 |
| 178 | +} |
| 179 | +PROMPT_COMMAND='real_time_prompt' |
0 commit comments