From fbcda4d5a92e023388259652652d154558e49ef3 Mon Sep 17 00:00:00 2001 From: Andrew Baumann <0xabu@users.noreply.github.com> Date: Thu, 17 May 2018 05:46:27 -0700 Subject: [PATCH] agnoster: cut down on fork/execs improve performance when not in a repo (#6210) * agnoster: improve perf with use of $jobstates (zsh/parameter module) This saves multiple fork/execs (for the subshell and wc) each time the prompt is rendered * agnoster: compute git repo_path only when in a git repo this avoids needlessly invoking git twice every time we render the prompt * agnoster: avoid subshell when rendering prompt Rather than forking a subshell to print the prompt, construct it incrementally by appending to $PROMPT. v2: fix incorrect CURRENT_BG v3: fix bzr and hg prompting Thanks @mcornella for the help. --- themes/agnoster.zsh-theme | 46 +++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) mode change 100644 => 100755 themes/agnoster.zsh-theme diff --git a/themes/agnoster.zsh-theme b/themes/agnoster.zsh-theme old mode 100644 new mode 100755 index 07546fd34..292551f44 --- a/themes/agnoster.zsh-theme +++ b/themes/agnoster.zsh-theme @@ -29,6 +29,7 @@ # A few utility functions to make it easy and re-usable to draw segmented prompts CURRENT_BG='NONE' +zmodload zsh/parameter # Special Powerline characters @@ -55,23 +56,23 @@ prompt_segment() { [[ -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%{$fg%} " + PROMPT+=" %{$bg%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR%{$fg%} " else - echo -n "%{$bg%}%{$fg%} " + PROMPT+="%{$bg%}%{$fg%} " fi CURRENT_BG=$1 - [[ -n $3 ]] && echo -n $3 + [[ -n $3 ]] && PROMPT+=$3 } # End the prompt, closing any open segments prompt_end() { if [[ -n $CURRENT_BG ]]; then - echo -n " %{%k%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR" + PROMPT+=" %{%k%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR" else - echo -n "%{%k%}" + PROMPT+="%{%k%}" fi - echo -n "%{%f%}" - CURRENT_BG='' + PROMPT+="%{%f%}" + CURRENT_BG='NONE' } ### Prompt components @@ -93,9 +94,9 @@ prompt_git() { PL_BRANCH_CHAR=$'\ue0a0' #  } local ref dirty mode repo_path - repo_path=$(git rev-parse --git-dir 2>/dev/null) if $(git rev-parse --is-inside-work-tree >/dev/null 2>&1); then + repo_path=$(git rev-parse --git-dir 2>/dev/null) dirty=$(parse_git_dirty) ref=$(git symbolic-ref HEAD 2> /dev/null) || ref="➦ $(git rev-parse --short HEAD 2> /dev/null)" if [[ -n $dirty ]]; then @@ -123,7 +124,7 @@ prompt_git() { zstyle ':vcs_info:*' formats ' %u%c' zstyle ':vcs_info:*' actionformats ' %u%c' vcs_info - echo -n "${ref/refs\/heads\//$PL_BRANCH_CHAR }${vcs_info_msg_0_%% }${mode}" + PROMPT+="${ref/refs\/heads\//$PL_BRANCH_CHAR }${vcs_info_msg_0_%% }${mode}" fi } @@ -135,15 +136,15 @@ prompt_bzr() { revision=`bzr log | head -n2 | tail -n1 | sed 's/^revno: //'` if [[ $status_mod -gt 0 ]] ; then prompt_segment yellow black - echo -n "bzr@"$revision "✚ " + PROMPT+="bzr@$revision ✚ " else if [[ $status_all -gt 0 ]] ; then prompt_segment yellow black - echo -n "bzr@"$revision + PROMPT+="bzr@$revision" else prompt_segment green black - echo -n "bzr@"$revision + PROMPT+="bzr@$revision" fi fi fi @@ -151,36 +152,36 @@ prompt_bzr() { prompt_hg() { (( $+commands[hg] )) || return - local rev status + local rev st branch if $(hg id >/dev/null 2>&1); then if $(hg prompt >/dev/null 2>&1); then if [[ $(hg prompt "{status|unknown}") = "?" ]]; then # if files are not added prompt_segment red white - st='±' + st=' ±' elif [[ -n $(hg prompt "{status|modified}") ]]; then # if any modification prompt_segment yellow black - st='±' + st=' ±' else # if working copy is clean prompt_segment green black fi - echo -n $(hg prompt "☿ {rev}@{branch}") $st + PROMPT+="$(hg prompt "☿ {rev}@{branch}")$st" else st="" rev=$(hg id -n 2>/dev/null | sed 's/[^-0-9]//g') branch=$(hg id -b 2>/dev/null) if `hg st | grep -q "^\?"`; then prompt_segment red black - st='±' + st=' ±' elif `hg st | grep -q "^[MA]"`; then prompt_segment yellow black - st='±' + st=' ±' else prompt_segment green black fi - echo -n "☿ $rev@$branch" $st + PROMPT+="☿ $rev@$branch$st" fi fi } @@ -207,7 +208,7 @@ prompt_status() { symbols=() [[ $RETVAL -ne 0 ]] && symbols+="%{%F{red}%}✘" [[ $UID -eq 0 ]] && symbols+="%{%F{yellow}%}⚡" - [[ $(jobs -l | wc -l) -gt 0 ]] && symbols+="%{%F{cyan}%}⚙" + [[ ${#jobstates} -ne 0 ]] && symbols+="%{%F{cyan}%}⚙" [[ -n "$symbols" ]] && prompt_segment black default "$symbols" } @@ -215,6 +216,7 @@ prompt_status() { ## Main prompt build_prompt() { RETVAL=$? + PROMPT='%{%f%b%k%}' prompt_status prompt_virtualenv prompt_context @@ -223,6 +225,8 @@ build_prompt() { prompt_bzr prompt_hg prompt_end + PROMPT+=' ' } -PROMPT='%{%f%b%k%}$(build_prompt) ' +autoload -U add-zsh-hook +add-zsh-hook precmd build_prompt