Refactor to avoid subshell usage, prefer variables
Performance tests indicate using a lot of subshells can lead to bad performance.
This commit is contained in:
116
pure.zsh
116
pure.zsh
@@ -26,25 +26,29 @@
|
|||||||
# turns seconds into human readable time
|
# turns seconds into human readable time
|
||||||
# 165392 => 1d 21h 56m 32s
|
# 165392 => 1d 21h 56m 32s
|
||||||
# https://github.com/sindresorhus/pretty-time-zsh
|
# https://github.com/sindresorhus/pretty-time-zsh
|
||||||
prompt_pure_human_time() {
|
prompt_pure_human_time_to_var() {
|
||||||
echo -n " "
|
local human=" " total_seconds=$1 var=$2
|
||||||
local tmp=$1
|
local days=$(( total_seconds / 60 / 60 / 24 ))
|
||||||
local days=$(( tmp / 60 / 60 / 24 ))
|
local hours=$(( total_seconds / 60 / 60 % 24 ))
|
||||||
local hours=$(( tmp / 60 / 60 % 24 ))
|
local minutes=$(( total_seconds / 60 % 60 ))
|
||||||
local minutes=$(( tmp / 60 % 60 ))
|
local seconds=$(( total_seconds % 60 ))
|
||||||
local seconds=$(( tmp % 60 ))
|
(( days > 0 )) && human+="${days}d "
|
||||||
(( $days > 0 )) && echo -n "${days}d "
|
(( hours > 0 )) && human+="${hours}h "
|
||||||
(( $hours > 0 )) && echo -n "${hours}h "
|
(( minutes > 0 )) && human+="${minutes}m "
|
||||||
(( $minutes > 0 )) && echo -n "${minutes}m "
|
human+="${seconds}s"
|
||||||
echo "${seconds}s"
|
|
||||||
|
# store human readable time in variable as specified by caller
|
||||||
|
typeset -g "${var}"="${human}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# displays the exec time of the last command if set threshold was exceeded
|
# stores (into prompt_pure_cmd_exec_time) the exec time of the last command if set threshold was exceeded
|
||||||
prompt_pure_check_cmd_exec_time() {
|
prompt_pure_check_cmd_exec_time() {
|
||||||
local stop=$EPOCHSECONDS
|
integer elapsed
|
||||||
local start=${prompt_pure_cmd_timestamp:-$stop}
|
(( elapsed = EPOCHSECONDS - ${prompt_pure_cmd_timestamp:-$EPOCHSECONDS} ))
|
||||||
integer elapsed=$stop-$start
|
prompt_pure_cmd_exec_time=
|
||||||
(($elapsed > ${PURE_CMD_MAX_EXEC_TIME:=5})) && prompt_pure_human_time $elapsed
|
(( elapsed > ${PURE_CMD_MAX_EXEC_TIME:=5} )) && {
|
||||||
|
prompt_pure_human_time_to_var $elapsed "prompt_pure_cmd_exec_time"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prompt_pure_clear_screen() {
|
prompt_pure_clear_screen() {
|
||||||
@@ -57,17 +61,26 @@ prompt_pure_clear_screen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prompt_pure_check_git_arrows() {
|
prompt_pure_check_git_arrows() {
|
||||||
|
# reset git arrows
|
||||||
|
prompt_pure_git_arrows=
|
||||||
|
|
||||||
# check if there is an upstream configured for this branch
|
# check if there is an upstream configured for this branch
|
||||||
command git rev-parse --abbrev-ref @'{u}' &>/dev/null || return
|
command git rev-parse --abbrev-ref @'{u}' &>/dev/null || return
|
||||||
|
|
||||||
local right left arrows
|
local arrow_status
|
||||||
right=$(command git rev-list --right-only --count HEAD...@'{u}' 2>/dev/null)
|
# check git left and right arrow_status
|
||||||
left=$(command git rev-list --left-only --count HEAD...@'{u}' 2>/dev/null)
|
arrow_status="$(command git rev-list --left-right --count HEAD...@'{u}' 2>/dev/null)"
|
||||||
|
# exit if the command failed
|
||||||
|
(( !$? )) || return
|
||||||
|
|
||||||
(( ${right:-0} > 0 )) && arrows="${PURE_GIT_DOWN_ARROW:-⇣}"
|
# left and right are tab-separated, split on tab and store as array
|
||||||
|
arrow_status=(${(ps:\t:)arrow_status})
|
||||||
|
local arrows left=${arrow_status[1]} right=${arrow_status[2]}
|
||||||
|
|
||||||
|
(( ${right:-0} > 0 )) && arrows+="${PURE_GIT_DOWN_ARROW:-⇣}"
|
||||||
(( ${left:-0} > 0 )) && arrows+="${PURE_GIT_UP_ARROW:-⇡}"
|
(( ${left:-0} > 0 )) && arrows+="${PURE_GIT_UP_ARROW:-⇡}"
|
||||||
# output the arrows
|
|
||||||
[[ $arrows != "" ]] && echo " ${arrows}"
|
[[ -n $arrows ]] && prompt_pure_git_arrows=" ${arrows}"
|
||||||
}
|
}
|
||||||
|
|
||||||
prompt_pure_preexec() {
|
prompt_pure_preexec() {
|
||||||
@@ -84,8 +97,13 @@ prompt_pure_preexec() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# string length ignoring ansi escapes
|
# string length ignoring ansi escapes
|
||||||
prompt_pure_string_length() {
|
prompt_pure_string_length_to_var() {
|
||||||
echo $(( ${#${(S%%)1//(\%([KF1]|)\{*\}|\%[Bbkf])}} ))
|
local str=$1 var=$2 length
|
||||||
|
# perform expansion on str and check length
|
||||||
|
length=$(( ${#${(S%%)str//(\%([KF1]|)\{*\}|\%[Bbkf])}} ))
|
||||||
|
|
||||||
|
# store string length in variable as specified by caller
|
||||||
|
typeset -g "${var}"="${length}"
|
||||||
}
|
}
|
||||||
|
|
||||||
prompt_pure_preprompt_render() {
|
prompt_pure_preprompt_render() {
|
||||||
@@ -114,13 +132,16 @@ prompt_pure_preprompt_render() {
|
|||||||
# only redraw if preprompt has changed
|
# only redraw if preprompt has changed
|
||||||
[[ "${prompt_pure_last_preprompt}" != "${preprompt}" ]] || return
|
[[ "${prompt_pure_last_preprompt}" != "${preprompt}" ]] || return
|
||||||
|
|
||||||
# calculate length of preprompt for redraw purposes
|
# calculate length of preprompt and store it locally in preprompt_length
|
||||||
local preprompt_length=$(prompt_pure_string_length $preprompt)
|
integer preprompt_length
|
||||||
local lines=$(( ($preprompt_length - 1) / $COLUMNS + 1 ))
|
prompt_pure_string_length_to_var "${preprompt}" "preprompt_length"
|
||||||
|
|
||||||
|
# calculate number of preprompt lines for redraw purposes
|
||||||
|
integer lines=$(( (preprompt_length - 1) / COLUMNS + 1 ))
|
||||||
|
|
||||||
# disable clearing of line if last char of preprompt is last column of terminal
|
# disable clearing of line if last char of preprompt is last column of terminal
|
||||||
local clr="\e[K"
|
local clr='\e[K'
|
||||||
(( $COLUMNS * $lines == $preprompt_length )) && clr=""
|
(( COLUMNS * lines == preprompt_length )) && clr=
|
||||||
|
|
||||||
# modify previous preprompt
|
# modify previous preprompt
|
||||||
print -Pn "\e7\e[${lines}A\e[1G${preprompt}${clr}\e8"
|
print -Pn "\e7\e[${lines}A\e[1G${preprompt}${clr}\e8"
|
||||||
@@ -131,15 +152,15 @@ prompt_pure_preprompt_render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prompt_pure_precmd() {
|
prompt_pure_precmd() {
|
||||||
# store exec time for when preprompt gets re-rendered
|
# check exec time and store it in a variable
|
||||||
prompt_pure_cmd_exec_time=$(prompt_pure_check_cmd_exec_time)
|
prompt_pure_check_cmd_exec_time
|
||||||
|
|
||||||
# by making sure that prompt_pure_cmd_timestamp is defined here the async functions are prevented from interfering
|
# by making sure that prompt_pure_cmd_timestamp is defined here the async functions are prevented from interfering
|
||||||
# with the initial preprompt rendering
|
# with the initial preprompt rendering
|
||||||
prompt_pure_cmd_timestamp=
|
prompt_pure_cmd_timestamp=
|
||||||
|
|
||||||
# check for git arrows
|
# check for git arrows
|
||||||
prompt_pure_git_arrows=$(prompt_pure_check_git_arrows)
|
prompt_pure_check_git_arrows
|
||||||
|
|
||||||
# tell the terminal we are setting the title
|
# tell the terminal we are setting the title
|
||||||
print -Pn "\e]0;"
|
print -Pn "\e]0;"
|
||||||
@@ -193,11 +214,11 @@ prompt_pure_async_tasks() {
|
|||||||
prompt_pure_async_init=1
|
prompt_pure_async_init=1
|
||||||
}
|
}
|
||||||
|
|
||||||
# get the current git working tree, empty if not inside a git directory
|
# store working_tree without the "x" prefix
|
||||||
local working_tree="$(command git rev-parse --show-toplevel 2>/dev/null)"
|
local working_tree="${vcs_info_msg_1_#x}"
|
||||||
|
|
||||||
# check if the working tree changed (prompt_pure_current_working_tree is prefixed by "x")
|
# check if the working tree changed (prompt_pure_current_working_tree is prefixed by "x")
|
||||||
if [[ "${prompt_pure_current_working_tree:-x}" != "x${working_tree}" ]]; then
|
if [[ ${prompt_pure_current_working_tree#x} != $working_tree ]]; then
|
||||||
# stop any running async jobs
|
# stop any running async jobs
|
||||||
async_flush_jobs "prompt_pure"
|
async_flush_jobs "prompt_pure"
|
||||||
|
|
||||||
@@ -210,21 +231,20 @@ prompt_pure_async_tasks() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# only perform tasks inside git working tree
|
# only perform tasks inside git working tree
|
||||||
[[ "${working_tree}" != "" ]] || return
|
[[ -n $working_tree ]] || return
|
||||||
|
|
||||||
if (( ${PURE_GIT_PULL:-1} )); then
|
# do not preform git fetch if it is disabled or working_tree == HOME
|
||||||
# make sure working tree is not $HOME
|
if (( ${PURE_GIT_PULL:-1} )) && [[ $working_tree != $HOME ]]; then
|
||||||
[[ "${working_tree}" != "$HOME" ]] &&
|
|
||||||
# tell worker to do a git fetch
|
# tell worker to do a git fetch
|
||||||
async_job "prompt_pure" prompt_pure_async_git_fetch "$working_tree"
|
async_job "prompt_pure" prompt_pure_async_git_fetch "${working_tree}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# if dirty checking is sufficiently fast, tell worker to check it again, or wait for timeout
|
# if dirty checking is sufficiently fast, tell worker to check it again, or wait for timeout
|
||||||
local time_since_last_dirty_check=$(( $EPOCHSECONDS - ${prompt_pure_git_last_dirty_check_timestamp:-0} ))
|
integer time_since_last_dirty_check=$(( EPOCHSECONDS - ${prompt_pure_git_last_dirty_check_timestamp:-0} ))
|
||||||
if (( $time_since_last_dirty_check > ${PURE_GIT_DELAY_DIRTY_CHECK:-1800} )); then
|
if (( time_since_last_dirty_check > ${PURE_GIT_DELAY_DIRTY_CHECK:-1800} )); then
|
||||||
unset prompt_pure_git_last_dirty_check_timestamp
|
unset prompt_pure_git_last_dirty_check_timestamp
|
||||||
# check check if there is anything to pull
|
# check check if there is anything to pull
|
||||||
async_job "prompt_pure" prompt_pure_async_git_dirty "${PURE_GIT_UNTRACKED_DIRTY:-1}" "$working_tree"
|
async_job "prompt_pure" prompt_pure_async_git_dirty "${PURE_GIT_UNTRACKED_DIRTY:-1}" "${working_tree}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +264,7 @@ prompt_pure_async_callback() {
|
|||||||
(( $exec_time > 2 )) && prompt_pure_git_last_dirty_check_timestamp=$EPOCHSECONDS
|
(( $exec_time > 2 )) && prompt_pure_git_last_dirty_check_timestamp=$EPOCHSECONDS
|
||||||
;;
|
;;
|
||||||
prompt_pure_async_git_fetch)
|
prompt_pure_async_git_fetch)
|
||||||
prompt_pure_git_arrows=$(prompt_pure_check_git_arrows)
|
prompt_pure_check_git_arrows
|
||||||
prompt_pure_preprompt_render
|
prompt_pure_preprompt_render
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -268,8 +288,12 @@ prompt_pure_setup() {
|
|||||||
|
|
||||||
zstyle ':vcs_info:*' enable git
|
zstyle ':vcs_info:*' enable git
|
||||||
zstyle ':vcs_info:*' use-simple true
|
zstyle ':vcs_info:*' use-simple true
|
||||||
zstyle ':vcs_info:git*' formats ' %b'
|
# only export two msg variables from vcs_info
|
||||||
zstyle ':vcs_info:git*' actionformats ' %b|%a'
|
zstyle ':vcs_info:*' max-exports 2
|
||||||
|
# vcs_info_msg_0_ = ' %b' (for branch)
|
||||||
|
# vcs_info_msg_1_ = 'x%R' git top level (%R), x-prefix prevents creation of a named path (AUTO_NAME_DIRS)
|
||||||
|
zstyle ':vcs_info:git*' formats ' %b' 'x%R'
|
||||||
|
zstyle ':vcs_info:git*' actionformats ' %b|%a' 'x%R'
|
||||||
|
|
||||||
# if the user has not registered a custom zle widget for clear-screen,
|
# if the user has not registered a custom zle widget for clear-screen,
|
||||||
# override the builtin one so that the preprompt is displayed correctly when
|
# override the builtin one so that the preprompt is displayed correctly when
|
||||||
|
|||||||
Reference in New Issue
Block a user