zsh: avoid global array of colors in prompt
This commit is contained in:
parent
a28fa3a3f8
commit
eff5a3d0b1
1 changed files with 86 additions and 59 deletions
|
@ -1,19 +1,6 @@
|
|||
typeset -gA zfg=(
|
||||
[reset]='%{%f%}'
|
||||
|
||||
[black]='%{%F{black}%}'
|
||||
[red]='%{%F{red}%}'
|
||||
[green]='%{%F{green}%}'
|
||||
[yellow]='%{%F{yellow}%}'
|
||||
[blue]='%{%F{blue}%}'
|
||||
[magenta]='%{%F{magenta}%}'
|
||||
[cyan]='%{%F{cyan}%}'
|
||||
[white]='%{%F{white}%}'
|
||||
|
||||
# %F{...} only supports the 8 basic colors by name
|
||||
[gray]='%{%F{8}%}'
|
||||
[bright]='%{%F{15}%}'
|
||||
[faded]='%{%F{240}%}'
|
||||
typeset -gA _fs_prompt=(
|
||||
[is_transient]=true
|
||||
[transient_color]='%{%F{magenta}%}'
|
||||
)
|
||||
|
||||
typeset -gA icons=(
|
||||
|
@ -28,69 +15,101 @@ typeset -gA icons=(
|
|||
)
|
||||
|
||||
fs_prompt_render_full() {
|
||||
local separator="${zfg[faded]} ❯ "
|
||||
local black='%{%F{0}%}' red='%{%F{1}%}' green='%{%F{2}%}' yellow='%{%F{3}%}' \
|
||||
blue='%{%F{4}%}' magenta='%{%F{5}%}' cyan='%{%F{6}%}' white='%{%F{7}%}' \
|
||||
gray='%{%F{8}%}' orange='%{%F{166}%}' faded='%{%F{240}%}' \
|
||||
reset='%{%f%}'
|
||||
|
||||
local sep_color="$faded" signal_color="$white" error_color="$red" reset="$reset"
|
||||
|
||||
local sections=(
|
||||
"$(fs_prompt_exit_code)"
|
||||
"$(fs_prompt_user_and_hostname)"
|
||||
"$(fs_prompt_pwd)"
|
||||
"$(fs_prompt_git)"
|
||||
"$(fs_prompt_virtualenv)"
|
||||
"$(fs_prompt_jobs)"
|
||||
"$(fs_prompt_exec_time)"
|
||||
"$(fs_prompt_exit_code $error_color $signal_color)"
|
||||
# root user separator
|
||||
"$(fs_prompt_user_and_hostname $red $yellow $faded)"
|
||||
"$(fs_prompt_pwd $cyan)"
|
||||
# branch ahead behind untracked staged dirty conflict separator
|
||||
"$(fs_prompt_git $blue $blue $cyan $white $green $orange $red $gray)"
|
||||
"$(fs_prompt_virtualenv $yellow)"
|
||||
"$(fs_prompt_jobs $magenta)"
|
||||
"$(fs_prompt_exec_time $gray)"
|
||||
)
|
||||
echo "\n${(@pj.$separator.)sections:#}${zfg[reset]}"
|
||||
local sep="$sep_color ❯ "
|
||||
echo "\n${(@pj:$sep:)sections:#}$reset"
|
||||
|
||||
if ((PROMPT_EXIT_CODE == 0)); then
|
||||
echo -n "${zfg[faded]}"
|
||||
echo -n "$sep_color"
|
||||
elif ((PROMPT_EXIT_CODE > 128 && PROMPT_EXIT_CODE < 160)); then
|
||||
echo -n "${zfg[white]}"
|
||||
echo -n "$signal_color"
|
||||
else
|
||||
echo -n "${zfg[red]}"
|
||||
echo -n "$error_color"
|
||||
fi
|
||||
(($SHLVL > 1)) && printf '%.0s' {2..$SHLVL}
|
||||
echo -n "❯ ${zfg[reset]}"
|
||||
echo -n "❯ $reset"
|
||||
}
|
||||
|
||||
fs_prompt_render_compact() {
|
||||
echo -n "${zfg[magenta]}❯ ${zfg[reset]}"
|
||||
echo -n "${_fs_prompt[transient_color]}❯ %{%f%}"
|
||||
}
|
||||
|
||||
fs_prompt_exit_code() {
|
||||
((PROMPT_EXIT_CODE == 0)) && return
|
||||
|
||||
local error_color="$1" signal_color="$2" bold="%{%B%}" no_bold="%{%b%}"
|
||||
|
||||
if ((PROMPT_EXIT_CODE > 128 && PROMPT_EXIT_CODE < 160)); then
|
||||
print "%{%B%}${zfg[white]}$(kill -l $PROMPT_EXIT_CODE)%{%b%}"
|
||||
print "${bold}${signal_color}$(kill -l $PROMPT_EXIT_CODE)${no_bold}"
|
||||
else
|
||||
print "%{%B%}${zfg[red]} $PROMPT_EXIT_CODE%{%b%}"
|
||||
print "${bold}${error_color} ${PROMPT_EXIT_CODE}${no_bold}"
|
||||
fi
|
||||
}
|
||||
|
||||
fs_prompt_user_and_hostname() {
|
||||
local root_color="$1" user_color="$2" at_color="${3:-$2}"
|
||||
local parts=()
|
||||
|
||||
# username in red if root, yellow if otherwise relevant
|
||||
if [[ $UID == 0 ]]; then
|
||||
parts+="${zfg[red]}${icons[user]}%n"
|
||||
parts+="${root_color}${icons[user]}%n"
|
||||
elif [[ $LOGNAME != $USER ]] || [[ -n $SSH_CONNECTION ]]; then
|
||||
parts+="${zfg[yellow]}${icons[user]}%n"
|
||||
parts+="${user_color}${icons[user]}%n"
|
||||
fi
|
||||
|
||||
# hostname in yellow if relevant
|
||||
[[ -n $SSH_CONNECTION ]] && parts+="${zfg[yellow]}%m"
|
||||
[[ -n $SSH_CONNECTION ]] && parts+="${user_color}%m"
|
||||
|
||||
(($#parts)) && {
|
||||
local separator="${zfg[gray]}@"
|
||||
print "${(pj:$separator:)parts}"
|
||||
local at="${at_color}@"
|
||||
print "${(pj:$at:)parts}"
|
||||
}
|
||||
}
|
||||
|
||||
fs_prompt_pwd() {
|
||||
print "${zfg[cyan]}${icons[folder]}%~"
|
||||
local color="$1"
|
||||
print "${color}${icons[folder]}%~"
|
||||
}
|
||||
|
||||
fs_prompt_git() {
|
||||
local branch_color="$1"
|
||||
local ahead_color="$2"
|
||||
local behind_color="$3"
|
||||
local untracked_color="$4"
|
||||
local staged_color="$5"
|
||||
local dirty_color="$6"
|
||||
local conflict_color="$7"
|
||||
local sep_color="$8"
|
||||
|
||||
local gitstatus # local swallows git's exit code if not on its own line
|
||||
gitstatus=$(command git status --porcelain -b 2>/dev/null) || return
|
||||
# gitstatus=$(command git status --porcelain -b 2>/dev/null) || return
|
||||
|
||||
gitstatus="## some-longer-name...origin/tracking [ahead 5, behind 12]
|
||||
M staged_1
|
||||
M staged_2
|
||||
M dirty_1
|
||||
M dirty_2
|
||||
M dirty_3
|
||||
DD conflict
|
||||
?? untracked
|
||||
"
|
||||
|
||||
# Sort through the status of files.
|
||||
local untracked=0 dirty=0 staged=0 conflicts=0 branch_line=''
|
||||
|
@ -150,42 +169,50 @@ fs_prompt_git() {
|
|||
fi
|
||||
}
|
||||
|
||||
local track_parts=()
|
||||
(($ahead > 0 )) && track_parts+="${zfg[blue]}↑${ahead}"
|
||||
(($behind > 0 )) && track_parts+="${zfg[cyan]}${behind}↓"
|
||||
local result=()
|
||||
{
|
||||
local sep="${sep_color}"
|
||||
local tracking=()
|
||||
(($ahead)) && tracking+="${ahead_color}${ahead}" # ↑
|
||||
(($behind)) && tracking+="${behind_color}${behind}" # ↓
|
||||
(($#tracking)) && result+="${(pj:$sep:)tracking} "
|
||||
|
||||
local state_parts=()
|
||||
(($staged > 0)) && state_parts+="${zfg[green]}+${staged}"
|
||||
(($dirty > 0 )) && state_parts+="${zfg[red]}${dirty}✶"
|
||||
(($conflicts)) && result+="${conflict_color} %{%B%}${conflicts}%{%b%}"
|
||||
|
||||
local separator="${zfg[gray]}"
|
||||
local gitinfo=("${zfg[blue]}${branch}")
|
||||
(($#track_parts > 0)) && gitinfo+="${(pj:$separator:)track_parts}"
|
||||
(($conflicts > 0 )) && gitinfo+="${zfg[red]}${conflicts} "
|
||||
(($untracked > 0 )) && gitinfo+="${zfg[white]}${untracked}?"
|
||||
(($#state_parts)) && gitinfo+="${(pj:$separator:)state_parts}"
|
||||
local state=()
|
||||
(($staged)) && state+="${staged_color}+${staged}"
|
||||
(($dirty)) && state+="${dirty_color}${dirty}✶"
|
||||
(($#state)) && result+="${(pj:$sep:)state}"
|
||||
|
||||
print "${(j: :)gitinfo}"
|
||||
(($untracked)) && result+="${untracked_color}${untracked}?"
|
||||
}
|
||||
print "${branch_color}${branch} ${(j: :)result}"
|
||||
}
|
||||
|
||||
fs_prompt_virtualenv() {
|
||||
[[ -n "$VIRTUAL_ENV" ]] && print "${zfg[green]}${icons[python]}${VIRTUAL_ENV:t}"
|
||||
[[ -n "$VIRTUAL_ENV" ]] || return
|
||||
local color="$1"
|
||||
print "${color}${icons[python]}${VIRTUAL_ENV:t}"
|
||||
}
|
||||
|
||||
fs_prompt_jobs() {
|
||||
(($PROMPT_JOB_COUNT > 0)) && print "${zfg[magenta]}${icons[background]}%j"
|
||||
(($PROMPT_JOB_COUNT)) || return
|
||||
local color="$1"
|
||||
print "${color}${icons[background]}%j"
|
||||
}
|
||||
|
||||
fs_prompt_exec_time() {
|
||||
(($PROMPT_EXEC_TIME <= 3)) && return # don't print time if under 3s
|
||||
|
||||
local color="$1"
|
||||
local parts=(
|
||||
"$((PROMPT_EXEC_TIME / 60 / 60 / 24))d" # days
|
||||
"$((PROMPT_EXEC_TIME / 60 / 60 % 24))h" # hours
|
||||
"$((PROMPT_EXEC_TIME / 60 % 60))m" # minutes
|
||||
"$((PROMPT_EXEC_TIME % 60))s" # seconds
|
||||
)
|
||||
print ${zfg[gray]}${icons[clock]}${parts:#0*} # only keep non-zero parts
|
||||
local exec_time="${(@)parts:#0*}" # only keep non-zero parts
|
||||
[[ -n "$exec_time" ]] && print "${color}${icons[clock]}${exec_time}"
|
||||
}
|
||||
|
||||
# Hook triggered when a command is about to be executed.
|
||||
|
@ -224,12 +251,12 @@ fs_setup_prompt() {
|
|||
add-zsh-hook preexec fs_prompt_preexec
|
||||
add-zsh-hook precmd fs_prompt_precmd
|
||||
|
||||
# Change to false to disable transient prompt.
|
||||
local use_transient_prompt=true
|
||||
if $use_transient_prompt; then
|
||||
if ${_fs_prompt[is_transient]}; then
|
||||
autoload -Uz add-zle-hook-widget
|
||||
add-zle-hook-widget line-finish fs_prompt_zle_line_finish
|
||||
PS2="${zfg[magenta]}%_❯${zfg[reset]} "
|
||||
PS2="${_fs_prompt[transient_color]}%_❯%{%f%} "
|
||||
else
|
||||
add-zle-hook-widget -d line-finish fs_prompt_zle_line_finish
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue