Not for normies
| 1 | ########################################## |
| 2 | ### Comfyline - theme for zsh ### |
| 3 | # Original Author: not pua ( imnotpua ) # |
| 4 | # email: atp@tutamail.com # |
| 5 | ########################################## |
| 6 | |
| 7 | |
| 8 | # make prompt work without oh-my-zsh |
| 9 | setopt PROMPT_SUBST |
| 10 | export LANG=en_US.UTF-8 |
| 11 | export LC_ALL=en_US.UTF-8 |
| 12 | |
| 13 | # default segment seperators |
| 14 | if [[ $COMFYLINE_SEGSEP == "" ]]; then |
| 15 | COMFYLINE_SEGSEP='\ue0b4' |
| 16 | fi |
| 17 | |
| 18 | if [[ $COMFYLINE_SEGSEP_REVERSE == "" ]]; then |
| 19 | COMFYLINE_SEGSEP_REVERSE='\ue0b6' |
| 20 | fi |
| 21 | |
| 22 | # date and time formats |
| 23 | if [[ $COMFYLINE_DATE_FORMAT == "" ]]; then |
| 24 | COMFYLINE_DATE_FORMAT="%A, %e %B %Y" |
| 25 | fi |
| 26 | |
| 27 | if [[ $COMFYLINE_TIME_FORMAT == "" ]]; then |
| 28 | COMFYLINE_TIME_FORMAT="%l:%M %p" |
| 29 | fi |
| 30 | |
| 31 | # default light theme |
| 32 | if [[ $RETVAL_RANK == "" ]]; then |
| 33 | RETVAL_RANK=1 |
| 34 | fi |
| 35 | if [[ $HOST_RANK == "" ]]; then |
| 36 | HOST_RANK=2 |
| 37 | fi |
| 38 | if [[ $USER_RANK == "" ]] then |
| 39 | USER_RANK=3 |
| 40 | fi |
| 41 | if [[ $DIR_RANK == "" ]]; then |
| 42 | DIR_RANK=4 |
| 43 | fi |
| 44 | if [[ $GIT_RANK == "" ]] then |
| 45 | GIT_RANK=5 |
| 46 | fi |
| 47 | if [[ $VENV_RANK = "" ]]; then |
| 48 | VENV_RANK=6 |
| 49 | fi |
| 50 | if [[ $BAT_RANK == "" ]] then |
| 51 | BAT_RANK=-3 |
| 52 | fi |
| 53 | if [[ $DATE_RANK == "" ]]; then |
| 54 | DATE_RANK=-2 |
| 55 | fi |
| 56 | if [[ $TIME_RANK == "" ]]; then |
| 57 | TIME_RANK=-1 |
| 58 | fi |
| 59 | |
| 60 | # default colors |
| 61 | if [[ $RETVAL_b == "" ]]; then |
| 62 | RETVAL_b="#8a8bd8" |
| 63 | fi |
| 64 | if [[ $RETVAL_f == "" ]]; then |
| 65 | RETVAL_f="#61355c" |
| 66 | fi |
| 67 | if [[ $HOST_b == "" ]]; then |
| 68 | HOST_b="#b3b5fb" |
| 69 | fi |
| 70 | if [[ $HOST_f == "" ]]; then |
| 71 | HOST_f="#4a4b87" |
| 72 | fi |
| 73 | if [[ $USER_b == "" ]]; then |
| 74 | USER_b="#f8bbe5" |
| 75 | fi |
| 76 | if [[ $USER_f == "" ]]; then |
| 77 | USER_f="#874c80" |
| 78 | fi |
| 79 | if [[ $GIT_b == "" ]]; then |
| 80 | GIT_b="#f6b3b3" |
| 81 | fi |
| 82 | if [[ $GIT_f == "" ]]; then |
| 83 | GIT_f="#d95353" |
| 84 | fi |
| 85 | if [[ $GIT_CLEAN_b == "" ]]; then |
| 86 | GIT_CLEAN_b="#b3f58c" |
| 87 | fi |
| 88 | if [[ $GIT_CLEAN_f == "" ]]; then |
| 89 | GIT_CLEAN_f="#568459" |
| 90 | fi |
| 91 | if [[ $DIR_b == "" ]]; then |
| 92 | DIR_b="#e1bff2" |
| 93 | fi |
| 94 | if [[ $DIR_f == "" ]]; then |
| 95 | DIR_f="#844189" |
| 96 | fi |
| 97 | if [[ $VENV_b == "" ]]; then |
| 98 | VENV_b="#a8ddf9" |
| 99 | fi |
| 100 | if [[ $VENV_f == "" ]]; then |
| 101 | VENV_f="#0066a4" |
| 102 | fi |
| 103 | if [[ $BAT_b == "" ]]; then |
| 104 | BAT_b="#b3b5fb" |
| 105 | fi |
| 106 | if [[ $BAT_f == "" ]]; then |
| 107 | BAT_f="#4a4b87" |
| 108 | fi |
| 109 | if [[ $DATE_b == "" ]]; then |
| 110 | DATE_b="#f8bbe5" |
| 111 | fi |
| 112 | if [[ $DATE_f == "" ]]; then |
| 113 | DATE_f="#874c80" |
| 114 | fi |
| 115 | if [[ $TIME_b == "" ]]; then |
| 116 | TIME_b="#e1bff2" |
| 117 | fi |
| 118 | if [[ $TIME_f == "" ]]; then |
| 119 | TIME_f="#844189" |
| 120 | fi |
| 121 | |
| 122 | # basic functions |
| 123 | |
| 124 | #function takes 4 arguments, background, foreground, text and rank (for edge cases) |
| 125 | function create_segment(){ |
| 126 | if [[ $4 -lt $RIGHTMOST_RANK ]]; then |
| 127 | local segment="%F{$1}$COMFYLINE_SEGSEP_REVERSE" |
| 128 | echo -n "$segment%K{$1}%F{$2} $3 " |
| 129 | elif [[ $4 -gt $LEFTMOST_RANK ]]; then |
| 130 | local segment="%K{$1}$COMFYLINE_SEGSEP " |
| 131 | echo -n "$segment%F{$2}$3%F{$1} " |
| 132 | elif [[ $4 -eq $RIGHTMOST_RANK ]]; then |
| 133 | if [[ $COMFYLINE_NO_START -eq 1 ]]; then |
| 134 | local segment="%F{$1}$COMFYLINE_SEGSEP_REVERSE" |
| 135 | echo -n "$segment%K{$1}%F{$2} $3" |
| 136 | else |
| 137 | local segment="%F{$1}$COMFYLINE_SEGSEP_REVERSE" |
| 138 | echo -n "$segment%K{$1}%F{$2} $3 %k%F{$1}$COMFYLINE_SEGSEP" |
| 139 | fi |
| 140 | elif [[ $4 -eq $LEFTMOST_RANK ]]; then |
| 141 | if [[ $COMFYLINE_NO_START -eq 1 ]]; then |
| 142 | local segment="%K{$1} " |
| 143 | echo -n "$segment%F{$2}$3%F{$1} " |
| 144 | else |
| 145 | local segment="%F{$1}$COMFYLINE_SEGSEP_REVERSE%K{$1} " |
| 146 | echo -n "$segment%F{$2}$3%F{$1} " |
| 147 | fi |
| 148 | fi |
| 149 | |
| 150 | } |
| 151 | ### explanation: creates segment seperator with new bg but fg as old bg. |
| 152 | ### then prints contents in new fg and prepares for next fg as current bg |
| 153 | |
| 154 | # segment functions |
| 155 | function retval(){ |
| 156 | if [[ $COMFYLINE_RETVAL_NUMBER -eq 2 ]]; then |
| 157 | symbol="%(?..✘ %?)" |
| 158 | elif [[ $COMFYLINE_RETVAL_NUMBER -eq 1 ]]; then |
| 159 | symbol="%?" |
| 160 | else |
| 161 | symbol="%(?..✘)" |
| 162 | fi |
| 163 | create_segment $RETVAL_b $RETVAL_f $symbol $RETVAL_RANK |
| 164 | } |
| 165 | |
| 166 | function hostname(){ |
| 167 | if [[ $COMFYLINE_FULL_HOSTNAME -eq 1 ]]; then |
| 168 | create_segment $HOST_b $HOST_f "%M" $HOST_RANK |
| 169 | else |
| 170 | create_segment $HOST_b $HOST_f "%m" $HOST_RANK |
| 171 | fi |
| 172 | } |
| 173 | |
| 174 | function username(){ |
| 175 | create_segment $USER_b $USER_f "%n" $USER_RANK |
| 176 | } |
| 177 | |
| 178 | function dir(){ |
| 179 | if [[ $COMFYLINE_FULL_DIR -eq 1 ]]; then |
| 180 | symbol="%d" |
| 181 | else |
| 182 | symbol="%~" |
| 183 | fi |
| 184 | create_segment $DIR_b $DIR_f $symbol $DIR_RANK |
| 185 | } |
| 186 | |
| 187 | # variables to set git_prompt info and status |
| 188 | ZSH_THEME_GIT_PROMPT_PREFIX=" \ue0a0 " |
| 189 | ZSH_THEME_GIT_PROMPT_SUFFIX="" |
| 190 | ZSH_THEME_GIT_PROMPT_DIRTY="" |
| 191 | ZSH_THEME_GIT_PROMPT_CLEAN="" |
| 192 | ZSH_THEME_GIT_PROMPT_ADDED=" ✚" |
| 193 | ZSH_THEME_GIT_PROMPT_MODIFIED=" ±" |
| 194 | ZSH_THEME_GIT_PROMPT_DELETED=" \u2796" |
| 195 | ZSH_THEME_GIT_PROMPT_UNTRACKED=" !" |
| 196 | ZSH_THEME_GIT_PROMPT_RENAMED=" \u21b7" |
| 197 | ZSH_THEME_GIT_PROMPT_UNMERGED=" \u21e1" |
| 198 | ZSH_THEME_GIT_PROMPT_AHEAD=" \u21c5" |
| 199 | ZSH_THEME_GIT_PROMPT_BEHIND=" \u21b1" |
| 200 | ZSH_THEME_GIT_PROMPT_DIVERGED=" \u21b0" |
| 201 | |
| 202 | function gitrepo(){ |
| 203 | if [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then |
| 204 | if [[ $(git status --porcelain) == "" ]]; then |
| 205 | if [[ $(command -v git_prompt_info 2> /dev/null) ]]; then |
| 206 | create_segment $GIT_CLEAN_b $GIT_CLEAN_f "$(git_prompt_info)$(git_prompt_status)" $GIT_RANK |
| 207 | else |
| 208 | create_segment $GIT_CLEAN_b $GIT_CLEAN_f "$ZSH_THEME_GIT_PROMPT_PREFIX$(git rev-parse --abbrev-ref HEAD)" $GIT_RANK |
| 209 | fi |
| 210 | else |
| 211 | if [[ $(command -v git_prompt_info 2> /dev/null) ]]; then |
| 212 | create_segment $GIT_b $GIT_f "$(git_prompt_info)$(git_prompt_status)" $GIT_RANK |
| 213 | else |
| 214 | create_segment $GIT_b $GIT_f "$ZSH_THEME_GIT_PROMPT_PREFIX$(git rev-parse --abbrev-ref HEAD)" $GIT_RANK |
| 215 | fi |
| 216 | fi |
| 217 | fi |
| 218 | } |
| 219 | |
| 220 | function venv(){ |
| 221 | if [ -n "$VIRTUAL_ENV" ]; then |
| 222 | create_segment $VENV_b $VENV_f ${VIRTUAL_ENV:t:gs/%/%%} $VENV_RANK |
| 223 | fi |
| 224 | } |
| 225 | |
| 226 | # battery function |
| 227 | |
| 228 | # variables |
| 229 | |
| 230 | if [[ $COMFYLINE_BATTERY_LOW == "" ]]; then |
| 231 | COMFYLINE_BATTERY_LOW=15 |
| 232 | fi |
| 233 | if [[ $COMFYLINE_BATTERY_HIGH == "" ]]; then |
| 234 | COMFYLINE_BATTERY_HIGH=90 |
| 235 | fi |
| 236 | if [[ $COMFYLINE_CHARGING_ICON == "" ]]; then |
| 237 | COMFYLINE_CHARGING_ICON="⚡️" |
| 238 | fi |
| 239 | if [[ $COMFYLINE_HIGHCHARGE_ICON == "" ]]; then |
| 240 | COMFYLINE_HIGHCHARGE_ICON="" |
| 241 | fi |
| 242 | if [[ $COMFYLINE_MIDCHARGE_ICON == "" ]]; then |
| 243 | COMFYLINE_MIDCHARGE_ICON="" |
| 244 | fi |
| 245 | if [[ $COMFYLINE_LOWCHARGE_ICON == "" ]]; then |
| 246 | COMFYLINE_LOWCHARGE_ICON="" |
| 247 | fi |
| 248 | |
| 249 | function calcbat(){ |
| 250 | BAT="" |
| 251 | if [[ $(uname) == "Linux" ]]; then |
| 252 | number=$(ls /sys/class/power_supply/ | grep 'BAT' | wc -l ) |
| 253 | if [[ $number -eq 0 ]]; then |
| 254 | return 0 |
| 255 | fi |
| 256 | for ((i=0;i<$number;i++));do |
| 257 | capacity=$(cat /sys/class/power_supply/BAT${i}/capacity) |
| 258 | stats=$(cat /sys/class/power_supply/BAT${i}/status) |
| 259 | if [[ $stats == "Charging" ]]; then |
| 260 | stats="$COMFYLINE_CHARGING_ICON" |
| 261 | elif [[ $stats == "Discharging" ]]; then |
| 262 | if [ $capacity -gt $COMFYLINE_BATTERY_HIGH ]; then |
| 263 | stats="$COMFYLINE_HIGHCHARGE_ICON" |
| 264 | elif [ $capacity -lt $COMFYLINE_BATTERY_LOW ]; then |
| 265 | stats="$COMFYLINE_LOWCHARGE_ICON" |
| 266 | else |
| 267 | stats="$COMFYLINE_MIDCHARGE_ICON" |
| 268 | fi |
| 269 | elif [[ $stats == "Not charging" ]]; then |
| 270 | stats="$COMFYLINE_HIGHCHARGE_ICON" |
| 271 | fi |
| 272 | BAT="$BAT$capacity%% $stats " |
| 273 | done |
| 274 | |
| 275 | elif [[ $(uname) == "Darwin" ]]; then |
| 276 | battery_details = $(pmset -g batt) |
| 277 | charged=$(echo "$battery_details" | grep -w 'charged') |
| 278 | charging=$(echo "$battery_details" | grep -w 'AC Power') |
| 279 | discharging=$(echo "$battery_details" | grep -w 'Battery Power') |
| 280 | capacity=$(echo "$battery_details" | grep -o "([0-9]*)"%) |
| 281 | |
| 282 | if [ -n "$charging" ]; then |
| 283 | stats="$COMFYLINE_CHARGING_ICON" |
| 284 | elif [[ -n "$discharging" ]]; then |
| 285 | if [ $capacity -gt $COMFYLINE_BATTERY_HIGH ]; then |
| 286 | stats="$COMFYLINE_HIGHCHARGE_ICON" |
| 287 | elif [ $capacity -lt $COMFYLINE_BATTERY_LOW ]; then |
| 288 | stats="$COMFYLINE_LOWCHARGE_ICON" |
| 289 | else |
| 290 | stats="$COMFYLINE_MIDCHARGE_ICON" |
| 291 | fi |
| 292 | fi |
| 293 | BAT="$capacity%% $stats" |
| 294 | |
| 295 | elif [[ $(uname) == "FreeBSD" || $(uname) == "OpenBSD" ]]; then |
| 296 | capacity=$(apm -l) |
| 297 | stats=$(apm -b) |
| 298 | if [ $stats -eq 3 ]; then |
| 299 | stats="$COMFYLINE_CHARGING_ICON" |
| 300 | else |
| 301 | if [[ $capacity -gt $COMFYLINE_BATTERY_HIGH ]]; then |
| 302 | stats="$COMFYLINE_HIGHCHARGE_ICON" |
| 303 | elif [[ $capacity -lt $COMFYLINE_BATTERY_LOW ]]; then |
| 304 | stats="$COMFYLINE_LOWCHARGE_ICON" |
| 305 | else |
| 306 | stats="$COMFYLINE_MIDCHARGE_ICON" |
| 307 | fi |
| 308 | fi |
| 309 | BAT="$capacity%% $stats" |
| 310 | fi |
| 311 | } |
| 312 | |
| 313 | # function to call battery calculation |
| 314 | function currbat(){ |
| 315 | if [[ $COMFYLINE_BATTERY_PLUGIN -eq 1 ]]; then |
| 316 | create_segment $BAT_b $BAT_f "$(battery_pct_prompt)" $BAT_RANK |
| 317 | else |
| 318 | calcbat |
| 319 | create_segment $BAT_b $BAT_f "$BAT" $BAT_RANK |
| 320 | fi |
| 321 | } |
| 322 | |
| 323 | function currdate(){ |
| 324 | info="%D{$COMFYLINE_DATE_FORMAT}" |
| 325 | create_segment $DATE_b $DATE_f $info $DATE_RANK |
| 326 | } |
| 327 | |
| 328 | function currtime(){ |
| 329 | info="%D{$COMFYLINE_TIME_FORMAT}" |
| 330 | create_segment $TIME_b $TIME_f $info $TIME_RANK |
| 331 | } |
| 332 | |
| 333 | function endleft(){ |
| 334 | echo -n "%k$COMFYLINE_SEGSEP%f" |
| 335 | } |
| 336 | |
| 337 | # parse variables |
| 338 | |
| 339 | segments=("retval" "hostname" "username" "dir" "gitrepo" "venv" "currbat" "currtime" "currdate") |
| 340 | segment_ranks=($RETVAL_RANK $HOST_RANK $USER_RANK $DIR_RANK $GIT_RANK $VENV_RANK $BAT_RANK $TIME_RANK $DATE_RANK) |
| 341 | |
| 342 | # split into left and right |
| 343 | |
| 344 | left_prompt=() |
| 345 | right_prompt=() |
| 346 | left_ranks=() |
| 347 | right_ranks=() |
| 348 | for ((i=1;i<=${#segments[@]};i++)); do |
| 349 | if [[ segment_ranks[$i] -gt 0 ]]; then |
| 350 | left_prompt+=(${segments[$i]}) |
| 351 | left_ranks+=(${segment_ranks[$i]}) |
| 352 | elif [[ segment_ranks[$i] -lt 0 ]]; then |
| 353 | right_prompt+=(${segments[$i]}) |
| 354 | right_ranks+=(${segment_ranks[$i]#-}) |
| 355 | fi |
| 356 | done |
| 357 | |
| 358 | # sort the prompts according to ranks and find the leftmost and rightmost |
| 359 | # I use the traditional iterative method to find max/min and using count-sort for sorting |
| 360 | |
| 361 | LEFTMOST_RANK=100 |
| 362 | declare -A sorted_left |
| 363 | for ((i=1;i<=${#left_prompt[@]};i++)); do |
| 364 | if [[ $left_ranks[$i] -lt $LEFTMOST_RANK ]]; then LEFTMOST_RANK=$left_ranks[$i] fi |
| 365 | sorted_left[$left_ranks[$i]]="$left_prompt[$i]" |
| 366 | done |
| 367 | |
| 368 | RIGHTMOST_RANK=100 |
| 369 | declare -A sorted_right |
| 370 | for ((i=1;i<=${#right_prompt[@]};i++)); do |
| 371 | if [[ $right_ranks[$i] -lt $RIGHTMOST_RANK ]]; then RIGHTMOST_RANK=$right_ranks[$i] fi |
| 372 | sorted_right[$right_ranks[$i]]="$right_prompt[$i]" |
| 373 | done |
| 374 | ((RIGHTMOST_RANK*=-1)) |
| 375 | |
| 376 | |
| 377 | # finally make_prompt which makes prompts |
| 378 | make_left_prompt(){ |
| 379 | for ((j = 1; j <= ${#left_prompt[@]}; j++)); do |
| 380 | type $sorted_left[$j] &>/dev/null && $sorted_left[$j] |
| 381 | done |
| 382 | } |
| 383 | |
| 384 | make_right_prompt(){ |
| 385 | for ((j = ${#right_prompt[@]}; j>0; j--)); do |
| 386 | type $sorted_right[$j] &>/dev/null && $sorted_right[$j] |
| 387 | done |
| 388 | } |
| 389 | |
| 390 | export PROMPT='%{%f%b%k%}$(make_left_prompt)$(endleft) ' |
| 391 | export RPROMPT=' %{%f%b%k%}$(make_right_prompt)' # spaces left so that hiding is triggered |
| 392 | |
| 393 | if [[ $COMFYLINE_NEXT_LINE_CHAR == "" ]]; then |
| 394 | COMFYLINE_NEXT_LINE_CHAR='➟' |
| 395 | fi |
| 396 | |
| 397 | if [[ $COMFYLINE_NEXT_LINE_CHAR_COLOR == "" ]]; then |
| 398 | COMFYLINE_NEXT_LINE_CHAR_COLOR="grey" |
| 399 | fi |
| 400 | |
| 401 | next_line_maker(){ |
| 402 | echo -n "%F{$COMFYLINE_NEXT_LINE_CHAR_COLOR}$COMFYLINE_NEXT_LINE_CHAR %f" |
| 403 | } |
| 404 | |
| 405 | # setting up typing area |
| 406 | if [[ COMFYLINE_START_NEXT_LINE -eq 2 ]]; then |
| 407 | |
| 408 | PROMPT=$PROMPT' |
| 409 | '$(next_line_maker) |
| 410 | |
| 411 | |
| 412 | elif [[ COMFYLINE_NO_GAP_LINE -eq 1 ]]; then |
| 413 | else |
| 414 | |
| 415 | PROMPT=' |
| 416 | '$PROMPT |
| 417 | |
| 418 | fi |