# # Rainbow ZSH # # Fork from shellder # # # Segment drawing # CURRENT_BG='NONE' # # color scheme # # for i in {0..255}; do print -Pn "%K{$i} %k%F{$i}${(l:3::0:)i}%f " ${${(M)$((i%6)):#3}:+$'\n'}; done # RAINBOW_CONTEXT_BG=${RAINBOW_CONTEXT_BG:-'black'} RAINBOW_CONTEXT_FG=${RAINBOW_CONTEXT_FG:-81} RAINBOW_CONTEXT_SSH_BG=${RAINBOW_CONTEXT_SSH_BG:-'black'} RAINBOW_CONTEXT_SSH_FG=${RAINBOW_CONTEXT_SSH_FG:-123} RAINBOW_CONTEXT_SSH_USER_FG=${RAINBOW_CONTEXT_SSH_USER_FG:-250} RAINBOW_CONTEXT_SSH_HOST_FG=${RAINBOW_CONTEXT_SSH_HOST_FG:-206} RAINBOW_CONTEXT_ROOT_BG=${RAINBOW_CONTEXT_ROOT_BG:-124} RAINBOW_CONTEXT_ROOT_FG=${RAINBOW_CONTEXT_ROOT_FG:-'default'} RAINBOW_DIRECTORY_BG=${RAINBOW_DIRECTORY_BG:-'blue'} RAINBOW_DIRECTORY_FG=${RAINBOW_DIRECTORY_FG:-'black'} RAINBOW_GIT_CLEAN_BG=${RAINBOW_GIT_CLEAN_BG:-'green'} RAINBOW_GIT_CLEAN_FG=${RAINBOW_GIT_CLEAN_FG:-'black'} RAINBOW_GIT_UNTRACKED_BG=${RAINBOW_GIT_UNTRACKED_BG:-227} RAINBOW_GIT_UNTRACKED_FG=${RAINBOW_GIT_UNTRACKED_FG:-'black'} RAINBOW_GIT_UNPUSHED_BG=${RAINBOW_GIT_UNPUSHED_BG:-48} RAINBOW_GIT_UNPUSHED_FG=${RAINBOW_GIT_UNPUSHED_FG:-'black'} RAINBOW_GIT_MODIFIED_BG=${RAINBOW_GIT_MODIFIED_BG:-215} RAINBOW_GIT_MODIFIED_FG=${RAINBOW_GIT_MODIFIED_FG:-'black'} RAINBOW_GIT_STAGED_BG=${RAINBOW_GIT_STAGED_BG:-209} RAINBOW_GIT_STAGED_FG=${RAINBOW_GIT_STAGED_FG:-'black'} RAINBOW_GIT_ADDED_BG=${RAINBOW_GIT_ADDED_BG:-218} RAINBOW_GIT_ADDED_FG=${RAINBOW_GIT_ADDED_FG:-'black'} RAINBOW_GIT_TIME_SINCE_COMMIT_SHORT=${RAINBOW_GIT_TIME_SINCE_COMMIT_SHORT:-'green'} RAINBOW_GIT_TIME_SHORT_COMMIT_MEDIUM=${RAINBOW_GIT_TIME_SHORT_COMMIT_MEDIUM:-'yellow'} RAINBOW_GIT_TIME_SINCE_COMMIT_LONG=${RAINBOW_GIT_TIME_SINCE_COMMIT_LONG:-160} RAINBOW_GIT_TIME_SINCE_COMMIT_NEUTRAL=${RAINBOW_GIT_TIME_SINCE_COMMIT_NEUTRAL:-'cyan'} RAINBOW_HG_CLEAN_BG=${RAINBOW_HG_CLEAN_BG:-'green'} RAINBOW_HG_CLEAN_FG=${RAINBOW_HG_CLEAN_FG:-'black'} RAINBOW_HG_UNTRACKED_BG=${RAINBOW_HG_UNTRACKED_BG:-229} RAINBOW_HG_UNTRACKED_FG=${RAINBOW_HG_UNTRACKED_FG:-'black'} RAINBOW_HG_MODIFIED_BG=${RAINBOW_HG_MODIFIED_BG:-215} RAINBOW_HG_MODIFIED_FG=${RAINBOW_HG_MODIFIED_FG:-'black'} RAINBOW_HG_ADDED_BG=${RAINBOW_HG_ADDED_BG:-218} RAINBOW_HG_ADDED_FG=${RAINBOW_HG_ADDED_FG:-'black'} RAINBOW_HG_DELETED_BG=${RAINBOW_HG_DELETED_BG:-135} RAINBOW_HG_DELETED_FG=${RAINBOW_HG_DELETED_FG:-'black'} RAINBOW_VIRTUALENV_BG=${RAINBOW_VIRTUALENV_BG:-017} RAINBOW_VIRTUALENV_FG=${RAINBOW_VIRTUALENV_FG:-189} RAINBOW_STATUS_BG=${RAINBOW_STATUS_BG:-236} RAINBOW_STATUS_FG=${RAINBOW_STATUS_FG:-'default'} RAINBOW_STATUS_OK_BG=${RAINBOW_STATUS_OK_BG:-'black'} RAINBOW_STATUS_OK_FG=${RAINBOW_STATUS_OK_FG:-'green'} RAINBOW_STATUS_ERROR_BG=${RAINBOW_STATUS_ERROR_BG:-'red'} RAINBOW_STATUS_ERROR_FG=${RAINBOW_STATUS_ERROR_FG:-'yellow'} RAINBOW_EXCURSION_TIME_BG=${RAINBOW_EXCURSION_TIME_BG:-223} RAINBOW_EXCURSION_TIME_FG=${RAINBOW_EXCURSION_TIME_FG:-'black'} RAINBOW_TIME_BG=${RAINBOW_TIME_BG:-'white'} RAINBOW_TIME_FG=${RAINBOW_TIME_FG:-'black'} APPLE_ICON='\uF179' #  WINDOWS_ICON='\uF17A' #  FREEBSD_ICON='\UF30C ' #  ANDROID_ICON='\uF17B' #  LINUX_ARCH_ICON='\uF303' #  LINUX_CENTOS_ICON='\uF304' #  LINUX_COREOS_ICON='\uF305' #  LINUX_DEBIAN_ICON='\uF306' #  LINUX_RASPBIAN_ICON='\uF315' #  LINUX_ELEMENTARY_ICON='\uF309' #  LINUX_FEDORA_ICON='\uF30a' #  LINUX_GENTOO_ICON='\uF30d' #  LINUX_MAGEIA_ICON='\uF310' #  LINUX_MINT_ICON='\uF30e' #  LINUX_NIXOS_ICON='\uF313' #  LINUX_MANJARO_ICON='\uF312' #  LINUX_DEVUAN_ICON='\uF307' #  LINUX_ALPINE_ICON='\uF300' #  LINUX_AOSC_ICON='\uF301' #  LINUX_OPENSUSE_ICON='\uF314' #  LINUX_SABAYON_ICON='\uF317' #  LINUX_SLACKWARE_ICON='\uF319' #  LINUX_VOID_ICON='\uF17C' #  LINUX_UBUNTU_ICON='\uF31b' #  LINUX_ICON='\uF17C' #  SUNOS_ICON='\uF185 ' #  GIT_UNSTAGED_ICON='\uF06A' #  GIT_COMMIT_ICON='\uE729 ' #  GIT_BRANCH_ICON='\uF126 ' #  GIT_REMOTE_BRANCH_ICON='\uE728 ' #  GIT_ICON='\uF1D3 ' #  HG_ICON='\uF0C3 ' #  SSH_ICON='\uF489' #  EXECUTION_TIME_ICON='\uF252' #  PHP_ICON='\uE608' #  SCREEN_ICON='\uF879' #  CLOCK_ICON='\uF64F' #  prompt_os_icon() { local uname="$(uname)" local icon if [[ $uname == Linux && "$(uname -o 2>/dev/null)" == Android ]]; then icon="$ANDROID_ICON" else case $uname in SunOS) icon="$SUNOS_ICON";; Darwin) icon="$APPLE_ICON";; CYGWIN_NT-* | MSYS_NT-*) icon="$WINDOWS_ICON";; FreeBSD|OpenBSD|DragonFly) icon="$FREEBSD_ICON";; Linux) local os_id if [[ -r /etc/os-release ]]; then os_id=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"') fi case $os_id in *arch*) icon="$LINUX_ARCH_ICON";; *debian*) icon="$LINUX_DEBIAN_ICON";; *raspbian*) icon="$LINUX_RASPBIAN_ICON";; *ubuntu*) icon="$LINUX_UBUNTU_ICON";; *elementary*) icon="$LINUX_ELEMENTARY_ICON";; *fedora*) icon="$LINUX_FEDORA_ICON";; *coreos*) icon="$LINUX_COREOS_ICON";; *gentoo*) icon="$LINUX_GENTOO_ICON";; *mageia*) icon="$LINUX_MAGEIA_ICON";; *centos*) icon="$LINUX_CENTOS_ICON";; *opensuse*|*tumbleweed*) icon="$LINUX_OPENSUSE_ICON";; *sabayon*) icon="$LINUX_SABAYON_ICON";; *slackware*) icon="$LINUX_SLACKWARE_ICON";; *linuxmint*) icon="$LINUX_MINT_ICON";; *alpine*) icon="$LINUX_ALPINE_ICON";; *aosc*) icon="$LINUX_AOSC_ICON";; *nixos*) icon="$LINUX_NIXOS_ICON";; *devuan*) icon="$LINUX_DEVUAN_ICON";; *manjaro*) icon="$LINUX_MANJARO_ICON";; *void*) icon="$LINUX_VOID_ICON";; *) icon="$LINUX_ICON";; esac ;; esac fi prompt_segment white black "$icon" } # Special Powerline characters set_separator() { SEGMENT_SEPARATOR_RIGHT='\ue0b2' #  SEGMENT_SEPARATOR_LEFT='\ue0b0' #  } set_separator # Begin a segment # Takes two arguments, background and foreground. Both can be omitted, # rendering default background/foreground. prompt_segment() { local bg fg [[ -n $1 ]] && bg="%K{$1}" || bg='%k' [[ -n $2 ]] && fg="%F{$2}" || fg='%f' if [[ "$CURRENT_BG" != 'NONE' && $1 != "$CURRENT_BG" ]]; then echo -n " %{$bg%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR_LEFT%{$fg%} " else echo -n "%{$bg%}%{$fg%} " fi CURRENT_BG=$1 [[ -n $3 ]] && echo -n "$3" } prompt_segment_right() { local bg fg [[ -n $1 ]] && bg="%K{$1}" || bg="%k" [[ -n $2 ]] && fg="%F{$2}" || fg="%f" echo -n "%K{$CURRENT_BG}%F{$1}$SEGMENT_SEPARATOR_RIGHT%{$bg%}%{$fg%} " CURRENT_BG=$1 [[ -n $3 ]] && echo -n $3 } # End the prompt, closing any open segments prompt_end() { if [[ -n "$CURRENT_BG" ]]; then echo -n " %{%k%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR_LEFT" else echo -n '%{%k%}' fi echo -n '%{%f%}' CURRENT_BG='' } # # Prompt functions # # Context: user@hostname (who am I and where am I) prompt_context() { if [ -n "$SSH_CLIENT" ]; then prompt_segment $RAINBOW_CONTEXT_SSH_BG $RAINBOW_CONTEXT_SSH_FG "$SSH_ICON %F{$RAINBOW_CONTEXT_SSH_FG}%n%f%F{$RAINBOW_CONTEXT_SSH_USER_FG}@%F{$RAINBOW_CONTEXT_SSH_HOST_FG}%m" else if [[ "$TERM" == screen* ]]; then local screen=$SCREEN_ICON" " fi if [[ $UID -eq 0 ]]; then prompt_segment $RAINBOW_CONTEXT_ROOT_BG $RAINBOW_CONTEXT_ROOT_FG "$screen⚡%B%n%f@%m%b" else prompt_segment $RAINBOW_CONTEXT_BG $RAINBOW_CONTEXT_FG "$screen%n%f" fi fi } # Git: branch/detached head, dirty status prompt_git() { local repo_path local GIT_STATUS repo_path=$(git rev-parse --git-dir 2>/dev/null) if [[ -n $repo_path ]]; then local PL_BRANCH_CHAR dirty bgcolor fgcolor mode ref set_branch_char() { PL_BRANCH_CHAR=$VCS_GIT_ICON$'\ue0a0' #  } set_branch_char GIT_STATUS=$( command git status --porcelain --ignore-submodules=dirty 2>/dev/null | sed -e 's/^ //g' ) modified=$(<<< "$GIT_STATUS" grep '^M') untracked=$(<<< "$GIT_STATUS" grep '^?') added=$(<<< "$GIT_STATUS" grep '^A') staged=$(git diff --name-only --cached) unpushed=$(command git cherry 2>/dev/null) if [[ -n $added ]]; then bgcolor=$RAINBOW_GIT_ADDED_BG fgcolor=$RAINBOW_GIT_ADDED_FG elif [[ -n $staged ]]; then bgcolor=$RAINBOW_GIT_STAGED_BG fgcolor=$RAINBOW_GIT_STAGED_FG elif [[ -n $modified ]]; then bgcolor=$RAINBOW_GIT_MODIFIED_BG fgcolor=$RAINBOW_GIT_MODIFIED_FG elif [[ -n $untracked ]]; then bgcolor=$RAINBOW_GIT_UNTRACKED_BG fgcolor=$RAINBOW_GIT_UNTRACKED_FG elif [[ -n $unpushed ]]; then bgcolor=$RAINBOW_GIT_UNPUSHED_BG fgcolor=$RAINBOW_GIT_UNPUSHED_FG else bgcolor=$RAINBOW_GIT_CLEAN_BG fgcolor=$RAINBOW_GIT_CLEAN_FG fi prompt_segment "$bgcolor" "$fgcolor" if [[ -e "${repo_path}/BISECT_LOG" ]]; then mode=' ' elif [[ -e "${repo_path}/MERGE_HEAD" ]]; then mode=' >M<' elif [[ -e "${repo_path}/rebase" || -e "${repo_path}/rebase-apply" || -e "${repo_path}/rebase-merge" || -e "${repo_path}/../.dotest" ]]; then mode=' >R>' fi # vcs_info is too slow with MSYS2 (~300ms with i7-6770K + SSD) if [[ -z $MSYS ]]; then autoload -Uz vcs_info zstyle ':vcs_info:*' enable git zstyle ':vcs_info:*' check-for-changes true zstyle ':vcs_info:*' stagedstr '✚' zstyle ':vcs_info:*' unstagedstr '●' zstyle ':vcs_info:*' formats ' %u%c' zstyle ':vcs_info:*' actionformats ' %u%c' vcs_info else if [[ -n $dirty ]]; then vcs_info_msg_0_=' !' fi fi ref=$(git symbolic-ref HEAD 2> /dev/null) || ref="➦ $(git rev-parse --short HEAD 2> /dev/null)" echo -n "${ref/refs\/heads\//$PL_BRANCH_CHAR }${vcs_info_msg_0_%% }${mode}" fi } # Determine the time since last commit. If branch is clean, # use a neutral color, otherwise colors will vary according to time. function prompt_git_time() { local symbols if git rev-parse --git-dir > /dev/null 2>&1; then # Only proceed if there is actually a commit. if [[ $(git log 2>&1 > /dev/null | grep -c "^fatal: bad default revision") == 0 ]]; then # Get the last commit. last_commit=`git log --pretty=format:'%at' -1 2> /dev/null` now=`date +%s` seconds_since_last_commit=$((now-last_commit)) # Totals MINUTES=$((seconds_since_last_commit / 60)) HOURS=$((seconds_since_last_commit/3600)) # Sub-hours and sub-minutes DAYS=$((seconds_since_last_commit / 86400)) SUB_HOURS=$((HOURS % 24)) SUB_MINUTES=$((MINUTES % 60)) FGCOLOR="black" if [[ -n $(git status -s 2> /dev/null) ]]; then if [ "$MINUTES" -gt 30 ]; then BGCOLOR="$RAINBOW_GIT_TIME_SINCE_COMMIT_LONG" FGCOLOR="white" symbols=$GIT_UNSTAGED_ICON" " elif [ "$MINUTES" -gt 10 ]; then BGCOLOR="$RAINBOW_GIT_TIME_SHORT_COMMIT_MEDIUM" symbols=$GIT_UNSTAGED_ICON" " else BGCOLOR="$RAINBOW_GIT_TIME_SINCE_COMMIT_SHORT" symbols=$GIT_UNSTAGED_ICON" " fi else BGCOLOR="$RAINBOW_GIT_TIME_SINCE_COMMIT_NEUTRAL" symbols=$GIT_COMMIT_ICON fi if [ "$HOURS" -gt 24 ]; then prompt_segment_right $BGCOLOR $FGCOLOR "${DAYS}d${SUB_HOURS}h${SUB_MINUTES}m $symbols%{$reset_color%}" elif [ "$MINUTES" -gt 60 ]; then prompt_segment_right $BGCOLOR $FGCOLOR "${HOURS}h${SUB_MINUTES}m $symbols%{$reset_color%}" else prompt_segment_right $BGCOLOR $FGCOLOR "${MINUTES}m $symbols%{$reset_color%}" fi fi fi } prompt_hg() { if hg id >/dev/null 2>&1; then local INDEX=$(hg status 2>/dev/null) hg_status="" rev="" rev=$(hg id -n 2>/dev/null | sed 's/[^-0-9]//g') branch=$(hg branch) # Indicators are suffixed instead of prefixed to each other to # provide uniform view across git and mercurial indicators if $(echo "$INDEX" | grep -E '^\? ' &> /dev/null); then prompt_segment $RAINBOW_HG_UNTRACKED_BG $RAINBOW_HG_UNTRACKED_FG hg_status="?"$hg_status elif $(echo "$INDEX" | grep -E '^A ' &> /dev/null); then prompt_segment $RAINBOW_HG_ADDED_BG $RAINBOW_HG_ADDED_FG hg_status="+"$hg_status elif $(echo "$INDEX" | grep -E '^M ' &> /dev/null); then prompt_segment $RAINBOW_HG_MODIFIED_BG $RAINBOW_HG_MODIFIED_FG hg_status="!"$hg_status elif $(echo "$INDEX" | grep -E '^(R|!)' &> /dev/null); then prompt_segment $RAINBOW_HG_DELETED_BG $RAINBOW_HG_DELETED_FG hg_status="✘"$hg_status else prompt_segment $RAINBOW_HG_CLEAN_BG $RAINBOW_HG_CLEAN_FG hg_status="✔"$hg_status fi echo -n "☿ $rev@$branch "$hg_status fi } is_hg() { local root="$(pwd -P)" while [ "$root" ] && [ ! -d "$root/.hg" ]; do root="${root%/*}" done [[ -n "$root" ]] &>/dev/null } function prompt_hg_time() { is_hg || return local symbols # Only proceed if there is actually a commit. if [[ $(hg log 2>&1 > /dev/null | grep -c "") != '' ]]; then # Get the last commit date. last_entry=`hg log -l 1 --template "{date|hgdate}" | awk -F ' ' '{ print $1 }' 2>/dev/null` now=`date +%s` seconds_since_last_commit=$((now-last_entry)) # Totals local MINUTES=$((seconds_since_last_commit / 60)) local HOURS=$((seconds_since_last_commit/3600)) # Sub-hours and sub-minutes local DAYS=$((seconds_since_last_commit / 86400)) local SUB_HOURS=$((HOURS % 24)) local SUB_MINUTES=$((MINUTES % 60)) FGCOLOR="black" if [[ -n $(hg status -u 2> /dev/null) ]]; then if [ "$MINUTES" -gt 30 ]; then BGCOLOR="$RAINBOW_GIT_TIME_SINCE_COMMIT_LONG" FGCOLOR="white" symbols=$GIT_UNSTAGED_ICON" " elif [ "$MINUTES" -gt 10 ]; then BGCOLOR="$RAINBOW_GIT_TIME_SHORT_COMMIT_MEDIUM" symbols=$GIT_UNSTAGED_ICON" " else BGCOLOR="$RAINBOW_GIT_TIME_SINCE_COMMIT_SHORT" symbols=$GIT_UNSTAGED_ICON" " fi else BGCOLOR="$RAINBOW_GIT_TIME_SINCE_COMMIT_NEUTRAL" symbols=$GIT_COMMIT_ICON fi if [ "$HOURS" -gt 24 ]; then prompt_segment_right $BGCOLOR $FGCOLOR "${DAYS}d${SUB_HOURS}h${SUB_MINUTES}m $symbols%{$reset_color%}" elif [ "$MINUTES" -gt 60 ]; then prompt_segment_right $BGCOLOR $FGCOLOR "${HOURS}h${SUB_MINUTES}m $symbols%{$reset_color%}" else prompt_segment_right $BGCOLOR $FGCOLOR "${MINUTES}m $symbols%{$reset_color%}" fi fi } # Turn '/some/quite/very/long/path' into '/s/q/v/l/path' function shrinked_path() { local paths=(${PWD/$HOME/\~}) 'cur_dir' paths=(${(s:/:)paths}) for idx in {1..$#paths}; do if [[ idx -lt $#paths ]]; then cur_dir+="${paths[idx]:0:1}" else cur_dir+="${paths[idx]}" fi cur_dir+='/' done echo "${cur_dir: :-1}" } # Dir: current working directory prompt_dir() { local dir if [[ -n $RAINBOW_KEEP_PATH ]]; then dir='%~' else dir=$(shrinked_path) fi prompt_segment "$RAINBOW_DIRECTORY_BG" "$RAINBOW_DIRECTORY_FG" "$dir" } # Virtualenv: current working virtualenv prompt_virtualenv() { local virtualenv_path="$VIRTUAL_ENV" if [[ -n $virtualenv_path && -n $VIRTUAL_ENV_DISABLE_PROMPT ]]; then prompt_segment "$RAINBOW_VIRTUALENV_BG" "$RAINBOW_VIRTUALENV_FG" "$(basename "$virtualenv_path")" fi } preexec() { preexec_called=1 timer=$SECONDS } prompt_error() { if [ $RETVAL -ne 0 ] && [ "$preexec_called" = 1 ]; then prompt_segment_right $RAINBOW_STATUS_ERROR_BG $RAINBOW_STATUS_ERROR_FG '✘ %? ' unset preexec_called; else prompt_segment_right $RAINBOW_STATUS_OK_BG $RAINBOW_STATUS_OK_FG '✔ ' fi } # Status: background jobs prompt_status() { local symbols symbols=() [[ $(jobs -l | wc -l) -gt 0 ]] && symbols+='%{%F{cyan}%}⚙ ' [[ -n "$symbols" ]] && prompt_segment_right "$RAINBOW_STATUS_BG" "$RAINBOW_STATUS_FG" "$symbols" } prompt_excursion_time() { if [ $timer ]; then now=$SECONDS elapsed=$(($now-$timer)) unset $timer; unset $now; hours=$(($elapsed/3600)) min=$(($elapsed/60)) sec=$(($elapsed%60)) if [ "$elapsed" -ge 2 ]; then if [ "$elapsed" -le 60 ]; then prompt_segment_right $RAINBOW_EXCURSION_TIME_BG $RAINBOW_EXCURSION_TIME_FG $elapsed"s $EXECUTION_TIME_ICON " elif [ "$elapsed" -gt 60 ] && [ "$elapsed" -le 180 ]; then prompt_segment_right $RAINBOW_EXCURSION_TIME_BG $RAINBOW_EXCURSION_TIME_FG $min"m "$sec"s $EXECUTION_TIME_ICON " else if [ "$hours" -gt 0 ]; then min=$(($min%60)) prompt_segment_right $RAINBOW_EXCURSION_TIME_BG $RAINBOW_EXCURSION_TIME_FG $hours"h "$min"m "$sec"s $EXECUTION_TIME_ICON " else prompt_segment_right $RAINBOW_EXCURSION_TIME_BG $RAINBOW_EXCURSION_TIME_FG $min"m "$sec"s $EXECUTION_TIME_ICON " fi fi fi fi } prompt_time() { prompt_segment_right $RAINBOW_TIME_BG $RAINBOW_TIME_FG '%D{%H:%M:%S} '$CLOCK_ICON' ' } # # Prompt # build_prompt() { prompt_os_icon prompt_virtualenv prompt_context prompt_dir prompt_git prompt_hg prompt_end } build_rprompt() { RETVAL=$? prompt_error prompt_status prompt_excursion_time prompt_git_time prompt_hg_time prompt_time } export VIRTUAL_ENV_DISABLE_PROMPT='true' PROMPT='╭─%{%f%b%k%}$(build_prompt) ╰─➤ ' RPROMPT='%{%f%b%k%} $(build_rprompt)'