From aeabfdc084a91af872ce368ab300b3cea6f3889d Mon Sep 17 00:00:00 2001 From: Chauncey Garrett Date: Tue, 18 Jun 2013 16:03:48 -0500 Subject: [PATCH] Vastly improved the prompt - Added full termwidth prompt - Cleaned up the codebase - More efficient [ticket: X] --- modules/prompt/functions/prompt_garrett_setup | 419 +++++++++--------- 1 file changed, 219 insertions(+), 200 deletions(-) diff --git a/modules/prompt/functions/prompt_garrett_setup b/modules/prompt/functions/prompt_garrett_setup index 7dfa41f0..7d9cce86 100644 --- a/modules/prompt/functions/prompt_garrett_setup +++ b/modules/prompt/functions/prompt_garrett_setup @@ -30,76 +30,72 @@ # ————————————————————————————————————————————————————————————————————— pmodload 'helper' - # ————————————————————————————————————————————————————————————————————— # Help function # TODO not even remotely finished... # ————————————————————————————————————————————————————————————————————— function prompt_garrett_help() { - cat <<'EOF' + cat <<'EOF' This prompt is configurable via styles: - Context: :prompt:garrett + Context: :prompt:garrett - Colors (in zsh/terminfo value): - user-color - the color for user@host. defaults to 'green' - root-color - the color for the hostname for root. defaults to 'red' - prompt-color - the color for everything else. defaults to 'blue' + 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 type: - path - 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 (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. - default to 6. - length - the maximin lenght for the 'fixed' path style. - defaults to 20 - subdir - the number of subdirs to show for the 'subdir' path style. - defaults to 3. + 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. + You can set styles in the current terminal to test things out, values will be updated. EOF } # ————————————————————————————————————————————————————————————————————— # Preview -# TODO not sure if I need to do this or really how... +# TODO not ready # ————————————————————————————————————————————————————————————————————— function prompt_garrett_preview { - prompt_preview_theme 'garrett' + if (( $# > 0 )); then + prompt_preview_theme 'garrett' "$@" + else + prompt_preview_theme 'garrett' #red green blue + # print + # prompt_preview_theme 'garrett' yellow magenta black + fi } # ————————————————————————————————————————————————————————————————————— -# PWD truncation precmd -# TODO PWD doesn't work like the rest of my "easy variables" +# PWD truncation precmd function # ————————————————————————————————————————————————————————————————————— function prompt_garrett_pwd { + local pwd="${PWD/#$HOME/~}" - eval pwd='${PWD/#$HOME/~}' - if [[ "$pwd" == (#m)[/~] ]]; then - eval _prompt_garrett_pwd="$MATCH" + current_dir="${color_pwd}$MATCH" unset MATCH else - eval _prompt_garrett_pwd='${${${(@j:/:M)${(@s:/:)pwd}##.#?}:h}%/}/${pwd:t}' + current_dir="${color_pwd}${${${(@j:/:M)${(@s:/:)pwd}##.#?}:h}%/}/${pwd:t}" fi } # ————————————————————————————————————————————————————————————————————— -# PROMPT chpwd -# - a function which is executed whenever the directory is changed +# Determine number of background jobs precmd function # ————————————————————————————————————————————————————————————————————— -function prompt_garrett_chpwd { - emulate -L zsh # TODO can't remember why this is necessary... - ls -AG # list the contents of the new directory +function prompt_garrett_number_jobs { + number_jobs="%(1j.${color_prompt}J:${cyan}%j.)" } - + # ————————————————————————————————————————————————————————————————————— # Growl Notifications after x amount of time has passed # ————————————————————————————————————————————————————————————————————— @@ -126,125 +122,187 @@ function prompt_garrett_growl_precmd { } # ————————————————————————————————————————————————————————————————————— -# PROMPT precmd (After a command execution) +# PROMPT 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 -AG # list the contents of the new directory +} + +# ————————————————————————————————————————————————————————————————————— +# PROMPT preexec (Before command execution) +# ————————————————————————————————————————————————————————————————————— +function prompt_garrett_preexec { + # ————————————————————————————————————————————————————————————————————— + # Define timer and cmd for growl notification + # ————————————————————————————————————————————————————————————————————— + if (( $+commands[growlnotify] )); then + export PREEXEC_TIME=$(date +'%s') + export PREEXEC_CMD="The command: $1" + fi + + # ————————————————————————————————————————————————————————————————————— + # Ensure terminal code isn't colored from prompt + # ————————————————————————————————————————————————————————————————————— + print -n "$reset_color" +} + +# ————————————————————————————————————————————————————————————————————— +# PROMPT precmd (After command execution) # ————————————————————————————————————————————————————————————————————— function prompt_garrett_precmd { setopt LOCAL_OPTIONS unsetopt XTRACE KSH_ARRAYS - # Format PWD. - eval prompt_garrett_pwd + # ————————————————————————————————————————————————————————————————————— + # Show number of background jobs + # ————————————————————————————————————————————————————————————————————— + prompt_garrett_number_jobs + + # ————————————————————————————————————————————————————————————————————— + # Format PWD + # ————————————————————————————————————————————————————————————————————— + prompt_garrett_pwd + # ————————————————————————————————————————————————————————————————————— # Trigger a growl notification after x time has elapsed + # ————————————————————————————————————————————————————————————————————— if (( $+commands[growlnotify] )); then eval prompt_garrett_growl_precmd fi - - # Get git repository information. - if (( $+functions[git-info] )); then - git-info - fi -} - -# ————————————————————————————————————————————————————————————————————— -# PROMPT preexec -# ————————————————————————————————————————————————————————————————————— -function preexec { + + # ————————————————————————————————————————————————————————————————————— # Get ruby info + # ————————————————————————————————————————————————————————————————————— if (( $+functions[ruby-info] )); then ruby-info fi - # Define timer and cmd for growl notification - if (( $+commands[growlnotify] )); then - export PREEXEC_TIME=$(date +'%s') - export PREEXEC_CMD="The command: $1" - fi + # ————————————————————————————————————————————————————————————————————— + # Get git repository info + # ————————————————————————————————————————————————————————————————————— + if (( $+functions[git-info] )); then + git-info + fi + + # ————————————————————————————————————————————————————————————————————— + # Add a line to prompt for visibility + # ————————————————————————————————————————————————————————————————————— + 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="╭─( ${current_dir} )${git_info[remote_status]}${git_info[prompt_info]}${git_info[local_status]}${git_info[sha]} ( ${current_time} )─┐" + local zero='%([BSUbfksu]|([FB]|){*})' + local prompt_width_line1=${#${(S%%)prompt_line1//$~zero/}} + + local prompt_space_padding + (( prompt_space_padding= ${prompt_width_term} - ${prompt_width_line1} )) + + local prompt_space_character="—" + eval prompt_space="${color_prompt}\${(l.${prompt_space_padding}..${prompt_space_character}.)}" + + # ————————————————————————————————————————————————————————————————————— + # Prompt line 1 + # ————————————————————————————————————————————————————————————————————— + print + print -P '${color_prompt}╭─( ${current_dir} ${color_prompt})${git_info[remote_status]}${git_info[prompt_info]}${git_info[local_status]}${git_info[sha]} ${(e)prompt_space}( ${current_time}${color_prompt} )─┐' } # ————————————————————————————————————————————————————————————————————— # Setup prompt # ————————————————————————————————————————————————————————————————————— function prompt_garrett_setup { - setopt LOCAL_OPTIONS - unsetopt XTRACE KSH_ARRAYS - prompt_opts=(cr percent subst) - # ————————————————————————————————————————————————————————————————————— # Load necessary modules # ————————————————————————————————————————————————————————————————————— - setopt prompt_subst + setopt LOCAL_OPTIONS + unsetopt XTRACE KSH_ARRAYS + prompt_opts=(cr percent subst) # ————————————————————————————————————————————————————————————————————— # Add hook for calling precommand & 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 # ————————————————————————————————————————————————————————————————————— - # Alias the colors + # Colors # ————————————————————————————————————————————————————————————————————— - [[ -z $(functions colors) ]] && autoload -U colors && colors # Used in the color alias below - #[[ -z $(functions zsh/terminfo) ]] && autoload -Uz zsh/terminfo # TODO not sure if zsh/terminfo is necessary... - for color in red green yellow blue magenta cyan white grey; do - eval $color='%{$fg_no_bold[${(L)color}]%}' - eval BOLD_$color='%{$fg_bold[${(L)color}]%}' + # Alias the colors + [[ -z $(functions colors) ]] && autoload -U colors && colors + typeset -Ag FX FG BG + + 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 - eval no_color='%{$reset_color%}' - # ————————————————————————————————————————————————————————————————————— - # Check the UID to set prompt color - # TODO better Zsh way to determine UID? - # ————————————————————————————————————————————————————————————————————— - if [[ "$EUID" = "0" ]] || [[ "$USER" = 'root' ]]; then # root - eval user_color='${red}' # set root user color - eval prompt_color='${red}' # set root prompt color - eval BOLD_prompt_color='${BOLD_red}' # set root prompt BOLD color - eval user='%S${user_color}%n%s' + for color in {000..255}; do + FG[$color]="%F[38;5;${color}m" + BG[$color]="%K[48;5;${color}m" + done + + FX=( + reset "%{%}" + bold "%B" no-bold "%b" + italic "%{%}" no-italic "%{%}" + underline "%U" no-underline "%u" + blink "%{%}" no-blink "%{%}" + reverse "%{%}" no-reverse "%{%}" + standout "%S" no-standout "%s" + ) + + # Show all 256 colors with color number + function spectrum_ls() { + for code in {000..255}; do + print -P -- "$code: %K{$code} %k %F{$code} Lorem ipsum...%f" + 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 + eval color_user=${3:-'${red}'} + eval color_host=${3:-'${red}'} + eval color_prompt=${3:-'${red}'} + # eval color_prompt_BOLD=${3:-'${red_BOLD}'} + eval user='%S${color_user}%n%s' + elif [[ -n "$SSH_CLIENT" || -n "$SSH2_CLIENT" ]]; then # on SSH + eval color_user=${3:-'${green}'} + eval color_host=${3:-'${yellow}'} + eval color_prompt=${3:-'${yellow}'} + # eval color_prompt_BOLD=${3:-'${yellow_BOLD}'} + eval user='%S${color_user}%n%s' else # normal user - eval user_color='${green}' # set normal user color - eval prompt_color='${white}' # set normal prompt color - eval BOLD_prompt_color='${BOLD_white}' # set normal prompt BOLD color - eval user='${user_color}%n' - fi - - # ————————————————————————————————————————————————————————————————————— - # Check if we are on SSH or not to set host_color - # TODO better Zsh way to determine SSH2_CLIENT? - # ————————————————————————————————————————————————————————————————————— - if [[ -n "$SSH_CLIENT" || -n "$SSH2_CLIENT" ]]; then # SSH - eval host_color='${yellow}' - else # no SSH - eval host_color='${green}' + eval color_user=${1:-'${green}'} + eval color_host=${1:-'${green}'} + eval color_prompt=${1:-'${white}'} + # eval color_prompt_BOLD=${1:-'${white}'} + eval user='' + # eval user='${color_user}%n' fi # ————————————————————————————————————————————————————————————————————— - # Set hostname display - # ————————————————————————————————————————————————————————————————————— - eval host='${host_color}%m' # hostname up to first . (dot) - #eval host='${host_color}%M' # full hostname - - # ————————————————————————————————————————————————————————————————————— - # Determine number of background jobs - # TODO doesn't work like the rest of my "easy variables" - # - must instead insert code directly into PROMPT + # Report hostname # ————————————————————————————————————————————————————————————————————— -# eval number_jobs=' ${prompt_color}%(1j.J:${cyan}%j${no_color}.)' + eval host='${color_host}%m' # hostname up to first . (dot) + # eval host='${color_host}%M' # full hostname - # ————————————————————————————————————————————————————————————————————— # Report hostname - # ————————————————————————————————————————————————————————————————————— eval location='${user}${cyan}@${host}' # hostname with user - #eval location='${cyan}@${host}' # hostname without user - - # ————————————————————————————————————————————————————————————————————— - # Report present working directory - # TODO truncated dir doesn't work like the rest of my "easy variables" - # - must instead insert code directly into PROMPT - # ————————————————————————————————————————————————————————————————————— -# eval current_dir='${blue}%~' # Full directory -# eval current_dir='${blue}${_prompt_garrett_pwd}' # Truncated directory # ————————————————————————————————————————————————————————————————————— # Report return code @@ -255,40 +313,37 @@ function prompt_garrett_setup { # Report local time # ————————————————————————————————————————————————————————————————————— eval current_time='${green}%T' # 24 hour time format -# eval current_time='${green}%t' # AM/PM time format + # eval current_time='${green}%t' # AM/PM time format # ————————————————————————————————————————————————————————————————————— # Report terminal line number # ————————————————————————————————————————————————————————————————————— - eval line_number='${magenta}%!' - + eval line_number='${green}+${magenta}%!' + # ————————————————————————————————————————————————————————————————————— - # Report git prompt info (in order in which it will appear in the prompt) + # Report git info # ————————————————————————————————————————————————————————————————————— - zstyle ':prezto:module:git:info:branch' format "${cyan}λ ${green}%b" - zstyle ':prezto:module:git:info:remote' format "%R" + # zstyle ':prezto:module:git:info' verbose 'yes' - zstyle ':prezto:module:git:info:action' format "${yellow}%s" - zstyle ':prezto:module:git:info:position' format "${red}%p" + # Git prompt info (in order in which it will appear in the prompt) + zstyle ':prezto:module:git:info:branch' format "${cyan} λ ${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 (in order in which it will appear in the prompt) - # ————————————————————————————————————————————————————————————————————— - zstyle ':prezto:module:git:info:commit' format "${prompt_color}➤ ${yellow}%.7c" + zstyle ':prezto:module:git:info:commit' format "${color_prompt} ➤ ${yellow}%.7c" # Git remote status (in order in which it will appear in the prompt) - # ————————————————————————————————————————————————————————————————————— - zstyle ':prezto:module:git:info:behind' format "${BOLD_magenta}%A⤥" - #zstyle ':prezto:module:git:info:behind' format "${BOLD_magenta}⬇" - zstyle ':prezto:module:git:info:ahead' format "${BOLD_magenta}%B⤤" - #zstyle ':prezto:module:git:info:ahead' format "${BOLD_magenta}⬆" - zstyle ':prezto:module:git:info:diverged' format "${BOLD_magenta}⥮" - zstyle ':prezto:module:git:info:stashed' format "${cyan} %S✭" - + 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 (in order in which it will appear in the prompt) - # ————————————————————————————————————————————————————————————————————— zstyle ':prezto:module:git:info:clean' format "" - zstyle ':prezto:module:git:info:dirty' format "${yellow}⚡${prompt_color} |" + zstyle ':prezto:module:git:info:dirty' format "${yellow} ⚡${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} ✱" @@ -297,93 +352,57 @@ function prompt_garrett_setup { 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" \ + '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 "${white}%v" # %v - ruby version - zstyle ':prezto:module:ruby:info:version' format "version:%v " + zstyle ':prezto:module:ruby:info:version' format "${white}ruby-%v " - # ————————————————————————————————————————————————————————————————————— # Vim mode indicator - # TODO not sure how to just use alternate... # ————————————————————————————————————————————————————————————————————— - local vi_mode_prompt_info="${${KEYMAP/vicmd/${BOLD_red}❮${red}❮❮}/(main|viins)/} " - eval MODE_INDICATOR='${BOLD_red}❮${red}❮❮' - - zstyle ':prezto:module:editor:info:keymap:primary' format "${no_color}❯${grey}❯${BOLD_red}❯ " - #zstyle ':prezto:module:editor:info:keymap:primary:insert' format "I" + zstyle ':prezto:module:editor:info:keymap:primary' format "${red}❯${color_prompt}❯❯ " + zstyle ':prezto:module:editor:info:keymap:alternate' format "${red}❮${color_prompt}❮❮ " + # 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:keymap:alternate' format "${BOLD_red}❮${grey}❮${no_color}❮ " - zstyle ':prezto:module:editor:info:completing' format "${BOLD_red}..." - - # ————————————————————————————————————————————————————————————————————— - # Scary Root Prompt (for default root prompt, i.e., usually bash) - # - different from zsh root prompt - # ————————————————————————————————————————————————————————————————————— - export SUDO_PS1="\[\e[31;1;46m\][\u] \w \$\[\e[0m\] " + zstyle ':prezto:module:editor:info:completing' format "${red}..." # ————————————————————————————————————————————————————————————————————— # Finally! the PROMPT... # - add %E to beginning of PROMPT to clear screen after every command -# TODO prompt works but code is not ideal (clean) -# ————————————————————————————————————————————————————————————————————— - -# PROMPT on left -# ————————————————————————————————————————————————————————————————————— -#PROMPT=' -# TODO: how I'd like it to look... -#${prompt_color}╭─( ${current_dir} ${prompt_color}) ${git_info[remote_status]} ${git_info[prompt_info]} ${git_info[local_status]} -#${prompt_color}⎪ ${line_number}${number_jobs}${git_info[sha]} -#${prompt_color}╰─❮ ${current_time}${prompt_color} ❯${editor_info[keymap]}${no_color}' -# TODO: for testing the problems I have... -#PROMPT=' -#current dir: -#test ${current_dir} -#code ${blue}${_prompt_garrett_pwd} ${prompt_color} -# -#number jobs: -#test ${number_jobs} -#code ${prompt_color}%(1j.J:${cyan}%j${no_color}.) -# -#vi mode: -#test ${vi_mode_prompt_info} -#test ${editor_info[alternate]} -#test ${editor_info[overwrite]} -#code ${editor_info[keymap]} -#code ${${KEYMAP/vicmd/${BOLD_red}❮${red}❮❮}/(main|viins)/} -# -#ruby version: -#test ${ruby_info[version]} -#code %v -#' -# TODO: how it must look to work... -PROMPT=' -${prompt_color}╭─( ${blue}${_prompt_garrett_pwd} ${prompt_color}) ${git_info[remote_status]} ${git_info[prompt_info]} ${git_info[local_status]} -${prompt_color}⎪ ${line_number} ${prompt_color}%(1j.J:${cyan}%j${no_color}.)${git_info[sha]} -${prompt_color}╰─❮ ${current_time}${prompt_color} ❯${editor_info[keymap]}${no_color}' - - -# PROMPT on right # ————————————————————————————————————————————————————————————————————— -# TODO: how I'd like it to look... -#RPROMPT="${editor_info[alternate]}${ruby_info[version]}${editor_info[overwrite]}${return_code}${location} ${no_color}" -# TODO: how it must look to work... -RPROMPT='${${KEYMAP/vicmd/${BOLD_red}❮${red}❮❮}/(main|viins)/} ${ruby_info[version]}${editor_info[overwrite]}${return_code}${location} ${no_color}' + +# Left PROMPT +export PROMPT='${color_prompt}╰─${editor_info[keymap]}' + +# Right PROMPT +export RPROMPT='${editor_info[alternate]}${editor_info[overwrite]}${return_code}${number_jobs} ${ruby_info[version]}${location} ${line_number}${color_prompt} ─┘' + +# Continuation PROMPT +export PROMPT2='${color_prompt}%_ ${editor_info[keymap]}' + +# Selection PROMPT +export PROMPT3='${yellow}#? ' + +# Execution trace PROMPT +export PROMPT4='${blue}$0${color_prompt}@${yellow}$LINENO+ ' + +# Backup scary root prompt (for default root prompt, i.e., usually bash) +# NOTE: different from zsh root prompt +export SUDO_PS1="\[\e[31;1;46m\][\u] \w \$\[\e[0m\] " # Autocorrection PROMPT -# ————————————————————————————————————————————————————————————————————— -SPROMPT=" -Correct ${red}%R${no_color} to ${green}%r${no_color}? [nyae] " +export SPROMPT=' +${color_prompt}Correct ${red}%R${color_prompt} to ${green}%r${color_prompt} ? [nyae] ' } prompt_garrett_setup "$@" +