From d04fbf6d1a1dd38b2c99322d4f6dc82595fa8fc0 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 12 Apr 2020 11:20:38 -0500 Subject: [PATCH 01/19] Move Git action after dirty with space and default color (#506) Co-authored-by: Sindre Sorhus --- pure.zsh | 14 +++++++------- readme.md | 25 +++++++++++++------------ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/pure.zsh b/pure.zsh index 90093d9e..0e56a8d3 100644 --- a/pure.zsh +++ b/pure.zsh @@ -143,14 +143,14 @@ prompt_pure_preprompt_render() { # Set the path. preprompt_parts+=('%F{${prompt_pure_colors[path]}}%~%f') - # Add Git branch and dirty status info. + # Git branch and dirty status info. typeset -gA prompt_pure_vcs_info if [[ -n $prompt_pure_vcs_info[branch] ]]; then - local branch="%F{$git_color}"'${prompt_pure_vcs_info[branch]}' - if [[ -n $prompt_pure_vcs_info[action] ]]; then - branch+="|%F{$prompt_pure_colors[git:action]}"'$prompt_pure_vcs_info[action]'"%F{$git_color}" - fi - preprompt_parts+=("$branch""%F{$git_dirty_color}"'${prompt_pure_git_dirty}%f') + preprompt_parts+=("%F{$git_color}"'${prompt_pure_vcs_info[branch]}'"%F{$git_dirty_color}"'${prompt_pure_git_dirty}%f') + fi + # Git action (for example, merge). + if [[ -n $prompt_pure_vcs_info[action] ]]; then + preprompt_parts+=("%F{$prompt_pure_colors[git:action]}"'$prompt_pure_vcs_info[action]%f') fi # Git pull/push arrows. if [[ -n $prompt_pure_git_arrows ]]; then @@ -746,7 +746,7 @@ prompt_pure_setup() { git:stash cyan git:branch 242 git:branch:cached red - git:action 242 + git:action yellow git:dirty 218 host 242 path blue diff --git a/readme.md b/readme.md index c8a0aef7..6c62f997 100644 --- a/readme.md +++ b/readme.md @@ -134,18 +134,19 @@ Colors can be changed by using [`zstyle`](http://zsh.sourceforge.net/Doc/Release The following diagram shows where each color is applied on the prompt: ``` -┌───────────────────────────────────────────── path -│ ┌────────────────────────────────── git:branch -│ │ ┌─────────────────────────── git:action -│ │ │ ┌─────────────────── git:dirty -│ │ │ │ ┌───────────────── git:arrow -│ │ │ │ │ ┌─────────────── git:stash -│ │ │ │ │ │ ┌────── host -│ │ │ │ │ │ │ -~/dev/pure master|rebase-i* ⇡ ≡ zaphod@heartofgold 42s -venv ❯ │ │ -│ │ │ └───── execution_time -│ │ └──────────────────────── user +┌────────────────────────────────────────────────────── user +│ ┌─────────────────────────────────────────────── host +│ │ ┌─────────────────────────────────── path +│ │ │ ┌──────────────────────── git:branch +│ │ │ │ ┌────────────────── git:dirty +│ │ │ │ │ ┌──────────────── git:action +│ │ │ │ │ │ ┌─────── git:arrow +│ │ │ │ │ │ │ ┌───── git:stash +│ │ │ │ │ │ │ │ ┌─── execution_time +│ │ │ │ │ │ │ │ │ +zaphod@heartofgold ~/dev/pure master* rebase-i ⇡ ≡ 42s +venv ❯ +│ │ │ └───────────────────────────────────────────────── prompt └────────────────────────────────────────────────────── virtualenv (or prompt:continuation) ``` From 7f1e473c15216a19a1df9a868e3facbf61981fee Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 13 Apr 2020 08:55:41 -0500 Subject: [PATCH 02/19] Fix stash during git action (#535) Co-authored-by: Sindre Sorhus Co-authored-by: Mathias Fredriksson --- pure.zsh | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/pure.zsh b/pure.zsh index 0e56a8d3..6eee2bf9 100644 --- a/pure.zsh +++ b/pure.zsh @@ -24,14 +24,6 @@ # \e[2K => clear everything on the current line -+vi-git-stash() { - local -a stashes - stashes=$(git stash list 2>/dev/null | wc -l) - if [[ $stashes -gt 0 ]]; then - hook_com[misc]="stash=${stashes}" - fi -} - # Turns seconds into human readable time. # 165392 => 1d 21h 56m 32s # https://github.com/sindresorhus/pretty-time-zsh @@ -157,7 +149,7 @@ prompt_pure_preprompt_render() { preprompt_parts+=('%F{$prompt_pure_colors[git:arrow]}${prompt_pure_git_arrows}%f') fi # Git stash symbol (if opted in). - if [[ -n $prompt_pure_vcs_info[stash] ]]; then + if [[ -n $prompt_pure_git_stash ]]; then preprompt_parts+=('%F{$prompt_pure_colors[git:stash]}${PURE_GIT_STASH_SYMBOL:-≡}%f') fi @@ -267,14 +259,10 @@ prompt_pure_async_vcs_info() { zstyle ':vcs_info:*' enable git zstyle ':vcs_info:*' use-simple true # Only export four message variables from `vcs_info`. - zstyle ':vcs_info:*' max-exports 4 - # Export branch (%b), Git toplevel (%R), action (rebase/cherry-pick) (%a), - # and stash information via misc (%m). - zstyle ':vcs_info:git*' formats '%b' '%R' '%a' '%m' - zstyle ':vcs_info:git*' actionformats '%b' '%R' '%a' '%m' - if [[ $1 == 0 ]]; then - zstyle ':vcs_info:git*+set-message:*' hooks git-stash - fi + zstyle ':vcs_info:*' max-exports 3 + # Export branch (%b), Git toplevel (%R), action (rebase/cherry-pick) (%a) + zstyle ':vcs_info:git*' formats '%b' '%R' '%a' + zstyle ':vcs_info:git*' actionformats '%b' '%R' '%a' vcs_info @@ -283,7 +271,6 @@ prompt_pure_async_vcs_info() { info[branch]=$vcs_info_msg_0_ info[top]=$vcs_info_msg_1_ info[action]=$vcs_info_msg_2_ - info[stash]=$vcs_info_msg_3_ print -r - ${(@kvq)info} } @@ -365,6 +352,10 @@ prompt_pure_async_git_arrows() { command git rev-list --left-right --count HEAD...@'{u}' } +prompt_pure_async_git_stash() { + git rev-list --walk-reflogs --count refs/stash +} + # Try to lower the priority of the worker so that disk heavy operations # like `git status` has less impact on the system responsivity. prompt_pure_async_renice() { @@ -408,12 +399,10 @@ prompt_pure_async_tasks() { unset prompt_pure_git_fetch_pattern prompt_pure_vcs_info[branch]= prompt_pure_vcs_info[top]= - prompt_pure_vcs_info[stash]= fi unset MATCH MBEGIN MEND - zstyle -t ":prompt:pure:git:stash" show - async_job "prompt_pure" prompt_pure_async_vcs_info $? + async_job "prompt_pure" prompt_pure_async_vcs_info # Only perform tasks inside a Git working tree. [[ -n $prompt_pure_vcs_info[top] ]] || return @@ -447,6 +436,13 @@ prompt_pure_async_refresh() { # Check check if there is anything to pull. async_job "prompt_pure" prompt_pure_async_git_dirty ${PURE_GIT_UNTRACKED_DIRTY:-1} fi + + # If stash is enabled, tell async worker to count stashes + if zstyle -t ":prompt:pure:git:stash" show; then + async_job "prompt_pure" prompt_pure_async_git_stash + else + unset prompt_pure_git_stash + fi } prompt_pure_check_git_arrows() { @@ -505,7 +501,6 @@ prompt_pure_async_callback() { prompt_pure_vcs_info[branch]=$info[branch] prompt_pure_vcs_info[top]=$info[top] prompt_pure_vcs_info[action]=$info[action] - prompt_pure_vcs_info[stash]=$info[stash] do_render=1 ;; @@ -563,6 +558,11 @@ prompt_pure_async_callback() { ;; esac ;; + prompt_pure_async_git_stash) + local prev_stash=$prompt_pure_git_stash + typeset -g prompt_pure_git_stash=$output + [[ $prev_stash != $prompt_pure_git_stash ]] && do_render=1 + ;; prompt_pure_async_renice) ;; esac From 3589b7f3f8a687b2a3b7f91100bae540fcd4056f Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Thu, 16 Apr 2020 17:22:07 +0800 Subject: [PATCH 03/19] Use HTTPS links --- readme.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/readme.md b/readme.md index 6c62f997..cc06b393 100644 --- a/readme.md +++ b/readme.md @@ -50,7 +50,6 @@ Most prompts are cluttered, ugly and slow. I wanted something visually pleasing - Support VI-mode indication by reverse prompt symbol (Zsh 5.3+). - Makes an excellent starting point for your own custom prompt. - ## Install Can be installed with `npm` or manually. Requires Git 2.0.0+ and ZSH 5.2+. Older versions of ZSH are known to work, but they are **not** recommended. @@ -88,7 +87,6 @@ autoload -U promptinit; promptinit prompt pure ``` - ## Options | Option | Description | Default value | @@ -163,7 +161,6 @@ zmodload zsh/nearcolor zstyle :prompt:pure:path color '#FF0000' ``` - ## Example ```sh @@ -186,7 +183,6 @@ zstyle :prompt:pure:git:stash show yes prompt pure ``` - ## Tips In the screenshot you see Pure running in [Hyper](https://hyper.is) with the [hyper-snazzy](https://github.com/sindresorhus/hyper-snazzy) theme and Menlo font. @@ -196,7 +192,6 @@ The [Tomorrow Night Eighties](https://github.com/chriskempson/tomorrow-theme) th To have commands colorized as seen in the screenshot, install [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting). - ## Integration ### [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh) @@ -253,14 +248,12 @@ zinit ice compile'(pure|async).zsh' pick'async.zsh' src'pure.zsh' zinit light sindresorhus/pure ``` - ## FAQ There are currently no FAQs. See [FAQ Archive](https://github.com/sindresorhus/pure/wiki/FAQ-Archive) for previous FAQs. - ## Ports - **ZSH** @@ -281,9 +274,8 @@ See [FAQ Archive](https://github.com/sindresorhus/pure/wiki/FAQ-Archive) for pre - **PowerShell** - [nickcox/pure-pwsh](https://github.com/nickcox/pure-pwsh/) - PowerShell/PS Core implementation of the Pure prompt. - ## Team -[![Sindre Sorhus](https://github.com/sindresorhus.png?size=100)](http://sindresorhus.com) | [![Mathias Fredriksson](https://github.com/mafredri.png?size=100)](https://github.com/mafredri) +[![Sindre Sorhus](https://github.com/sindresorhus.png?size=100)](https://sindresorhus.com) | [![Mathias Fredriksson](https://github.com/mafredri.png?size=100)](https://github.com/mafredri) ---|--- [Sindre Sorhus](https://github.com/sindresorhus) | [Mathias Fredriksson](https://github.com/mafredri) From 81dd496eb380aa051494f93fd99322ec796ec4c2 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 1 May 2020 19:12:42 +0300 Subject: [PATCH 04/19] Respawn Pure async worker on crash (#543) --- async.zsh | 176 ++++++++++++++++++++++++++++++++++++++---------------- pure.zsh | 51 ++++++++++++---- 2 files changed, 164 insertions(+), 63 deletions(-) diff --git a/async.zsh b/async.zsh index d0f3f001..4c1dccc3 100644 --- a/async.zsh +++ b/async.zsh @@ -3,12 +3,12 @@ # # zsh-async # -# version: 1.7.2 +# version: 1.8.0 # author: Mathias Fredriksson # url: https://github.com/mafredri/zsh-async # -typeset -g ASYNC_VERSION=1.7.2 +typeset -g ASYNC_VERSION=1.8.0 # Produce debug output from zsh-async when set to 1. typeset -g ASYNC_DEBUG=${ASYNC_DEBUG:-0} @@ -37,19 +37,27 @@ _async_job() { # block, after the command block has completed, the stdin for `cat` is # closed, causing stderr to be appended with a $'\0' at the end to mark the # end of output from this job. - local jobname=${ASYNC_JOB_NAME:-$1} - local stdout stderr ret tok - { - stdout=$(eval "$@") - ret=$? - duration=$(( EPOCHREALTIME - duration )) # Calculate duration. + local jobname=${ASYNC_JOB_NAME:-$1} out + out="$( + local stdout stderr ret tok + { + stdout=$(eval "$@") + ret=$? + duration=$(( EPOCHREALTIME - duration )) # Calculate duration. + + print -r -n - $'\0'${(q)jobname} $ret ${(q)stdout} $duration + } 2> >(stderr=$(cat) && print -r -n - " "${(q)stderr}$'\0') + )" + if [[ $out != $'\0'*$'\0' ]]; then + # Corrupted output (aborted job?), skipping. + return + fi - # Grab mutex lock, stalls until token is available. - read -r -k 1 -p tok || exit 1 + # Grab mutex lock, stalls until token is available. + read -r -k 1 -p tok || return 1 - # Return output ( ). - print -r -n - $'\0'${(q)jobname} $ret ${(q)stdout} $duration - } 2> >(stderr=$(cat) && print -r -n - " "${(q)stderr}$'\0') + # Return output ( ). + print -r -n - "$out" # Unlock mutex by inserting a token. print -n -p $tok @@ -73,10 +81,13 @@ _async_worker() { # When a zpty is deleted (using -d) all the zpty instances created before # the one being deleted receive a SIGHUP, unless we catch it, the async # worker would simply exit (stop working) even though visible in the list - # of zpty's (zpty -L). - TRAPHUP() { - return 0 # Return 0, indicating signal was handled. - } + # of zpty's (zpty -L). This has been fixed around the time of Zsh 5.4 + # (not released). + if ! is-at-least 5.4.1; then + TRAPHUP() { + return 0 # Return 0, indicating signal was handled. + } + fi local -A storage local unique=0 @@ -121,15 +132,33 @@ _async_worker() { # Register a SIGCHLD trap to handle the completion of child processes. trap child_exit CHLD - # Process option parameters passed to worker - while getopts "np:u" opt; do + # Process option parameters passed to worker. + while getopts "np:uz" opt; do case $opt in n) notify_parent=1;; p) parent_pid=$OPTARG;; u) unique=1;; + z) notify_parent=0;; # Uses ZLE watcher instead. esac done + # Terminate all running jobs, note that this function does not + # reinstall the child trap. + terminate_jobs() { + trap - CHLD # Ignore child exits during kill. + coproc : # Quit coproc. + coproc_pid=0 # Reset pid. + + if is-at-least 5.4.1; then + trap '' HUP # Catch the HUP sent to this process. + kill -HUP -$$ # Send to entire process group. + trap - HUP # Disable HUP trap. + else + # We already handle HUP for Zsh < 5.4.1. + kill -HUP -$$ # Send to entire process group. + fi + } + killjobs() { local tok local -a pids @@ -143,9 +172,8 @@ _async_worker() { # process is in the middle of writing to stdin during kill. (( coproc_pid )) && read -r -k 1 -p tok - kill -HUP -$$ # Send to entire process group. - coproc : # Quit coproc. - coproc_pid=0 # Reset pid. + terminate_jobs + trap child_exit CHLD # Reinstall child trap. } local request do_eval=0 @@ -153,17 +181,27 @@ _async_worker() { while :; do # Wait for jobs sent by async_job. read -r -d $'\0' request || { - # Since we handle SIGHUP above (and thus do not know when `zpty -d`) - # occurs, a failure to read probably indicates that stdin has - # closed. This is why we propagate the signal to all children and - # exit manually. - kill -HUP -$$ # Send SIGHUP to all jobs. - exit 0 + # Unknown error occurred while reading from stdin, the zpty + # worker is likely in a broken state, so we shut down. + terminate_jobs + + # Stdin is broken and in case this was an unintended + # crash, we try to report it as a last hurrah. + print -r -n $'\0'"'[async]'" $(( 127 + 3 )) "''" 0 "'$0:$LINENO: zpty fd died, exiting'"$'\0' + + # We use `return` to abort here because using `exit` may + # result in an infinite loop that never exits and, as a + # result, high CPU utilization. + return $(( 127 + 1 )) } + # We need to clean the input here because sometimes when a zpty + # has died and been respawned, messages will be prefixed with a + # carraige return (\r, or \C-M). + request=${request#$'\C-M'} + # Check for non-job commands sent to worker case $request in - _unset_trap) notify_parent=0; continue;; _killjobs) killjobs; continue;; _async_eval*) do_eval=1;; esac @@ -175,9 +213,11 @@ _async_worker() { # Name of the job (first argument). local job=$cmd[1] - # If worker should perform unique jobs - if (( unique )); then - # Check if a previous job is still running, if yes, let it finnish + # Check if a worker should perform unique jobs, unless + # this is an eval since they run synchronously. + if (( !do_eval )) && (( unique )); then + # Check if a previous job is still running, if yes, + # skip this job and let the previous one finish. for pid in ${${(v)jobstates##*:*:}%\=*}; do if [[ ${storage[$job]} == $pid ]]; then continue 2 @@ -317,7 +357,7 @@ _async_zle_watcher() { async_stop_worker $worker if [[ -n $callback ]]; then - $callback '[async]' 2 "" 0 "$worker:zle -F $1 returned error $2" 0 + $callback '[async]' 2 "" 0 "$0:$LINENO: error: fd for $worker failed: zle -F $1 returned error $2" 0 fi return fi; @@ -327,6 +367,28 @@ _async_zle_watcher() { fi } +_async_send_job() { + setopt localoptions noshwordsplit noksharrays noposixidentifiers noposixstrings + + local caller=$1 + local worker=$2 + shift 2 + + zpty -t $worker &>/dev/null || { + typeset -gA ASYNC_CALLBACKS + local callback=$ASYNC_CALLBACKS[$worker] + + if [[ -n $callback ]]; then + $callback '[async]' 3 "" 0 "$0:$LINENO: error: no such worker: $worker" 0 + else + print -u2 "$caller: no such async worker: $worker" + fi + return 1 + } + + zpty -w $worker "$@"$'\0' +} + # # Start a new asynchronous job on specified worker, assumes the worker is running. # @@ -344,8 +406,7 @@ async_job() { cmd=(${(q)cmd}) # Quote special characters in multi argument commands. fi - # Quote the cmd in case RC_EXPAND_PARAM is set. - zpty -w $worker "$cmd"$'\0' + _async_send_job $0 $worker "$cmd" } # @@ -369,7 +430,7 @@ async_worker_eval() { fi # Quote the cmd in case RC_EXPAND_PARAM is set. - zpty -w $worker "_async_eval $cmd"$'\0' + _async_send_job $0 $worker "_async_eval $cmd" } # This function traps notification signals and calls all registered callbacks @@ -392,7 +453,7 @@ _async_notify_trap() { async_register_callback() { setopt localoptions noshwordsplit nolocaltraps - typeset -gA ASYNC_CALLBACKS + typeset -gA ASYNC_PTYS ASYNC_CALLBACKS local worker=$1; shift ASYNC_CALLBACKS[$worker]="$*" @@ -401,6 +462,14 @@ async_register_callback() { # workers to notify (via -n) when a job is done. if [[ ! -o interactive ]] || [[ ! -o zle ]]; then trap '_async_notify_trap' WINCH + elif [[ -o interactive ]] && [[ -o zle ]]; then + local fd w + for fd w in ${(@kv)ASYNC_PTYS}; do + if [[ $w == $worker ]]; then + zle -F $fd _async_zle_watcher # Register the ZLE handler. + break + fi + done fi } @@ -465,6 +534,8 @@ async_start_worker() { setopt localoptions noshwordsplit local worker=$1; shift + local -a args + args=("$@") zpty -t $worker &>/dev/null && return typeset -gA ASYNC_PTYS @@ -478,15 +549,21 @@ async_start_worker() { unsetopt xtrace } - if (( ! ASYNC_ZPTY_RETURNS_FD )) && [[ -o interactive ]] && [[ -o zle ]]; then - # When zpty doesn't return a file descriptor (on older versions of zsh) - # we try to guess it anyway. - integer -l zptyfd - exec {zptyfd}>&1 # Open a new file descriptor (above 10). - exec {zptyfd}>&- # Close it so it's free to be used by zpty. + if [[ -o interactive ]] && [[ -o zle ]]; then + # Inform the worker to ignore the notify flag and that we're + # using a ZLE watcher instead. + args+=(-z) + + if (( ! ASYNC_ZPTY_RETURNS_FD )); then + # When zpty doesn't return a file descriptor (on older versions of zsh) + # we try to guess it anyway. + integer -l zptyfd + exec {zptyfd}>&1 # Open a new file descriptor (above 10). + exec {zptyfd}>&- # Close it so it's free to be used by zpty. + fi fi - zpty -b $worker _async_worker -p $$ $@ || { + zpty -b $worker _async_worker -p $$ $args || { async_stop_worker $worker return 1 } @@ -494,7 +571,7 @@ async_start_worker() { # Re-enable it if it was enabled, for debugging. (( has_xtrace )) && setopt xtrace - if [[ $ZSH_VERSION < 5.0.8 ]]; then + if ! is-at-least 5.0.8; then # For ZSH versions older than 5.0.8 we delay a bit to give # time for the worker to start before issuing commands, # otherwise it will not be ready to receive them. @@ -506,11 +583,7 @@ async_start_worker() { REPLY=$zptyfd # Use the guessed value for the file desciptor. fi - ASYNC_PTYS[$REPLY]=$worker # Map the file desciptor to the worker. - zle -F $REPLY _async_zle_watcher # Register the ZLE handler. - - # Disable trap in favor of ZLE handler when notify is enabled (-n). - async_job $worker _unset_trap + ASYNC_PTYS[$REPLY]=$worker # Map the file desciptor to the worker. fi } @@ -556,6 +629,9 @@ async_init() { zmodload zsh/zpty zmodload zsh/datetime + # Load is-at-least for reliable version check. + autoload -Uz is-at-least + # Check if zsh/zpty returns a file descriptor or not, # shell must also be interactive with zle enabled. typeset -g ASYNC_ZPTY_RETURNS_FD=0 diff --git a/pure.zsh b/pure.zsh index 6eee2bf9..90919097 100644 --- a/pure.zsh +++ b/pure.zsh @@ -121,6 +121,8 @@ prompt_pure_set_colors() { prompt_pure_preprompt_render() { setopt localoptions noshwordsplit + unset prompt_pure_async_render_requested + # Set color for Git branch/dirty status and change color if dirty checking has been delayed. local git_color=$prompt_pure_colors[git:branch] local git_dirty_color=$prompt_pure_colors[git:dirty] @@ -129,7 +131,7 @@ prompt_pure_preprompt_render() { # Initialize the preprompt array. local -a preprompt_parts - # Username and machine, if applicable. + # Username and machine, if applicable. [[ -n $prompt_pure_state[username] ]] && preprompt_parts+=($prompt_pure_state[username]) # Set the path. @@ -191,6 +193,8 @@ prompt_pure_preprompt_render() { } prompt_pure_precmd() { + setopt localoptions noshwordsplit + # Check execution time and store it in a variable. prompt_pure_check_cmd_exec_time unset prompt_pure_cmd_timestamp @@ -370,16 +374,22 @@ prompt_pure_async_renice() { fi } +prompt_pure_async_init() { + typeset -g prompt_pure_async_inited + if ((${prompt_pure_async_inited:-0})); then + return + fi + prompt_pure_async_inited=1 + async_start_worker "prompt_pure" -u -n + async_register_callback "prompt_pure" prompt_pure_async_callback + async_worker_eval "prompt_pure" prompt_pure_async_renice +} + prompt_pure_async_tasks() { setopt localoptions noshwordsplit # Initialize the async worker. - ((!${prompt_pure_async_init:-0})) && { - async_start_worker "prompt_pure" -u -n - async_register_callback "prompt_pure" prompt_pure_async_callback - typeset -g prompt_pure_async_init=1 - async_job "prompt_pure" prompt_pure_async_renice - } + prompt_pure_async_init # Update the current working directory of the async worker. async_worker_eval "prompt_pure" builtin cd -q $PWD @@ -463,10 +473,27 @@ prompt_pure_async_callback() { case $job in \[async]) - # Code is 1 for corrupted worker output and 2 for dead worker. - if [[ $code -eq 2 ]]; then - # Our worker died unexpectedly. - typeset -g prompt_pure_async_init=0 + # Handle all the errors that could indicate a crashed + # async worker. See zsh-async documentation for the + # definition of the exit codes. + if (( code == 2 )) || (( code == 3 )) || (( code == 130 )); then + # Our worker died unexpectedly, try to recover immediately. + # TODO(mafredri): Do we need to handle next_pending + # and defer the restart? + typeset -g prompt_pure_async_inited=0 + async_stop_worker prompt_pure + prompt_pure_async_init # Reinit the worker. + prompt_pure_async_tasks # Restart all tasks. + + # Reset render state due to restart. + unset prompt_pure_async_render_requested + fi + ;; + \[async/eval]) + if (( code )); then + # Looks like async_worker_eval failed, + # rerun async tasks just in case. + prompt_pure_async_tasks fi ;; prompt_pure_async_vcs_info) @@ -563,8 +590,6 @@ prompt_pure_async_callback() { typeset -g prompt_pure_git_stash=$output [[ $prev_stash != $prompt_pure_git_stash ]] && do_render=1 ;; - prompt_pure_async_renice) - ;; esac if (( next_pending )); then From c42bd354943ba4cf2da3ecf493fca4fef0b2722c Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 2 May 2020 00:17:25 +0800 Subject: [PATCH 05/19] 1.12.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 61b5cdf4..b2bf53ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pure-prompt", - "version": "1.11.0", + "version": "1.12.0", "description": "Pretty, minimal and fast ZSH prompt", "license": "MIT", "repository": "sindresorhus/pure", From abd6c438880426a3dc03a4e272ef419328e17909 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sun, 5 Jul 2020 17:38:30 +0800 Subject: [PATCH 06/19] Readme tweaks --- readme.md | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/readme.md b/readme.md index cc06b393..0100d25c 100644 --- a/readme.md +++ b/readme.md @@ -4,38 +4,9 @@ -
- ---- - -
-

-

- - Sindre's open source work is supported by the community - -

- Special thanks to: -
-
- - Botpress - -
- Botpress is an open-source conversational assistant creation platform. -
- They welcome contributions from anyone, whether you're into machine learning,
want to get started in open-source, or just have an improvement idea.
-
-

-
- ---- - -
- ## Overview -Most prompts are cluttered, ugly and slow. I wanted something visually pleasing that stayed out of my way. +Most prompts are cluttered, ugly and slow. We wanted something visually pleasing that stayed out of our way. ### Why? From 3a70426baa023eaee53bbf36dc8b28eb4c79fac8 Mon Sep 17 00:00:00 2001 From: Michael Bianco Date: Tue, 7 Jul 2020 14:27:02 -0600 Subject: [PATCH 07/19] Eliminate unnecessary Git locking (#549) --- pure.zsh | 2 +- readme.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pure.zsh b/pure.zsh index 90919097..cfb9fbce 100644 --- a/pure.zsh +++ b/pure.zsh @@ -287,7 +287,7 @@ prompt_pure_async_git_dirty() { if [[ $untracked_dirty = 0 ]]; then command git diff --no-ext-diff --quiet --exit-code else - test -z "$(command git status --porcelain --ignore-submodules -unormal)" + test -z "$(command git status --no-optional-locks --porcelain --ignore-submodules -unormal)" fi return $? diff --git a/readme.md b/readme.md index 0100d25c..61b19cda 100644 --- a/readme.md +++ b/readme.md @@ -23,7 +23,7 @@ Most prompts are cluttered, ugly and slow. We wanted something visually pleasing ## Install -Can be installed with `npm` or manually. Requires Git 2.0.0+ and ZSH 5.2+. Older versions of ZSH are known to work, but they are **not** recommended. +Can be installed with `npm` or manually. Requires Git 2.15.2+ and ZSH 5.2+. Older versions of ZSH are known to work, but they are **not** recommended. ### npm From 3a5355b0299dbebfe8b010e1cec2c361dd8e773a Mon Sep 17 00:00:00 2001 From: Diogo Duarte Date: Wed, 8 Jul 2020 14:21:26 +0100 Subject: [PATCH 08/19] Fix '--no-optional-locks' argument position (#553) --- pure.zsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pure.zsh b/pure.zsh index cfb9fbce..2cbd7d06 100644 --- a/pure.zsh +++ b/pure.zsh @@ -287,7 +287,7 @@ prompt_pure_async_git_dirty() { if [[ $untracked_dirty = 0 ]]; then command git diff --no-ext-diff --quiet --exit-code else - test -z "$(command git status --no-optional-locks --porcelain --ignore-submodules -unormal)" + test -z "$(command git --no-optional-locks status --porcelain --ignore-submodules -unormal)" fi return $? From 7ae0cb59005a836736c8f9ec3c2d09b465e42c58 Mon Sep 17 00:00:00 2001 From: Emily Marigold Klassen Date: Thu, 6 Aug 2020 03:48:58 -0700 Subject: [PATCH 09/19] Add forivall/pure to Ports section in the readme (#556) --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 61b19cda..0dd06801 100644 --- a/readme.md +++ b/readme.md @@ -230,6 +230,7 @@ See [FAQ Archive](https://github.com/sindresorhus/pure/wiki/FAQ-Archive) for pre - **ZSH** - [therealklanni/purity](https://github.com/therealklanni/purity) - More compact current working directory, important details on the main prompt line, and extra Git indicators. - [intelfx/pure](https://github.com/intelfx/pure) - Solarized-friendly colors, highly verbose, and fully async Git integration. + - [forivall/pure](https://github.com/forivall/pure) - A minimal fork which highlights the Git repo's root directory in the path. - [dfurnes/purer](https://github.com/dfurnes/purer) - Compact single-line prompt with built-in Vim-mode indicator. - [chabou/pure-now](https://github.com/chabou/pure-now) - Fork with [Now](https://zeit.co/now) support. - [pure10k](https://gist.github.com/romkatv/7cbab80dcbc639003066bb68b9ae0bbf) - Configuration file for [Powerlevel10k](https://github.com/romkatv/powerlevel10k/) that makes it look like Pure. From 0a3801807dc274515dd6a2a26d56f63881ad07b4 Mon Sep 17 00:00:00 2001 From: Jamie Macdonald Date: Mon, 10 Aug 2020 13:09:14 -0700 Subject: [PATCH 10/19] Respect Git config `status.showUntrackedFiles` (#542) --- pure.zsh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pure.zsh b/pure.zsh index 2cbd7d06..aef4725a 100644 --- a/pure.zsh +++ b/pure.zsh @@ -283,11 +283,15 @@ prompt_pure_async_vcs_info() { prompt_pure_async_git_dirty() { setopt localoptions noshwordsplit local untracked_dirty=$1 + local untracked_git_mode=$(command git config --get status.showUntrackedFiles) + if [[ "$untracked_git_mode" != 'no' ]]; then + untracked_git_mode='normal' + fi if [[ $untracked_dirty = 0 ]]; then command git diff --no-ext-diff --quiet --exit-code else - test -z "$(command git --no-optional-locks status --porcelain --ignore-submodules -unormal)" + test -z "$(command git --no-optional-locks status --porcelain --ignore-submodules -u${untracked_git_mode})" fi return $? From 567990aedfb404f4c1c83bb8afc3555319e6b0f1 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 10 Aug 2020 22:10:50 +0200 Subject: [PATCH 11/19] 1.13.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b2bf53ae..9706a1ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pure-prompt", - "version": "1.12.0", + "version": "1.13.0", "description": "Pretty, minimal and fast ZSH prompt", "license": "MIT", "repository": "sindresorhus/pure", From 02643fd167b6bace2f31ad248fc317e32a42d3fd Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Wed, 9 Sep 2020 17:49:35 +0200 Subject: [PATCH 12/19] Update readme.md --- readme.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/readme.md b/readme.md index 0dd06801..4ff6820b 100644 --- a/readme.md +++ b/readme.md @@ -4,6 +4,30 @@ +
+ +--- + + + +--- + +
+ ## Overview Most prompts are cluttered, ugly and slow. We wanted something visually pleasing that stayed out of our way. From 5cbf310a4bcba40e3bcd001aca22f850b837e8cc Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 24 Sep 2020 00:35:25 +0300 Subject: [PATCH 13/19] Bump Pure internal version when publishing package (#565) --- package.json | 3 ++- pure.zsh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9706a1ed..24fdf3e7 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "scripts": { "postinstall": "PURE_DEST=/usr/local/share/zsh/site-functions npm run --silent postinstall-link && exit 0; PURE_DEST=\"$PWD/functions\" npm run postinstall-link && npm run postinstall-fail-instructions", "postinstall-link": "mkdir -p \"$PURE_DEST\" && ln -sf \"$PWD/pure.zsh\" \"$PURE_DEST/prompt_pure_setup\" && ln -sf \"$PWD/async.zsh\" \"$PURE_DEST/async\"", - "postinstall-fail-instructions": "echo \"ERROR: Could not automagically symlink the prompt. Either:\\n1. Check out the readme on how to do it manually: https://github.com/sindresorhus/pure#manually\\n2. Or add the following to your \\`.zshrc\\`:\\n\\n fpath+=('$PWD/functions')\"" + "postinstall-fail-instructions": "echo \"ERROR: Could not automagically symlink the prompt. Either:\\n1. Check out the readme on how to do it manually: https://github.com/sindresorhus/pure#manually\\n2. Or add the following to your \\`.zshrc\\`:\\n\\n fpath+=('$PWD/functions')\"", + "version": "sed -i '' -e 's/prompt_pure_state\\[version\\]=.*/prompt_pure_state[version]=\"'\"$npm_package_version\"'\"/' pure.zsh" }, "files": [ "pure.zsh", diff --git a/pure.zsh b/pure.zsh index aef4725a..dea15f65 100644 --- a/pure.zsh +++ b/pure.zsh @@ -684,7 +684,7 @@ prompt_pure_state_setup() { [[ $UID -eq 0 ]] && username='%F{$prompt_pure_colors[user:root]}%n%f'"$hostname" typeset -gA prompt_pure_state - prompt_pure_state[version]="1.11.0" + prompt_pure_state[version]="1.13.0" prompt_pure_state+=( username "$username" prompt "${PURE_PROMPT_SYMBOL:-❯}" From 10953cfc0ab95c9fc201161627df89175d9c93e7 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 24 Sep 2020 00:35:50 +0300 Subject: [PATCH 14/19] Add zsh-async version to system report (#567) --- pure.zsh | 1 + 1 file changed, 1 insertion(+) diff --git a/pure.zsh b/pure.zsh index dea15f65..a97d466b 100644 --- a/pure.zsh +++ b/pure.zsh @@ -712,6 +712,7 @@ prompt_pure_system_report() { for k v in "${(@kv)prompt_pure_state}"; do print - " - $k: \`${(q)v}\`" done + print - "- zsh-async version: ${ASYNC_VERSION}" print - "- PROMPT: \`$(typeset -p PROMPT)\`" print - "- Colors: \`$(typeset -p prompt_pure_colors)\`" print - "- Virtualenv: \`$(typeset -p VIRTUAL_ENV_DISABLE_PROMPT)\`" From b8335a6be16623c0a38f9a1c867dadd76b6f02b4 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 24 Sep 2020 01:56:11 +0300 Subject: [PATCH 15/19] Update zsh-async to v1.8.4 (#566) --- async.zsh | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/async.zsh b/async.zsh index 4c1dccc3..08ed3a6b 100644 --- a/async.zsh +++ b/async.zsh @@ -3,12 +3,12 @@ # # zsh-async # -# version: 1.8.0 +# version: v1.8.4 # author: Mathias Fredriksson # url: https://github.com/mafredri/zsh-async # -typeset -g ASYNC_VERSION=1.8.0 +typeset -g ASYNC_VERSION=1.8.4 # Produce debug output from zsh-async when set to 1. typeset -g ASYNC_DEBUG=${ASYNC_DEBUG:-0} @@ -531,7 +531,7 @@ async_flush_jobs() { # -p pid to notify (defaults to current pid) # async_start_worker() { - setopt localoptions noshwordsplit + setopt localoptions noshwordsplit noclobber local worker=$1; shift local -a args @@ -542,13 +542,6 @@ async_start_worker() { typeset -h REPLY typeset has_xtrace=0 - # Make sure async worker is started without xtrace - # (the trace output interferes with the worker). - [[ -o xtrace ]] && { - has_xtrace=1 - unsetopt xtrace - } - if [[ -o interactive ]] && [[ -o zle ]]; then # Inform the worker to ignore the notify flag and that we're # using a ZLE watcher instead. @@ -563,13 +556,31 @@ async_start_worker() { fi fi - zpty -b $worker _async_worker -p $$ $args || { - async_stop_worker $worker - return 1 + # Workaround for stderr in the main shell sometimes (incorrectly) being + # reassigned to /dev/null by the reassignment done inside the async + # worker. + # See https://github.com/mafredri/zsh-async/issues/35. + integer errfd=-1 + exec {errfd}>&2 + + # Make sure async worker is started without xtrace + # (the trace output interferes with the worker). + [[ -o xtrace ]] && { + has_xtrace=1 + unsetopt xtrace } + zpty -b $worker _async_worker -p $$ $args 2>&$errfd + local ret=$? + # Re-enable it if it was enabled, for debugging. (( has_xtrace )) && setopt xtrace + exec {errfd}>& - + + if (( ret )); then + async_stop_worker $worker + return 1 + fi if ! is-at-least 5.0.8; then # For ZSH versions older than 5.0.8 we delay a bit to give From 7cc22a4a1e235800059167266289304b9f87ba44 Mon Sep 17 00:00:00 2001 From: Tim Spence Date: Thu, 24 Sep 2020 13:54:03 -0700 Subject: [PATCH 16/19] Show user@host when running in a container (#564) --- pure.zsh | 9 +++++++++ readme.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pure.zsh b/pure.zsh index a97d466b..d334226c 100644 --- a/pure.zsh +++ b/pure.zsh @@ -680,6 +680,9 @@ prompt_pure_state_setup() { # Show `username@host` if logged in through SSH. [[ -n $ssh_connection ]] && username='%F{$prompt_pure_colors[user]}%n%f'"$hostname" + # Show `username@host` if inside a container. + prompt_pure_is_inside_container && username='%F{$prompt_pure_colors[user]}%n%f'"$hostname" + # Show `username@host` if root, with username in default color. [[ $UID -eq 0 ]] && username='%F{$prompt_pure_colors[user:root]}%n%f'"$hostname" @@ -691,6 +694,12 @@ prompt_pure_state_setup() { ) } +# Return true if executing inside a Docker or LXC container. +prompt_pure_is_inside_container() { + ([[ -r /proc/1/cgroup ]] && grep -q -E "(lxc|docker)" /proc/1/cgroup ) \ + || [[ "$container" == "lxc" ]] +} + prompt_pure_system_report() { setopt localoptions noshwordsplit diff --git a/readme.md b/readme.md index 4ff6820b..1990c530 100644 --- a/readme.md +++ b/readme.md @@ -40,7 +40,7 @@ Most prompts are cluttered, ugly and slow. We wanted something visually pleasing - Indicates when you have unpushed/unpulled `git` commits with up/down arrows. *(Check is done asynchronously!)* - Prompt character turns red if the last command didn't exit with `0`. - Command execution time will be displayed if it exceeds the set threshold. -- Username and host only displayed when in an SSH session. +- Username and host only displayed when in an SSH session or a container. - Shows the current path in the title and the [current folder & command](screenshot-title-cmd.png) when a process is running. - Support VI-mode indication by reverse prompt symbol (Zsh 5.3+). - Makes an excellent starting point for your own custom prompt. From 7924d0938a6d7dafa75f8b27b177ff32d05bc6e2 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Sun, 27 Sep 2020 15:51:49 +0300 Subject: [PATCH 17/19] Use GIT_OPTIONAL_LOCKS=0 instead of --no-optional-locks (#569) --- pure.zsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pure.zsh b/pure.zsh index d334226c..785ac042 100644 --- a/pure.zsh +++ b/pure.zsh @@ -291,7 +291,7 @@ prompt_pure_async_git_dirty() { if [[ $untracked_dirty = 0 ]]; then command git diff --no-ext-diff --quiet --exit-code else - test -z "$(command git --no-optional-locks status --porcelain --ignore-submodules -u${untracked_git_mode})" + test -z "$(GIT_OPTIONAL_LOCKS=0 command git status --porcelain --ignore-submodules -u${untracked_git_mode})" fi return $? From f9a36863257c41622696a150491714a1750ef841 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Sun, 27 Sep 2020 15:52:43 +0300 Subject: [PATCH 18/19] More system report improvements (#568) --- pure.zsh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pure.zsh b/pure.zsh index 785ac042..6ba2ebc3 100644 --- a/pure.zsh +++ b/pure.zsh @@ -703,11 +703,15 @@ prompt_pure_is_inside_container() { prompt_pure_system_report() { setopt localoptions noshwordsplit - print - "- Zsh: $($SHELL --version) ($SHELL)" + local shell=$SHELL + if [[ -z $shell ]]; then + shell=$commands[zsh] + fi + print - "- Zsh: $($shell --version) ($shell)" print -n - "- Operating system: " case "$(uname -s)" in Darwin) print "$(sw_vers -productName) $(sw_vers -productVersion) ($(sw_vers -buildVersion))";; - *) print "$(uname -s) ($(uname -v))";; + *) print "$(uname -s) ($(uname -r) $(uname -v) $(uname -m) $(uname -o))";; esac print - "- Terminal program: ${TERM_PROGRAM:-unknown} (${TERM_PROGRAM_VERSION:-unknown})" print -n - "- Tmux: " @@ -719,11 +723,12 @@ prompt_pure_system_report() { print - "- Pure state:" for k v in "${(@kv)prompt_pure_state}"; do - print - " - $k: \`${(q)v}\`" + print - " - $k: \`${(q-)v}\`" done - print - "- zsh-async version: ${ASYNC_VERSION}" + print - "- zsh-async version: \`${ASYNC_VERSION}\`" print - "- PROMPT: \`$(typeset -p PROMPT)\`" print - "- Colors: \`$(typeset -p prompt_pure_colors)\`" + print - "- TERM: \`$(typeset -p TERM)\`" print - "- Virtualenv: \`$(typeset -p VIRTUAL_ENV_DISABLE_PROMPT)\`" print - "- Conda: \`$(typeset -p CONDA_CHANGEPS1)\`" From fda3c1951be42e90198c9262171734aaf42ad978 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sun, 27 Sep 2020 14:55:37 +0200 Subject: [PATCH 19/19] 1.14.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 24fdf3e7..2c596b58 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pure-prompt", - "version": "1.13.0", + "version": "1.14.0", "description": "Pretty, minimal and fast ZSH prompt", "license": "MIT", "repository": "sindresorhus/pure",