Skip to content

Commit

Permalink
Migrate sorin prompt to zsh-async
Browse files Browse the repository at this point in the history
  • Loading branch information
belak committed Jul 18, 2017
1 parent f236344 commit b6e01cc
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 46 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@
[submodule "modules/fasd/external"]
path = modules/fasd/external
url = https://github.com/clvv/fasd
[submodule "modules/prompt/external/async"]
path = modules/prompt/external/async
url = https://github.com/mafredri/zsh-async
1 change: 1 addition & 0 deletions modules/prompt/external/async
Submodule async added at 28c7a6
2 changes: 1 addition & 1 deletion modules/prompt/functions/async
92 changes: 47 additions & 45 deletions modules/prompt/functions/prompt_sorin_setup
Original file line number Diff line number Diff line change
Expand Up @@ -32,49 +32,41 @@
# Load dependencies.
pmodload 'helper'

prompt_sorin_git_info() {
if (( _prompt_sorin_precmd_async_pid > 0 )); then
# Append Git status.
if [[ -s "$_prompt_sorin_precmd_async_data" ]]; then
alias typeset='typeset -g'
source "$_prompt_sorin_precmd_async_data"
RPROMPT+='${git_info:+${(e)git_info[status]}}'
unalias typeset
function prompt_sorin_git_info {
local _git_target
local _git_post_target

# We split on : because it's a character which isn't allowed in ref names.
IFS=':' read _git_target _git_post_target <<<"$3"

# The target actually contains 3 space separated possibilities, so we need to
# make sure we grab the first one.
_git_target=${(z)_git_target}
_git_target=$(coalesce ${_git_target[@]})

# If what we're looking at is empty, we clear out the git portion of the
# prompt and return early.
if [[ -z "$_git_target" ]]; then
if [[ -n "$_prompt_sorin_git" ]]; then
_prompt_sorin_git=''
zle && zle reset-prompt
fi

# Reset PID.
_prompt_sorin_precmd_async_pid=0

# Redisplay prompt.
zle && zle reset-prompt
return
fi

_prompt_sorin_git="${_git_target}${_git_post_target}"

# Redisplay prompt.
zle && zle reset-prompt
}

function prompt_sorin_precmd_async {
# Get Git repository information.
function prompt_sorin_async_git {
cd -q "$1"
if (( $+functions[git-info] )); then
git-info
### TODO XXX
# This section exists to patch over vulnerabilities when sourcing the
# file in $_prompt_sorin_precmd_async_data. Without it if a branch is named
# $foo it will expand if we have a $foo variable, and a branch named
# $(IFS=_;cmd=rm_-rf_~;$cmd) could delete the users home directory.
# This is a stopgap to prevent code execution and fix the vulnerability,
# but it eventually needs to be removed in favor of zsh_async and not using
# a file to store the prompt data in.
###
local tmp_prompt_var=$(typeset -p git_info)
# Replace all $ with $\ to escape
tmp_prompt_var=${tmp_prompt_var//\$/\\$}
# Unescape the first \$ as it's our $( )
tmp_prompt_var=${tmp_prompt_var:s/\\$/\$}
# Escape all backticks ` to \`
tmp_prompt_var=${tmp_prompt_var//\`/\\\`}
printf "%s\n" "$tmp_prompt_var" >! "$_prompt_sorin_precmd_async_data"
echo ${git_info[status]}
fi

# Signal completion to parent process.
kill -WINCH $$
}

function prompt_sorin_precmd {
Expand All @@ -84,18 +76,19 @@ function prompt_sorin_precmd {
# Format PWD.
_prompt_sorin_pwd=$(promptpwd)

# Define prompts.
RPROMPT='${editor_info[overwrite]}%(?:: %F{1}⏎%f)${VIM:+" %B%F{6}V%f%b"}'

# Kill the old process of slow commands if it is still running.
if (( _prompt_sorin_precmd_async_pid > 0 )); then
kill -KILL "$_prompt_sorin_precmd_async_pid" &>/dev/null
async_flush_jobs async_sorin_git

# Handle updating git data. We also clear the git prompt data if we're in a
# different git root now.
local new_git_root="$(git-dir 2>/dev/null)"
if [[ $new_git_root != $_sorin_cur_git_root ]]; then
_prompt_sorin_git=''
_sorin_cur_git_root=$new_git_root
fi

# Compute slow commands in the background.
trap prompt_sorin_git_info WINCH
prompt_sorin_precmd_async &!
_prompt_sorin_precmd_async_pid=$!
async_job async_sorin_git prompt_sorin_async_git "$PWD"
}

function prompt_sorin_setup {
Expand All @@ -107,6 +100,7 @@ function prompt_sorin_setup {

# Load required functions.
autoload -Uz add-zsh-hook
autoload -Uz async && async

# Add hook for calling git-info before each command.
add-zsh-hook precmd prompt_sorin_precmd
Expand All @@ -133,11 +127,19 @@ function prompt_sorin_setup {
zstyle ':prezto:module:git:info:unmerged' format ' %%B%F{3}═%f%%b'
zstyle ':prezto:module:git:info:untracked' format ' %%B%F{7}◼%f%%b'
zstyle ':prezto:module:git:info:keys' format \
'status' '$(coalesce "%b" "%p" "%c")%s%A%B%S%a%d%m%r%U%u'
'status' '%b %p %c:%s%A%B%S%a%d%m%r%U%u'

# Get the async worker set up
async_start_worker async_sorin_git -n
async_register_callback async_sorin_git prompt_sorin_git_info
_sorin_cur_git_root=''

_prompt_sorin_git=''
_prompt_sorin_pwd=''

# Define prompts.
PROMPT='${SSH_TTY:+"%F{9}%n%f%F{7}@%f%F{3}%m%f "}%F{4}${_prompt_sorin_pwd}%(!. %B%F{1}#%f%b.)${editor_info[keymap]} '
RPROMPT=''
RPROMPT='${editor_info[overwrite]}%(?:: %F{1}⏎%f)${VIM:+" %B%F{6}V%f%b"}${_prompt_sorin_git}'
SPROMPT='zsh: correct %F{1}%R%f to %F{2}%r%f [nyae]? '
}

Expand Down

0 comments on commit b6e01cc

Please sign in to comment.