diff --git a/async.zsh b/async.zsh index d0f3f001..08ed3a6b 100644 --- a/async.zsh +++ b/async.zsh @@ -3,12 +3,12 @@ # # zsh-async # -# version: 1.7.2 +# version: v1.8.4 # author: Mathias Fredriksson # url: https://github.com/mafredri/zsh-async # -typeset -g ASYNC_VERSION=1.7.2 +typeset -g ASYNC_VERSION=1.8.4 # 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 } @@ -462,15 +531,38 @@ 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 + args=("$@") zpty -t $worker &>/dev/null && return typeset -gA ASYNC_PTYS typeset -h REPLY typeset has_xtrace=0 + 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 + + # 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 ]] && { @@ -478,23 +570,19 @@ 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. - fi - - zpty -b $worker _async_worker -p $$ $@ || { - async_stop_worker $worker - return 1 - } + 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 [[ $ZSH_VERSION < 5.0.8 ]]; then + 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 # time for the worker to start before issuing commands, # otherwise it will not be ready to receive them. @@ -506,11 +594,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 +640,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/package.json b/package.json index 61b5cdf4..2c596b58 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pure-prompt", - "version": "1.11.0", + "version": "1.14.0", "description": "Pretty, minimal and fast ZSH prompt", "license": "MIT", "repository": "sindresorhus/pure", @@ -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 90093d9e..6ba2ebc3 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 @@ -129,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] @@ -137,27 +131,27 @@ 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. 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 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 @@ -199,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 @@ -267,14 +263,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 +275,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} } @@ -292,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 status --porcelain --ignore-submodules -unormal)" + test -z "$(GIT_OPTIONAL_LOCKS=0 command git status --porcelain --ignore-submodules -u${untracked_git_mode})" fi return $? @@ -365,6 +360,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() { @@ -379,16 +378,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 @@ -408,12 +413,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 +450,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() { @@ -467,10 +477,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) @@ -505,7 +532,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,7 +589,10 @@ prompt_pure_async_callback() { ;; esac ;; - prompt_pure_async_renice) + 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 ;; esac @@ -651,25 +680,38 @@ 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" 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:-❯}" ) } +# 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 - 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: " @@ -681,10 +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 - "- 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)\`" @@ -746,7 +790,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..1990c530 100644 --- a/readme.md +++ b/readme.md @@ -12,20 +12,15 @@

- Sindre's open source work is supported by the community + Sindre Sorhus' 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.
-

@@ -35,7 +30,7 @@ ## 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? @@ -45,15 +40,14 @@ Most prompts are cluttered, ugly and slow. I 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. - ## 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 @@ -88,7 +82,6 @@ autoload -U promptinit; promptinit prompt pure ``` - ## Options | Option | Description | Default value | @@ -134,18 +127,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) ``` @@ -162,7 +156,6 @@ zmodload zsh/nearcolor zstyle :prompt:pure:path color '#FF0000' ``` - ## Example ```sh @@ -185,7 +178,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. @@ -195,7 +187,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) @@ -252,19 +243,18 @@ 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** - [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. @@ -280,9 +270,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)