|
| 1 | +# Git bash for windows powerline theme |
| 2 | +# |
| 3 | +# Licensed under MIT |
| 4 | +# Based on https://github.com/Bash-it/bash-it and https://github.com/Bash-it/bash-it/tree/master/themes/powerline |
| 5 | +# Some ideas from https://github.com/speedenator/agnoster-bash |
| 6 | +# Git code based on https://github.com/joeytwiddle/git-aware-prompt/blob/master/prompt.sh |
| 7 | +# More info about color codes in https://en.wikipedia.org/wiki/ANSI_escape_code |
| 8 | + |
| 9 | +GITHUB_LOGO=" " |
| 10 | +FOLDER_ICON=" " |
| 11 | +PROMPT_CHAR=${POWERLINE_PROMPT_CHAR:=""} |
| 12 | +POWERLINE_LEFT_SEPARATOR=" " |
| 13 | +POWERLINE_PROMPT="last_status user_info cwd scm" |
| 14 | + |
| 15 | +USER_INFO_SSH_CHAR=" " |
| 16 | +USER_INFO_PROMPT_COLOR="G W" |
| 17 | + |
| 18 | +SCM_GIT_CHAR=" " |
| 19 | +SCM_PROMPT_CLEAN="" |
| 20 | +SCM_PROMPT_DIRTY="*" |
| 21 | +SCM_PROMPT_AHEAD="↑" |
| 22 | +SCM_PROMPT_BEHIND="↓" |
| 23 | +SCM_PROMPT_CLEAN_COLOR="G Bl" |
| 24 | +SCM_PROMPT_DIRTY_COLOR="R Bl" |
| 25 | +SCM_PROMPT_AHEAD_COLOR="" |
| 26 | +SCM_PROMPT_BEHIND_COLOR="" |
| 27 | +SCM_PROMPT_STAGED_COLOR="Y Bl" |
| 28 | +SCM_PROMPT_UNSTAGED_COLOR="R Bl" |
| 29 | +SCM_PROMPT_COLOR=${SCM_PROMPT_CLEAN_COLOR} |
| 30 | + |
| 31 | +CWD_PROMPT_COLOR="B W" |
| 32 | + |
| 33 | +STATUS_PROMPT_COLOR="Bl R B" |
| 34 | +STATUS_PROMPT_ERROR="✘" |
| 35 | +STATUS_PROMPT_ERROR_COLOR="Bl R B" |
| 36 | +STATUS_PROMPT_ROOT="⚡" |
| 37 | +STATUS_PROMPT_ROOT_COLOR="Bl Y B" |
| 38 | +STATUS_PROMPT_JOBS="●" |
| 39 | +STATUS_PROMPT_JOBS_COLOR="Bl Y B" |
| 40 | + |
| 41 | +function __color { |
| 42 | + local bg |
| 43 | + local fg |
| 44 | + local mod |
| 45 | + case $1 in |
| 46 | + 'Bl') bg=40;; |
| 47 | + 'R') bg=41;; |
| 48 | + 'G') bg=42;; |
| 49 | + 'Y') bg=43;; |
| 50 | + 'B') bg=44;; |
| 51 | + 'M') bg=45;; |
| 52 | + 'C') bg=46;; |
| 53 | + 'W') bg=47;; |
| 54 | + *) bg=49;; |
| 55 | + esac |
| 56 | + |
| 57 | + case $2 in |
| 58 | + 'Bl') fg=30;; |
| 59 | + 'R') fg=31;; |
| 60 | + 'G') fg=32;; |
| 61 | + 'Y') fg=33;; |
| 62 | + 'B') fg=34;; |
| 63 | + 'M') fg=35;; |
| 64 | + 'C') fg=36;; |
| 65 | + 'W') fg=37;; |
| 66 | + *) fg=39;; |
| 67 | + esac |
| 68 | + |
| 69 | + case $3 in |
| 70 | + 'B') mod=1;; |
| 71 | + *) mod=0;; |
| 72 | + esac |
| 73 | + |
| 74 | + # Control codes enclosed in \[\] to not polute PS1 |
| 75 | + # See http://unix.stackexchange.com/questions/71007/how-to-customize-ps1-properly |
| 76 | + echo "\[\e[${mod};${fg};${bg}m\]" |
| 77 | +} |
| 78 | + |
| 79 | +function __powerline_user_info_prompt { |
| 80 | + local user_info="" |
| 81 | + local color=${USER_INFO_PROMPT_COLOR} |
| 82 | + # if [[ -n "${SSH_CLIENT}" ]]; then |
| 83 | + # user_info="${USER_INFO_SSH_CHAR}\u@\h" |
| 84 | + # else |
| 85 | + # user_info="\u@\h" |
| 86 | + # fi |
| 87 | + user_info="${GITHUB_LOGO}" |
| 88 | + [[ -n "${user_info}" ]] && echo "${user_info}|${color}" |
| 89 | +} |
| 90 | + |
| 91 | +function __powerline_cwd_prompt { |
| 92 | + echo "${FOLDER_ICON} \$(basename \"\$(pwd)\") |${CWD_PROMPT_COLOR}" |
| 93 | + # echo "\w |${CWD_PROMPT_COLOR}" |
| 94 | +} |
| 95 | + |
| 96 | +function __powerline_scm_prompt { |
| 97 | + git_local_branch="" |
| 98 | + git_branch="" |
| 99 | + git_dirty="" |
| 100 | + git_dirty_count="" |
| 101 | + git_ahead_count="" |
| 102 | + git_ahead="" |
| 103 | + git_behind_count="" |
| 104 | + git_behind="" |
| 105 | + |
| 106 | + find_git_branch() { |
| 107 | + # Based on: http://stackoverflow.com/a/13003854/170413 |
| 108 | + git_local_branch=$(git rev-parse --abbrev-ref HEAD 2> /dev/null) |
| 109 | + |
| 110 | + if [[ -n "$git_local_branch" ]]; then |
| 111 | + if [[ "$git_local_branch" == "HEAD" ]]; then |
| 112 | + # Branc detached Could show the hash here |
| 113 | + git_branch=$(git rev-parse --short HEAD 2>/dev/null) |
| 114 | + else |
| 115 | + git_branch=$git_local_branch |
| 116 | + fi |
| 117 | + else |
| 118 | + git_branch="" |
| 119 | + return 1 |
| 120 | + fi |
| 121 | + } |
| 122 | + |
| 123 | + find_git_dirty() { |
| 124 | + # All dirty files (modified and untracked) |
| 125 | + local status_count=$(git status --porcelain 2> /dev/null | wc -l) |
| 126 | + |
| 127 | + if [[ "$status_count" != 0 ]]; then |
| 128 | + git_dirty=true |
| 129 | + git_dirty_count="$status_count" |
| 130 | + else |
| 131 | + git_dirty='' |
| 132 | + git_dirty_count='' |
| 133 | + fi |
| 134 | + } |
| 135 | + |
| 136 | + find_git_ahead_behind() { |
| 137 | + if [[ -n "$git_local_branch" ]] && [[ "$git_branch" != "HEAD" ]]; then |
| 138 | + local upstream_branch=$(git rev-parse --abbrev-ref "@{upstream}" 2> /dev/null) |
| 139 | + # If we get back what we put in, then that means the upstream branch was not found. (This was observed on git 1.7.10.4 on Ubuntu) |
| 140 | + [[ "$upstream_branch" = "@{upstream}" ]] && upstream_branch='' |
| 141 | + # If the branch is not tracking a specific remote branch, then assume we are tracking origin/[this_branch_name] |
| 142 | + [[ -z "$upstream_branch" ]] && upstream_branch="origin/$git_local_branch" |
| 143 | + if [[ -n "$upstream_branch" ]]; then |
| 144 | + git_ahead_count=$(git rev-list --left-right ${git_local_branch}...${upstream_branch} 2> /dev/null | grep -c '^<') |
| 145 | + git_behind_count=$(git rev-list --left-right ${git_local_branch}...${upstream_branch} 2> /dev/null | grep -c '^>') |
| 146 | + if [[ "$git_ahead_count" = 0 ]]; then |
| 147 | + git_ahead_count='' |
| 148 | + else |
| 149 | + git_ahead=true |
| 150 | + fi |
| 151 | + if [[ "$git_behind_count" = 0 ]]; then |
| 152 | + git_behind_count='' |
| 153 | + else |
| 154 | + git_behind=true |
| 155 | + fi |
| 156 | + fi |
| 157 | + fi |
| 158 | + } |
| 159 | + |
| 160 | + |
| 161 | + local color |
| 162 | + local scm_info |
| 163 | + |
| 164 | + find_git_branch && find_git_dirty && find_git_ahead_behind |
| 165 | + |
| 166 | + #not in Git repo |
| 167 | + [[ -z "$git_branch" ]] && return |
| 168 | + |
| 169 | + scm_info="${SCM_GIT_CHAR}${git_branch}" |
| 170 | + [[ -n "$git_dirty" ]] && color=${SCM_PROMPT_DIRTY_COLOR} || color=${SCM_PROMPT_CLEAN_COLOR} |
| 171 | + [[ -n "$git_behind" ]] && scm_info+="${SCM_PROMPT_BEHIND}${git_behind_count}" |
| 172 | + [[ -n "$git_ahead" ]] && scm_info+="${SCM_PROMPT_AHEAD}${git_ahead_count}" |
| 173 | + |
| 174 | + [[ -n "${scm_info}" ]] && echo "${scm_info}|${color}" |
| 175 | +} |
| 176 | + |
| 177 | +function __powerline_left_segment { |
| 178 | + local OLD_IFS="${IFS}"; IFS="|" |
| 179 | + local params=( $1 ) |
| 180 | + IFS="${OLD_IFS}" |
| 181 | + local separator_char="${POWERLINE_LEFT_SEPARATOR}" |
| 182 | + local separator="" |
| 183 | + local styles=( ${params[1]} ) |
| 184 | + |
| 185 | + if [[ "${SEGMENTS_AT_LEFT}" -gt 0 ]]; then |
| 186 | + styles[1]=${LAST_SEGMENT_COLOR} |
| 187 | + styles[2]="" |
| 188 | + separator="$(__color ${styles[@]})${separator_char}" |
| 189 | + fi |
| 190 | + |
| 191 | + styles=( ${params[1]} ) |
| 192 | + LEFT_PROMPT+="${separator}$(__color ${styles[@]})${params[0]}" |
| 193 | + |
| 194 | + #Save last background for next segment |
| 195 | + LAST_SEGMENT_COLOR=${styles[0]} |
| 196 | + (( SEGMENTS_AT_LEFT += 1 )) |
| 197 | +} |
| 198 | + |
| 199 | +function __powerline_last_status_prompt { |
| 200 | + local symbols=() |
| 201 | + [[ $last_status -ne 0 ]] && symbols+="$(__color ${STATUS_PROMPT_ERROR_COLOR})${STATUS_PROMPT_ERROR}" |
| 202 | + [[ $UID -eq 0 ]] && symbols+="$(__color ${STATUS_PROMPT_ROOT_COLOR})${STATUS_PROMPT_ROOT}" |
| 203 | + [[ $(jobs -l | wc -l) -gt 0 ]] && symbols+="$(__color ${STATUS_PROMPT_JOBS_COLOR})${STATUS_PROMPT_JOBS}" |
| 204 | + |
| 205 | + [[ -n "$symbols" ]] && echo "$symbols|${STATUS_PROMPT_COLOR}" |
| 206 | +} |
| 207 | + |
| 208 | +function __powerline_prompt_command { |
| 209 | + local last_status="$?" ## always the first |
| 210 | + local separator_char="${POWERLINE_PROMPT_CHAR}" |
| 211 | + |
| 212 | + LEFT_PROMPT="" |
| 213 | + SEGMENTS_AT_LEFT=0 |
| 214 | + LAST_SEGMENT_COLOR="" |
| 215 | + |
| 216 | + ## left prompt ## |
| 217 | + for segment in $POWERLINE_PROMPT; do |
| 218 | + local info="$(__powerline_${segment}_prompt)" |
| 219 | + [[ -n "${info}" ]] && __powerline_left_segment "${info}" |
| 220 | + done |
| 221 | + |
| 222 | + [[ -n "${LEFT_PROMPT}" ]] && LEFT_PROMPT+="$(__color - ${LAST_SEGMENT_COLOR})${separator_char}$(__color)" |
| 223 | + PS1="${LEFT_PROMPT} " |
| 224 | + |
| 225 | + ## cleanup ## |
| 226 | + unset LAST_SEGMENT_COLOR \ |
| 227 | + LEFT_PROMPT \ |
| 228 | + SEGMENTS_AT_LEFT |
| 229 | +} |
| 230 | + |
| 231 | +function safe_append_prompt_command { |
| 232 | + local prompt_re |
| 233 | + |
| 234 | + # Set OS dependent exact match regular expression |
| 235 | + if [[ ${OSTYPE} == darwin* ]]; then |
| 236 | + # macOS |
| 237 | + prompt_re="[[:<:]]${1}[[:>:]]" |
| 238 | + else |
| 239 | + # Linux, FreeBSD, etc. |
| 240 | + prompt_re="\<${1}\>" |
| 241 | + fi |
| 242 | + |
| 243 | + if [[ ${PROMPT_COMMAND} =~ ${prompt_re} ]]; then |
| 244 | + return |
| 245 | + elif [[ -z ${PROMPT_COMMAND} ]]; then |
| 246 | + PROMPT_COMMAND="${1}" |
| 247 | + else |
| 248 | + PROMPT_COMMAND="${1};${PROMPT_COMMAND}" |
| 249 | + fi |
| 250 | +} |
| 251 | + |
| 252 | +safe_append_prompt_command __powerline_prompt_command |
| 253 | + |
| 254 | +__color_matrix() { |
| 255 | + local buffer |
| 256 | + |
| 257 | + declare -A colors=([0]=black [1]=red [2]=green [3]=yellow [4]=blue [5]=purple [6]=cyan [7]=white) |
| 258 | + declare -A mods=([0]='' [1]=B [4]=U [5]=k [7]=N) |
| 259 | + |
| 260 | + # Print foreground color names |
| 261 | + echo -ne " " |
| 262 | + for fgi in "${!colors[@]}"; do |
| 263 | + local fg=`printf "%10s" "${colors[$fgi]}"` |
| 264 | + #print color names |
| 265 | + echo -ne "\e[m$fg " |
| 266 | + done |
| 267 | + echo |
| 268 | + |
| 269 | + # Print modificators |
| 270 | + echo -ne " " |
| 271 | + for fgi in "${!colors[@]}"; do |
| 272 | + for modi in "${!mods[@]}"; do |
| 273 | + local mod=`printf "%1s" "${mods[$modi]}"` |
| 274 | + buffer="${buffer}$mod " |
| 275 | + done |
| 276 | + # echo -ne "\e[m " |
| 277 | + buffer="${buffer} " |
| 278 | + done |
| 279 | + echo -e "$buffer\e[m" |
| 280 | + buffer="" |
| 281 | + |
| 282 | + # Print color matrix |
| 283 | + for bgi in "${!colors[@]}"; do |
| 284 | + local bgn=$((bgi + 40)) |
| 285 | + local bg=`printf "%6s" "${colors[$bgi]}"` |
| 286 | + |
| 287 | + #print color names |
| 288 | + echo -ne "\e[m$bg " |
| 289 | + |
| 290 | + for fgi in "${!colors[@]}"; do |
| 291 | + local fgn=$((fgi + 30)) |
| 292 | + local fg=`printf "%7s" "${colors[$fgi]}"` |
| 293 | + |
| 294 | + for modi in "${!mods[@]}"; do |
| 295 | + buffer="${buffer}\e[${modi};${bgn};${fgn}m " |
| 296 | + done |
| 297 | + # echo -ne "\e[m " |
| 298 | + buffer="${buffer}\e[m " |
| 299 | + done |
| 300 | + echo -e "$buffer\e[m" |
| 301 | + buffer="" |
| 302 | + done |
| 303 | +} |
| 304 | + |
| 305 | +__character_map () { |
| 306 | + echo "powerline: ±●➦★⚡★ ✗✘✓✓✔✕✖✗← ↑ → ↓" |
| 307 | + echo "other: ☺☻👨⚙⚒⚠⌛" |
| 308 | +} |
0 commit comments