# # Garrett Zsh Theme for Prezto # Created with modified code by Chauncey Garrett # @vrtcl1dvoshun # (ver.2013.09.30.23.32.46) # # A prompt full of information when you need it and absent when you don't. # # This prompt has the following features: # * change prompt color when uid is root # * change host color when on ssh # * display full or truncated hostname on ssh # * determine the number of background jobs # * report the present working directory # * report return codes # * report local time # * report the terminal line number # * report git status, git remote status, git prompt info and git SHA information # * indicate vi-mode # * notifications for commands taking longer than x time # # Features may be disabled and rearranged as desired by using the corresponding tokens. # # # Load dependencies # pmodload 'helper' # # PROMPT | prompt_garrett_help # - prompt configuration help # TODO not even remotely finished... # function prompt_garrett_help() { cat <<'EOF' This prompt is configurable via styles: Context: :prompt:garrett Colors (red green yellow blue magenta cyan white grey): color_user | The color for user@host. Defaults to 'green' root_color | The color for the hostname for root. Defaults to 'red' color_prompt | The color for everything else. Defaults to '' Path (path type - possible values): ratio - use COLUMNS/ratio to clip the path. Default. fixed - use a fixed maximum lenght. subdir - clip by number of subdirectories. full - show the full path Path length styles: ratio | the ratio for the 'ratio' path style, funnily enough. Defaults to 6. length | the maximum length for the 'fixed' path style. Defaults to 20. subdir | the number of subdirs to show for the 'subdir' path style. Defaults to 3. You can set styles in the current terminal to test things out, values will be updated. EOF } # # PROMPT | Preview # - display a preview of the prompt # TODO not ready # function prompt_garrett_preview { if (( $# > 0 )) then prompt_preview_theme 'garrett' "$@" else prompt_preview_theme 'garrett' # red green blue fi } # # PROMPT | prompt_garrett_pwd # - format the pwd display # function prompt_garrett_pwd { local pwd="${PWD/#$HOME/~}" if [[ "$pwd" == (#m)[/~] ]] then current_dir="${color_pwd}$MATCH" unset MATCH else current_dir="${color_pwd}${${${(@j:/:M)${(@s:/:)pwd}##.#?}:h}%/}/${pwd:t}" fi } # # PROMPT | prompt_garrett_number_jobs # - determine the number of background jobs # function prompt_garrett_number_jobs { number_jobs="%(1j.${color_prompt}J:${cyan}%j.) " } # # Notifications # - notify of command completion after x amount of time has passed # function prompt_garrett_notification_precmd { # trigger a notification after x time has elapsed DELAY_AFTER_NOTIFICATION=1 # determine x time elapsed start=${PREEXEC_TIME:-$(date +'%s')} stop=$(date +'%s') let elapsed=$stop-$start # notify! if [ $elapsed -gt $DELAY_AFTER_NOTIFICATION ] then # x time has passed, so notify! if [[ "$OSTYPE" == darwin* ]] && (( $+commands[terminal-notifier] )) then terminal-notifier -title "${PREEXEC_CMD:-Some command}" -message "required $elapsed s" -sound Tink # growlnotify -n "Terminal" -m "Took $elapsed s" ${PREEXEC_CMD:-Some command} else tput bel fi fi } # # PROMPT | prompt_garrett_chpwd # - a function which is executed whenever the directory is changed # function prompt_garrett_chpwd { emulate -L zsh # TODO can't remember why this is necessary... ls --color=auto # list the contents of the new directory } # # PROMPT | prompt_garrett_preexec # - functions that are called before command execution # function prompt_garrett_preexec { # Define timer and cmd for notification export PREEXEC_TIME=$(date +'%s') export PREEXEC_CMD="\$ $1" # Ensure terminal code isn't colored from prompt print -n "$reset_color" } # # PROMPT | prompt_garrett_precmd # - functions that are called before each prompt is displayed # function prompt_garrett_precmd { setopt LOCAL_OPTIONS unsetopt XTRACE KSH_ARRAYS # Show number of background jobs prompt_garrett_number_jobs # Format PWD prompt_garrett_pwd # Trigger a notification after x time has elapsed eval prompt_garrett_notification_precmd # Get ruby info if (( $+functions[ruby-info] )) then ruby-info fi # Get git repository info if (( $+functions[git-info] )) then git-info fi # # Add a line to prompt for visibility # # Determine the width local prompt_width_term (( prompt_width_term= ${COLUMNS} - 1 )) # Determine the length needed for prompt_space # NOTE: Be sure not to include the ${(e)prompt_space} portion or it won't work local prompt_line1="${altchar_upper_left_corner}( ${current_dir}${git_info[remote_status]}${git_info[prompt_info]}${git_info[local_status]}${git_info[sha]} )( ${ruby_info[version]}${location} )${altchar_upper_right_corner}" local zero='%([BSUbfksu]|([FB]|){*})' local prompt_width_line1=${#${(S%%)prompt_line1//$~zero/}} # Calc the padding local prompt_space_padding (( prompt_space_padding= ${prompt_width_term} - ${prompt_width_line1} )) # Add the correct number of characters local prompt_space_character="${altchar_padding}" eval prompt_space="${color_prompt}\${(l.${prompt_space_padding}..${prompt_space_character}.)}" # Prompt line 1 print print -P '${altchar_enable}${color_prompt}${altchar_upper_left_corner}( ${current_dir}${git_info[remote_status]}${git_info[prompt_info]}${git_info[local_status]}${git_info[sha]} ${color_prompt})${altchar_enter}${(e)prompt_space}${altchar_leave}( ${ruby_info[version]}${location}${color_prompt} )${altchar_upper_right_corner}' } # # PROMPT | prompt_garrett_setup # - finally, configure the prompt # function prompt_garrett_setup { # Load necessary modules setopt LOCAL_OPTIONS unsetopt XTRACE KSH_ARRAYS prompt_opts=(cr percent subst) # Add hooks for calling preexec, precmd & chpwd autoload -Uz add-zsh-hook add-zsh-hook preexec prompt_garrett_preexec add-zsh-hook precmd prompt_garrett_precmd add-zsh-hook chpwd prompt_garrett_chpwd # # Colors # # Alias the colors [[ -z $(functions colors) ]] && autoload -U colors && colors for color in black red green yellow blue magenta cyan white grey do eval $color='%F{${(L)color}}' eval ${color}_BOLD='%B{${(L)color}}' done # Color scheme eval color_pwd=\$\{${2:-'blue'}\} # eval color_pwd=${2:-'${blue}'} eval color_line_number=${5:-'${magenta}'} eval color_time=${6:-'${green}'} eval color_git_branch=${7:-'${green}'} eval color_git_sha=${8:-'${yellow}'} eval color_ruby_version=${8:-'${yellow}'} # Determine prompt, user and host colors if [[ "$EUID" = "0" ]] || [[ "$USER" = 'root' ]] then # root user # set colors eval color_user=${3:-'${red}'} eval color_host=${3:-'${red}'} eval color_prompt=${3:-'${red}'} # set style eval user='%S${color_user}%n%s' eval host='${color_host}%m' # hostname up to first . (dot) (use %M for full hostname) eval location='${user}${cyan}@${host}' # user@host.name elif [[ -n "$SSH_CLIENT" || -n "$SSH2_CLIENT" ]] then # on SSH # set colors eval color_user=${3:-'${green}'} eval color_host=${3:-'${yellow}'} eval color_prompt=${3:-'${yellow}'} # set style eval user='%S${color_user}%n%s' eval host='${color_host}%m' # hostname up to first . (dot) (use %M for full hostname) eval location='${user}${cyan}@${host}' # user@host.name else # normal user # set colors eval color_user=${1:-'${green}'} eval color_host=${1:-'${green}'} eval color_prompt=${1:-'${grey}'} # set style eval user='' eval host='${color_host}%m' # hostname up to first . (dot) (use %M for full hostname) eval location='${user}${cyan}@${host}' # user@host.name fi # # Report return code # eval return_code='%(?..${red}%? ⏎ ) ' # # Report local time # eval current_time='${green}%T' # 24 hour time format # eval current_time='${green}%*' # 24 hour time format, second precise # eval current_time='${green}%t' # AM/PM time format # Keep the time updated # schedprompt() # { # emulate -L zsh # zmodload -i zsh/sched # # Remove existing event, so that multiple calls to "schedprompt" work OK (you could put one in precmd to push the timer 30 seconds into the future, for example.) # integer i=${"${(@)zsh_scheduled_events#*:*:}"[(i)schedprompt]} # (( i )) && sched -$i # # Test that zle is running before calling the widget (recommended to avoid error messages). Otherwise it updates on entry to zle, so there's no loss. # zle && zle reset-prompt # # This ensures we're not too far off the start of the minute # sched +1 schedprompt # } # schedprompt # # Report terminal line number # eval line_number='${green}+${magenta}%!' # # Report git info # NOTE: listed in order in which the information will appear in the prompt # # Git verbose data (commit counts, etc.) # zstyle ':prezto:module:git:info' verbose 'yes' # Git prompt info zstyle ':prezto:module:git:info:branch' format "${cyan} λ${color_prompt}:${green}%b" zstyle ':prezto:module:git:info:remote' format "" zstyle ':prezto:module:git:info:action' format "${yellow} %s" zstyle ':prezto:module:git:info:position' format "${red} %p" # Git commit SHA zstyle ':prezto:module:git:info:commit' format "${yellow} %.7c" # Git remote status zstyle ':prezto:module:git:info:behind' format "${magenta} ⬇ " zstyle ':prezto:module:git:info:ahead' format "${magenta} ⬆ " zstyle ':prezto:module:git:info:diverged' format "${magenta} ⥮" zstyle ':prezto:module:git:info:stashed' format "${cyan} ✭" # Git local status zstyle ':prezto:module:git:info:clean' format "" zstyle ':prezto:module:git:info:dirty' format "${color_prompt} |" zstyle ':prezto:module:git:info:added' format "${green} ✚" zstyle ':prezto:module:git:info:deleted' format "${red} ✗" zstyle ':prezto:module:git:info:modified' format "${blue} ✱" zstyle ':prezto:module:git:info:renamed' format "${magenta} ➜" zstyle ':prezto:module:git:info:unmerged' format "${yellow} ═" zstyle ':prezto:module:git:info:untracked' format "${white} ◼" # Git prompt styles zstyle ':prezto:module:git:info:keys' format \ 'prompt_info' "%b" \ 'rprompt' "[%R]" \ 'local_status' "%C%D%a%d%m%r%U%u" \ 'remote_status' "%B%A%S" \ 'sha' "%c" \ # # Report ruby version # %v | ruby version # zstyle ':prezto:module:ruby:info:version' format "${yellow}ruby:%v " # # Vim mode indicator # zstyle ':prezto:module:editor:info:keymap:primary' format "${red}❱%(?.${color_prompt}.${red})❱❱ " zstyle ':prezto:module:editor:info:keymap:alternate' format "${red}❰%(?.${color_prompt}.${red})❰❰ " # zstyle ':prezto:module:editor:info:keymap:primary:insert' format "${red}I " zstyle ':prezto:module:editor:info:keymap:primary:overwrite' format "${red}♺ " zstyle ':prezto:module:editor:info:completing' format "${red}..." # # Use the extended character set, if available # typeset -A altchar set -A altchar ${(s..)terminfo[acsc]} altchar_enable="%{$terminfo[enacs]%}" altchar_enter="%{$terminfo[smacs]%}" altchar_leave="%{$terminfo[rmacs]%}" altchar_padding=${altchar[q]:--} altchar_upper_left_corner=%{$terminfo[smacs]%}${altchar[l]:--}${altchar[q]:--}%{$terminfo[rmacs]%} altchar_lower_left_corner=%{$terminfo[smacs]%}${altchar[m]:--}${altchar[q]:--}%{$terminfo[rmacs]%} altchar_upper_right_corner=%{$terminfo[smacs]%}${altchar[q]:--}${altchar[k]:--}%{$terminfo[rmacs]%} altchar_lower_right_corner=%{$terminfo[smacs]%}${altchar[q]:--}${altchar[j]:--}%{$terminfo[rmacs]%} # # Finally! # # | PROMPT | Left # | RPROMPT | Right # | PROMPT2 | Continuation # | PROMPT3 | Selection # | PROMPT4 | Execution trace # | SPROMPT | Autocorrection # | SUDO_PS1 | Backup root prompt # if (( $SHLVL == 1 )) then export PROMPT='${altchar_enable}${color_prompt}${altchar_lower_left_corner}${editor_info[keymap]}' else export PROMPT='${color_prompt}${altchar_lower_left_corner}( ${cyan}$SHLVL ${color_prompt}) ${editor_info[keymap]}' fi export RPROMPT='${editor_info[alternate]}${editor_info[overwrite]}${return_code}${number_jobs}${line_number} ${current_time} %(?.${color_prompt}.${red})❰${color_prompt}${altchar_lower_right_corner}' export PROMPT2='${color_prompt}%_ ${editor_info[keymap]}' export PROMPT3='${yellow}#? ' export PROMPT4='${blue}$0${color_prompt}@${yellow}%i+ ' export SPROMPT=' ${color_prompt}Correct ${red}%R${color_prompt} to ${green}%r${color_prompt} ? [nyae] ' export SUDO_PS1="\[\e[31;1;46m\][\u] \w \$\[\e[0m\] " } prompt_garrett_setup "$@"