From 4b779b8336458ef0deec53dbb40ec1cd382adcfd Mon Sep 17 00:00:00 2001 From: Fernando Schauenburg Date: Mon, 29 Jul 2024 20:27:06 +0200 Subject: [PATCH] zsh: avoid global array of icons in prompt --- config/zsh/prompt.zsh | 109 ++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 62 deletions(-) diff --git a/config/zsh/prompt.zsh b/config/zsh/prompt.zsh index c6d8df3..acea45e 100644 --- a/config/zsh/prompt.zsh +++ b/config/zsh/prompt.zsh @@ -1,18 +1,4 @@ -typeset -gA _fs_prompt=( - [is_transient]=true - [transient_color]='%{%F{magenta}%}' -) - -typeset -gA icons=( - [user]=" " - [folder]=" " - [branch]=" " - [tag]="⚑ " - [detached]=" " - [python]=" " - [background]=" " - [clock]=" " -) +typeset -gA _fs_prompt=([is_transient]=true [transient_color]='%{%F{magenta}%}') fs_prompt_render_full() { local black='%{%F{0}%}' red='%{%F{1}%}' green='%{%F{2}%}' yellow='%{%F{3}%}' \ @@ -20,22 +6,28 @@ fs_prompt_render_full() { gray='%{%F{8}%}' orange='%{%F{166}%}' faded='%{%F{240}%}' \ reset='%{%f%}' - local sep_color="$faded" signal_color="$white" error_color="$red" reset="$reset" + local sep_color="$faded" signal_color="$gray" error_color="$red" reset="$reset" + # + # First line + # local sections=( - "$(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)" + "$(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)" ) local sep="$sep_color ❯ " echo "\n${(@pj:$sep:)sections:#}$reset" + # + # Second line + # if ((PROMPT_EXIT_CODE == 0)); then echo -n "$sep_color" elif ((PROMPT_EXIT_CODE > 128 && PROMPT_EXIT_CODE < 160)); then @@ -47,6 +39,7 @@ fs_prompt_render_full() { echo -n "❯ $reset" } +# This is only used if transient prompt is enabled. fs_prompt_render_compact() { echo -n "${_fs_prompt[transient_color]}❯ %{%f%}" } @@ -54,24 +47,25 @@ fs_prompt_render_compact() { fs_prompt_exit_code() { ((PROMPT_EXIT_CODE == 0)) && return - local error_color="$1" signal_color="$2" bold="%{%B%}" no_bold="%{%b%}" + local error_icon="$1" signal_icon="$2" error_color="$3" signal_color="$4" if ((PROMPT_EXIT_CODE > 128 && PROMPT_EXIT_CODE < 160)); then - print "${bold}${signal_color}$(kill -l $PROMPT_EXIT_CODE)${no_bold}" + print "${signal_color}${signal_icon} $(kill -l $PROMPT_EXIT_CODE)" else - print "${bold}${error_color} ${PROMPT_EXIT_CODE}${no_bold}" + print "%{%B%}${error_color}${error_icon} ${PROMPT_EXIT_CODE}%{%b%}" fi } fs_prompt_user_and_hostname() { - local root_color="$1" user_color="$2" at_color="${3:-$2}" + local icon="$1" root_color="$2" user_color="$3" at_color="${4:-$3}" local parts=() # username in red if root, yellow if otherwise relevant + local user_name="${icon} %n" if [[ $UID == 0 ]]; then - parts+="${root_color}${icons[user]}%n" + parts+="${root_color}${user_name}" elif [[ $LOGNAME != $USER ]] || [[ -n $SSH_CONNECTION ]]; then - parts+="${user_color}${icons[user]}%n" + parts+="${user_color}${user_name}" fi # hostname in yellow if relevant @@ -84,32 +78,23 @@ fs_prompt_user_and_hostname() { } fs_prompt_pwd() { - local color="$1" - print "${color}${icons[folder]}%~" + local icon="$1" color="$2" + print "${color}${icon} %~" } 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" + typeset -A icons=([branch]="$1" [tag]="$2" [detached]="$3") + local branch_color="$4" + local ahead_color="$5" + local behind_color="$6" + local untracked_color="$7" + local staged_color="$8" + local dirty_color="$9" + local conflict_color="$10" + local sep_color="$11" 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="## 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 -" + gitstatus=$(command git status --porcelain -b 2>/dev/null) || return # Sort through the status of files. local untracked=0 dirty=0 staged=0 conflicts=0 branch_line='' @@ -131,14 +116,14 @@ DD conflict local branch='' upstream='' ahead=0 behind=0 { local fields=(${(s:...:)${branch_line#\#\# }}) - branch="${icons[branch]}$fields[1]" + branch="${icons[branch]} $fields[1]" local tracking=$fields[2] if [[ $branch == *'Initial commit'* ]] || [[ $branch == *'No commits'* ]]; then # Branch name is last word in these possible branch lines: # ## Initial commit on # ## No commits yet on - branch="${icons[branch]}${${(s: :)branch}[-1]}" + branch="${icons[branch]} ${${(s: :)branch}[-1]}" elif [[ $branch == *'no branch'* ]]; then # Dettached HEAD (also if a tag is checked out), branch line: @@ -150,7 +135,7 @@ DD conflict ref=$(command git describe --tags --long HEAD 2>/dev/null) [[ -n $ref ]] || ref=$(command git rev-parse --short HEAD 2>/dev/null) fi - branch="${icon}%{%B%}${ref}%{%b%}" + branch="${icon} %{%B%}${ref}%{%b%}" elif (($#fields > 1)); then # There is a tracking branch. Possibilites: @@ -175,7 +160,7 @@ DD conflict local tracking=() (($ahead)) && tracking+="${ahead_color}${ahead}" # ↑ (($behind)) && tracking+="${behind_color}${behind}" # ↓ - (($#tracking)) && result+="${(pj:$sep:)tracking} " + (($#tracking)) && result+="${(pj:$sep:)tracking}" (($conflicts)) && result+="${conflict_color} %{%B%}${conflicts}%{%b%}" @@ -191,20 +176,20 @@ DD conflict fs_prompt_virtualenv() { [[ -n "$VIRTUAL_ENV" ]] || return - local color="$1" - print "${color}${icons[python]}${VIRTUAL_ENV:t}" + local icon="$1" color="$2" + print "${color}${icon} ${VIRTUAL_ENV:t}" } fs_prompt_jobs() { (($PROMPT_JOB_COUNT)) || return - local color="$1" - print "${color}${icons[background]}%j" + local icon="$1" color="$2" + print "${color}${icon} %j" } fs_prompt_exec_time() { (($PROMPT_EXEC_TIME <= 3)) && return # don't print time if under 3s - local color="$1" + local icon="$1" color="$2" local parts=( "$((PROMPT_EXEC_TIME / 60 / 60 / 24))d" # days "$((PROMPT_EXEC_TIME / 60 / 60 % 24))h" # hours @@ -212,7 +197,7 @@ fs_prompt_exec_time() { "$((PROMPT_EXEC_TIME % 60))s" # seconds ) local exec_time="${(@)parts:#0*}" # only keep non-zero parts - [[ -n "$exec_time" ]] && print "${color}${icons[clock]}${exec_time}" + [[ -n "$exec_time" ]] && print "${color}${icon} ${exec_time}" } # Hook triggered when a command is about to be executed.