Browse Source

ijioj

master
Inhji Y. 1 year ago
parent
commit
c36882a6ab
19 changed files with 1 additions and 2286 deletions
  1. +1
    -7
      .gitmodules
  2. +0
    -12
      pure/.editorconfig
  3. +0
    -1
      pure/.gitattributes
  4. +0
    -1
      pure/.github/funding.yml
  5. +0
    -34
      pure/.github/issue_template.md
  6. +0
    -1
      pure/.npmrc
  7. +0
    -26
      pure/arch/PKGBUILD
  8. +0
    -574
      pure/async.zsh
  9. +0
    -9
      pure/license
  10. +0
    -42
      pure/package.json
  11. +0
    -1
      pure/pure.plugin.zsh
  12. +0
    -738
      pure/pure.zsh
  13. +0
    -267
      pure/readme.md
  14. BIN
      pure/screenshot-title-cmd.png
  15. BIN
      pure/screenshot.png
  16. +0
    -4
      z/Makefile
  17. +0
    -146
      z/README
  18. +0
    -170
      z/z.1
  19. +0
    -253
      z/z.sh

+ 1
- 7
.gitmodules View File

@@ -1,9 +1,3 @@
[submodule "dotbot"]
path = dotbot
url = https://github.com/anishathalye/dotbot
[submodule "pure"]
path = pure
url = https://github.com/sindresorhus/pure.git
[submodule "z"]
path = z
url = https://github.com/rupa/z.git
url = https://github.com/anishathalye/dotbot

+ 0
- 12
pure/.editorconfig View File

@@ -1,12 +0,0 @@
root = true

[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.yml]
indent_style = space
indent_size = 2

+ 0
- 1
pure/.gitattributes View File

@@ -1 +0,0 @@
* text=auto eol=lf

+ 0
- 1
pure/.github/funding.yml View File

@@ -1 +0,0 @@
github: sindresorhus

+ 0
- 34
pure/.github/issue_template.md View File

@@ -1,34 +0,0 @@
<!-- TIP: Hit 'Preview' for a more readable version of this template -->

### General information

- Pure version: 1.x.x
- ZSH version: 5.x.x
- Terminal program & version: <!-- e.g. Hyper 1.0.0, iTerm 3.0.0, Terminal 2.7.1, xterm 327, other? -->
- Operating system: <!-- e.g. macOS Sierra 10.12.1 -->
- ZSH framework: <!-- e.g. oh-my-zsh, prezto, antigen, antibody, zplug, other? -->

I have:
- [ ] Tested with another terminal program and can reproduce the issue: <!-- e.g. iTerm, etc. -->
- [ ] Followed the [Integration](https://github.com/sindresorhus/pure#integration) instructions for my framework

### Problem description


### Reproduction steps

1.
2.
3.

### My `.zshrc`:

<!--
Please provide a minimal `.zshrc` that reproduces the issue.
Try to remove everything that that does not affect the issue, the fewer lines, the better.
-->

```shell
autoload -U promptinit; promptinit
prompt pure
```

+ 0
- 1
pure/.npmrc View File

@@ -1 +0,0 @@
package-lock=false

+ 0
- 26
pure/arch/PKGBUILD View File

@@ -1,26 +0,0 @@
# Author: Sindre Sorhus
# Maintainer: Pat Brisbin <pbrisbin@gmail.com>
# Contributor: Emil Falk <emph@emph.se>
pkgname=zsh-pure-prompt-git
pkgver=r61.7d3b317
pkgrel=1
pkgdesc='A minimal and pure prompt for zsh.'
arch=('any')
url='https://github.com/sindresorhus/pure'
license=('MIT')
depends=('zsh' 'git')
source=("$pkgname::git://github.com/sindresorhus/pure.git")
sha256sums=('SKIP')

pkgver() {
cd $srcdir/$pkgname
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}

package() {
cd $srcdir/$pkgname
install -Dm644 pure.zsh \
"$pkgdir/usr/share/zsh/functions/Prompts/prompt_pure_setup"
install -Dm644 async.zsh \
"$pkgdir/usr/share/zsh/functions/async"
}

+ 0
- 574
pure/async.zsh View File

@@ -1,574 +0,0 @@
#!/usr/bin/env zsh

#
# zsh-async
#
# version: 1.7.2
# author: Mathias Fredriksson
# url: https://github.com/mafredri/zsh-async
#

typeset -g ASYNC_VERSION=1.7.2
# Produce debug output from zsh-async when set to 1.
typeset -g ASYNC_DEBUG=${ASYNC_DEBUG:-0}

# Execute commands that can manipulate the environment inside the async worker. Return output via callback.
_async_eval() {
local ASYNC_JOB_NAME
# Rename job to _async_eval and redirect all eval output to cat running
# in _async_job. Here, stdout and stderr are not separated for
# simplicity, this could be improved in the future.
{
eval "$@"
} &> >(ASYNC_JOB_NAME=[async/eval] _async_job 'cat')
}

# Wrapper for jobs executed by the async worker, gives output in parseable format with execution time
_async_job() {
# Disable xtrace as it would mangle the output.
setopt localoptions noxtrace

# Store start time for job.
float -F duration=$EPOCHREALTIME

# Run the command and capture both stdout (`eval`) and stderr (`cat`) in
# separate subshells. When the command is complete, we grab write lock
# (mutex token) and output everything except stderr inside the command
# 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.

# Grab mutex lock, stalls until token is available.
read -r -k 1 -p tok || exit 1

# Return output (<job_name> <return_code> <stdout> <duration> <stderr>).
print -r -n - $'\0'${(q)jobname} $ret ${(q)stdout} $duration
} 2> >(stderr=$(cat) && print -r -n - " "${(q)stderr}$'\0')

# Unlock mutex by inserting a token.
print -n -p $tok
}

# The background worker manages all tasks and runs them without interfering with other processes
_async_worker() {
# Reset all options to defaults inside async worker.
emulate -R zsh

# Make sure monitor is unset to avoid printing the
# pids of child processes.
unsetopt monitor

# Redirect stderr to `/dev/null` in case unforseen errors produced by the
# worker. For example: `fork failed: resource temporarily unavailable`.
# Some older versions of zsh might also print malloc errors (know to happen
# on at least zsh 5.0.2 and 5.0.8) likely due to kill signals.
exec 2>/dev/null

# 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.
}

local -A storage
local unique=0
local notify_parent=0
local parent_pid=0
local coproc_pid=0
local processing=0

local -a zsh_hooks zsh_hook_functions
zsh_hooks=(chpwd periodic precmd preexec zshexit zshaddhistory)
zsh_hook_functions=(${^zsh_hooks}_functions)
unfunction $zsh_hooks &>/dev/null # Deactivate all zsh hooks inside the worker.
unset $zsh_hook_functions # And hooks with registered functions.
unset zsh_hooks zsh_hook_functions # Cleanup.

close_idle_coproc() {
local -a pids
pids=(${${(v)jobstates##*:*:}%\=*})

# If coproc (cat) is the only child running, we close it to avoid
# leaving it running indefinitely and cluttering the process tree.
if (( ! processing )) && [[ $#pids = 1 ]] && [[ $coproc_pid = $pids[1] ]]; then
coproc :
coproc_pid=0
fi
}

child_exit() {
close_idle_coproc

# On older version of zsh (pre 5.2) we notify the parent through a
# SIGWINCH signal because `zpty` did not return a file descriptor (fd)
# prior to that.
if (( notify_parent )); then
# We use SIGWINCH for compatibility with older versions of zsh
# (pre 5.1.1) where other signals (INFO, ALRM, USR1, etc.) could
# cause a deadlock in the shell under certain circumstances.
kill -WINCH $parent_pid
fi
}

# 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
case $opt in
n) notify_parent=1;;
p) parent_pid=$OPTARG;;
u) unique=1;;
esac
done

killjobs() {
local tok
local -a pids
pids=(${${(v)jobstates##*:*:}%\=*})

# No need to send SIGHUP if no jobs are running.
(( $#pids == 0 )) && continue
(( $#pids == 1 )) && [[ $coproc_pid = $pids[1] ]] && continue

# Grab lock to prevent half-written output in case a child
# 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.
}

local request do_eval=0
local -a cmd
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
}

# 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

# Parse the request using shell parsing (z) to allow commands
# to be parsed from single strings and multi-args alike.
cmd=("${(z)request}")

# 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
for pid in ${${(v)jobstates##*:*:}%\=*}; do
if [[ ${storage[$job]} == $pid ]]; then
continue 2
fi
done
fi

# Guard against closing coproc from trap before command has started.
processing=1

# Because we close the coproc after the last job has completed, we must
# recreate it when there are no other jobs running.
if (( ! coproc_pid )); then
# Use coproc as a mutex for synchronized output between children.
coproc cat
coproc_pid="$!"
# Insert token into coproc
print -n -p "t"
fi

if (( do_eval )); then
shift cmd # Strip _async_eval from cmd.
_async_eval $cmd
else
# Run job in background, completed jobs are printed to stdout.
_async_job $cmd &
# Store pid because zsh job manager is extremely unflexible (show jobname as non-unique '$job')...
storage[$job]="$!"
fi

processing=0 # Disable guard.

if (( do_eval )); then
do_eval=0

# When there are no active jobs we can't rely on the CHLD trap to
# manage the coproc lifetime.
close_idle_coproc
fi
done
}

#
# Get results from finished jobs and pass it to the to callback function. This is the only way to reliably return the
# job name, return code, output and execution time and with minimal effort.
#
# If the async process buffer becomes corrupt, the callback will be invoked with the first argument being `[async]` (job
# name), non-zero return code and fifth argument describing the error (stderr).
#
# usage:
# async_process_results <worker_name> <callback_function>
#
# callback_function is called with the following parameters:
# $1 = job name, e.g. the function passed to async_job
# $2 = return code
# $3 = resulting stdout from execution
# $4 = execution time, floating point e.g. 2.05 seconds
# $5 = resulting stderr from execution
# $6 = has next result in buffer (0 = buffer empty, 1 = yes)
#
async_process_results() {
setopt localoptions unset noshwordsplit noksharrays noposixidentifiers noposixstrings

local worker=$1
local callback=$2
local caller=$3
local -a items
local null=$'\0' data
integer -l len pos num_processed has_next

typeset -gA ASYNC_PROCESS_BUFFER

# Read output from zpty and parse it if available.
while zpty -r -t $worker data 2>/dev/null; do
ASYNC_PROCESS_BUFFER[$worker]+=$data
len=${#ASYNC_PROCESS_BUFFER[$worker]}
pos=${ASYNC_PROCESS_BUFFER[$worker][(i)$null]} # Get index of NULL-character (delimiter).

# Keep going until we find a NULL-character.
if (( ! len )) || (( pos > len )); then
continue
fi

while (( pos <= len )); do
# Take the content from the beginning, until the NULL-character and
# perform shell parsing (z) and unquoting (Q) as an array (@).
items=("${(@Q)${(z)ASYNC_PROCESS_BUFFER[$worker][1,$pos-1]}}")

# Remove the extracted items from the buffer.
ASYNC_PROCESS_BUFFER[$worker]=${ASYNC_PROCESS_BUFFER[$worker][$pos+1,$len]}

len=${#ASYNC_PROCESS_BUFFER[$worker]}
if (( len > 1 )); then
pos=${ASYNC_PROCESS_BUFFER[$worker][(i)$null]} # Get index of NULL-character (delimiter).
fi

has_next=$(( len != 0 ))
if (( $#items == 5 )); then
items+=($has_next)
$callback "${(@)items}" # Send all parsed items to the callback.
(( num_processed++ ))
elif [[ -z $items ]]; then
# Empty items occur between results due to double-null ($'\0\0')
# caused by commands being both pre and suffixed with null.
else
# In case of corrupt data, invoke callback with *async* as job
# name, non-zero exit status and an error message on stderr.
$callback "[async]" 1 "" 0 "$0:$LINENO: error: bad format, got ${#items} items (${(q)items})" $has_next
fi
done
done

(( num_processed )) && return 0

# Avoid printing exit value when `setopt printexitvalue` is active.`
[[ $caller = trap || $caller = watcher ]] && return 0

# No results were processed
return 1
}

# Watch worker for output
_async_zle_watcher() {
setopt localoptions noshwordsplit
typeset -gA ASYNC_PTYS ASYNC_CALLBACKS
local worker=$ASYNC_PTYS[$1]
local callback=$ASYNC_CALLBACKS[$worker]

if [[ -n $2 ]]; then
# from man zshzle(1):
# `hup' for a disconnect, `nval' for a closed or otherwise
# invalid descriptor, or `err' for any other condition.
# Systems that support only the `select' system call always use
# `err'.

# this has the side effect to unregister the broken file descriptor
async_stop_worker $worker

if [[ -n $callback ]]; then
$callback '[async]' 2 "" 0 "$worker:zle -F $1 returned error $2" 0
fi
return
fi;

if [[ -n $callback ]]; then
async_process_results $worker $callback watcher
fi
}

#
# Start a new asynchronous job on specified worker, assumes the worker is running.
#
# usage:
# async_job <worker_name> <my_function> [<function_params>]
#
async_job() {
setopt localoptions noshwordsplit noksharrays noposixidentifiers noposixstrings

local worker=$1; shift

local -a cmd
cmd=("$@")
if (( $#cmd > 1 )); then
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'
}

#
# Evaluate a command (like async_job) inside the async worker, then worker environment can be manipulated. For example,
# issuing a cd command will change the PWD of the worker which will then be inherited by all future async jobs.
#
# Output will be returned via callback, job name will be [async/eval].
#
# usage:
# async_worker_eval <worker_name> <my_function> [<function_params>]
#
async_worker_eval() {
setopt localoptions noshwordsplit noksharrays noposixidentifiers noposixstrings

local worker=$1; shift

local -a cmd
cmd=("$@")
if (( $#cmd > 1 )); then
cmd=(${(q)cmd}) # Quote special characters in multi argument commands.
fi

# Quote the cmd in case RC_EXPAND_PARAM is set.
zpty -w $worker "_async_eval $cmd"$'\0'
}

# This function traps notification signals and calls all registered callbacks
_async_notify_trap() {
setopt localoptions noshwordsplit

local k
for k in ${(k)ASYNC_CALLBACKS}; do
async_process_results $k ${ASYNC_CALLBACKS[$k]} trap
done
}

#
# Register a callback for completed jobs. As soon as a job is finnished, async_process_results will be called with the
# specified callback function. This requires that a worker is initialized with the -n (notify) option.
#
# usage:
# async_register_callback <worker_name> <callback_function>
#
async_register_callback() {
setopt localoptions noshwordsplit nolocaltraps

typeset -gA ASYNC_CALLBACKS
local worker=$1; shift

ASYNC_CALLBACKS[$worker]="$*"

# Enable trap when the ZLE watcher is unavailable, allows
# workers to notify (via -n) when a job is done.
if [[ ! -o interactive ]] || [[ ! -o zle ]]; then
trap '_async_notify_trap' WINCH
fi
}

#
# Unregister the callback for a specific worker.
#
# usage:
# async_unregister_callback <worker_name>
#
async_unregister_callback() {
typeset -gA ASYNC_CALLBACKS

unset "ASYNC_CALLBACKS[$1]"
}

#
# Flush all current jobs running on a worker. This will terminate any and all running processes under the worker, use
# with caution.
#
# usage:
# async_flush_jobs <worker_name>
#
async_flush_jobs() {
setopt localoptions noshwordsplit

local worker=$1; shift

# Check if the worker exists
zpty -t $worker &>/dev/null || return 1

# Send kill command to worker
async_job $worker "_killjobs"

# Clear the zpty buffer.
local junk
if zpty -r -t $worker junk '*'; then
(( ASYNC_DEBUG )) && print -n "async_flush_jobs $worker: ${(V)junk}"
while zpty -r -t $worker junk '*'; do
(( ASYNC_DEBUG )) && print -n "${(V)junk}"
done
(( ASYNC_DEBUG )) && print
fi

# Finally, clear the process buffer in case of partially parsed responses.
typeset -gA ASYNC_PROCESS_BUFFER
unset "ASYNC_PROCESS_BUFFER[$worker]"
}

#
# Start a new async worker with optional parameters, a worker can be told to only run unique tasks and to notify a
# process when tasks are complete.
#
# usage:
# async_start_worker <worker_name> [-u] [-n] [-p <pid>]
#
# opts:
# -u unique (only unique job names can run)
# -n notify through SIGWINCH signal
# -p pid to notify (defaults to current pid)
#
async_start_worker() {
setopt localoptions noshwordsplit

local worker=$1; shift
zpty -t $worker &>/dev/null && return

typeset -gA ASYNC_PTYS
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 (( ! 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
}

# Re-enable it if it was enabled, for debugging.
(( has_xtrace )) && setopt xtrace

if [[ $ZSH_VERSION < 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.
sleep 0.001
fi

if [[ -o interactive ]] && [[ -o zle ]]; then
if (( ! ASYNC_ZPTY_RETURNS_FD )); then
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
fi
}

#
# Stop one or multiple workers that are running, all unfetched and incomplete work will be lost.
#
# usage:
# async_stop_worker <worker_name_1> [<worker_name_2>]
#
async_stop_worker() {
setopt localoptions noshwordsplit

local ret=0 worker k v
for worker in $@; do
# Find and unregister the zle handler for the worker
for k v in ${(@kv)ASYNC_PTYS}; do
if [[ $v == $worker ]]; then
zle -F $k
unset "ASYNC_PTYS[$k]"
fi
done
async_unregister_callback $worker
zpty -d $worker 2>/dev/null || ret=$?

# Clear any partial buffers.
typeset -gA ASYNC_PROCESS_BUFFER
unset "ASYNC_PROCESS_BUFFER[$worker]"
done

return $ret
}

#
# Initialize the required modules for zsh-async. To be called before using the zsh-async library.
#
# usage:
# async_init
#
async_init() {
(( ASYNC_INIT_DONE )) && return
typeset -g ASYNC_INIT_DONE=1

zmodload zsh/zpty
zmodload zsh/datetime

# 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
[[ -o interactive ]] && [[ -o zle ]] && {
typeset -h REPLY
zpty _async_test :
(( REPLY )) && ASYNC_ZPTY_RETURNS_FD=1
zpty -d _async_test
}
}

async() {
async_init
}

async "$@"

+ 0
- 9
pure/license View File

@@ -1,9 +0,0 @@
MIT License

Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 0
- 42
pure/package.json View File

@@ -1,42 +0,0 @@
{
"name": "pure-prompt",
"version": "1.10.0",
"description": "Pretty, minimal and fast ZSH prompt",
"license": "MIT",
"repository": "sindresorhus/pure",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"maintainers": [
{
"name": "Mathias Fredriksson",
"url": "https://github.com/mafredri"
}
],
"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')\""
},
"files": [
"pure.zsh",
"async.zsh"
],
"keywords": [
"zsh",
"zshell",
"sh",
"shell",
"bash",
"pure",
"prompt",
"theme",
"git",
"async",
"fast",
"minimal",
"pretty"
]
}

+ 0
- 1
pure/pure.plugin.zsh View File

@@ -1 +0,0 @@
pure.zsh

+ 0
- 738
pure/pure.zsh View File

@@ -1,738 +0,0 @@
# Pure
# by Sindre Sorhus
# https://github.com/sindresorhus/pure
# MIT License

# For my own and others sanity
# git:
# %b => current branch
# %a => current action (rebase/merge)
# prompt:
# %F => color dict
# %f => reset color
# %~ => current path
# %* => time
# %n => username
# %m => shortname host
# %(?..) => prompt conditional - %(condition.true.false)
# terminal codes:
# \e7 => save cursor position
# \e[2A => move cursor 2 lines up
# \e[1G => go to position 1 in terminal
# \e8 => restore cursor position
# \e[K => clears everything after the cursor on the current line
# \e[2K => clear everything on the current line


# Turns seconds into human readable time.
# 165392 => 1d 21h 56m 32s
# https://github.com/sindresorhus/pretty-time-zsh
prompt_pure_human_time_to_var() {
local human total_seconds=$1 var=$2
local days=$(( total_seconds / 60 / 60 / 24 ))
local hours=$(( total_seconds / 60 / 60 % 24 ))
local minutes=$(( total_seconds / 60 % 60 ))
local seconds=$(( total_seconds % 60 ))
(( days > 0 )) && human+="${days}d "
(( hours > 0 )) && human+="${hours}h "
(( minutes > 0 )) && human+="${minutes}m "
human+="${seconds}s"

# Store human readable time in a variable as specified by the caller
typeset -g "${var}"="${human}"
}

# Stores (into prompt_pure_cmd_exec_time) the execution
# time of the last command if set threshold was exceeded.
prompt_pure_check_cmd_exec_time() {
integer elapsed
(( elapsed = EPOCHSECONDS - ${prompt_pure_cmd_timestamp:-$EPOCHSECONDS} ))
typeset -g prompt_pure_cmd_exec_time=
(( elapsed > ${PURE_CMD_MAX_EXEC_TIME:-5} )) && {
prompt_pure_human_time_to_var $elapsed "prompt_pure_cmd_exec_time"
}
}

prompt_pure_set_title() {
setopt localoptions noshwordsplit

# Emacs terminal does not support settings the title.
(( ${+EMACS} )) && return

case $TTY in
# Don't set title over serial console.
/dev/ttyS[0-9]*) return;;
esac

# Show hostname if connected via SSH.
local hostname=
if [[ -n $prompt_pure_state[username] ]]; then
# Expand in-place in case ignore-escape is used.
hostname="${(%):-(%m) }"
fi

local -a opts
case $1 in
expand-prompt) opts=(-P);;
ignore-escape) opts=(-r);;
esac

# Set title atomically in one print statement so that it works when XTRACE is enabled.
print -n $opts $'\e]0;'${hostname}${2}$'\a'
}

prompt_pure_preexec() {
if [[ -n $prompt_pure_git_fetch_pattern ]]; then
# Detect when Git is performing pull/fetch, including Git aliases.
local -H MATCH MBEGIN MEND match mbegin mend
if [[ $2 =~ (git|hub)\ (.*\ )?($prompt_pure_git_fetch_pattern)(\ .*)?$ ]]; then
# We must flush the async jobs to cancel our git fetch in order
# to avoid conflicts with the user issued pull / fetch.
async_flush_jobs 'prompt_pure'
fi
fi

typeset -g prompt_pure_cmd_timestamp=$EPOCHSECONDS

# Shows the current directory and executed command in the title while a process is active.
prompt_pure_set_title 'ignore-escape' "$PWD:t: $2"

# Disallow Python virtualenv from updating the prompt. Set it to 12 if
# untouched by the user to indicate that Pure modified it. Here we use
# the magic number 12, same as in `psvar`.
export VIRTUAL_ENV_DISABLE_PROMPT=${VIRTUAL_ENV_DISABLE_PROMPT:-12}
}

# Change the colors if their value are different from the current ones.
prompt_pure_set_colors() {
local color_temp
for key value in ${(kv)prompt_pure_colors}; do
zstyle -t ":prompt:pure:$key" color "$value"
case $? in
1) # The current style is different from the one from zstyle.
zstyle -s ":prompt:pure:$key" color color_temp
prompt_pure_colors[$key]=$color_temp ;;
2) # No style is defined.
prompt_pure_colors[$key]=$prompt_pure_colors_default[$key] ;;
esac
done
}

prompt_pure_preprompt_render() {
setopt localoptions noshwordsplit

# Set color for Git branch/dirty status and change color if dirty checking has been delayed.
local git_color=$prompt_pure_colors[git:branch]
[[ -n ${prompt_pure_git_last_dirty_check_timestamp+x} ]] && git_color=$prompt_pure_colors[git:branch:cached]

# Initialize the preprompt array.
local -a preprompt_parts

# Set the path.
preprompt_parts+=('%F{${prompt_pure_colors[path]}}%~%f')

# Add Git branch and dirty status info.
typeset -gA prompt_pure_vcs_info
if [[ -n $prompt_pure_vcs_info[branch] ]]; then
preprompt_parts+=("%F{$git_color}"'${prompt_pure_vcs_info[branch]}${prompt_pure_git_dirty}%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

# Username and machine, if applicable.
[[ -n $prompt_pure_state[username] ]] && preprompt_parts+=('${prompt_pure_state[username]}')
# Execution time.
[[ -n $prompt_pure_cmd_exec_time ]] && preprompt_parts+=('%F{$prompt_pure_colors[execution_time]}${prompt_pure_cmd_exec_time}%f')

local cleaned_ps1=$PROMPT
local -H MATCH MBEGIN MEND
if [[ $PROMPT = *$prompt_newline* ]]; then
# Remove everything from the prompt until the newline. This
# removes the preprompt and only the original PROMPT remains.
cleaned_ps1=${PROMPT##*${prompt_newline}}
fi
unset MATCH MBEGIN MEND

# Construct the new prompt with a clean preprompt.
local -ah ps1
ps1=(
${(j. .)preprompt_parts} # Join parts, space separated.
$prompt_newline # Separate preprompt and prompt.
$cleaned_ps1
)

PROMPT="${(j..)ps1}"

# Expand the prompt for future comparision.
local expanded_prompt
expanded_prompt="${(S%%)PROMPT}"

if [[ $1 == precmd ]]; then
# Initial newline, for spaciousness.
print
elif [[ $prompt_pure_last_prompt != $expanded_prompt ]]; then
# Redraw the prompt.
prompt_pure_reset_prompt
fi

typeset -g prompt_pure_last_prompt=$expanded_prompt
}

prompt_pure_precmd() {
# Check execution time and store it in a variable.
prompt_pure_check_cmd_exec_time
unset prompt_pure_cmd_timestamp

# Shows the full path in the title.
prompt_pure_set_title 'expand-prompt' '%~'

# Modify the colors if some have changed..
prompt_pure_set_colors

# Perform async Git dirty check and fetch.
prompt_pure_async_tasks

# Check if we should display the virtual env. We use a sufficiently high
# index of psvar (12) here to avoid collisions with user defined entries.
psvar[12]=
# Check if a Conda environment is active and display its name.
if [[ -n $CONDA_DEFAULT_ENV ]]; then
psvar[12]="${CONDA_DEFAULT_ENV//[$'\t\r\n']}"
fi
# When VIRTUAL_ENV_DISABLE_PROMPT is empty, it was unset by the user and
# Pure should take back control.
if [[ -n $VIRTUAL_ENV ]] && [[ -z $VIRTUAL_ENV_DISABLE_PROMPT || $VIRTUAL_ENV_DISABLE_PROMPT = 12 ]]; then
psvar[12]="${VIRTUAL_ENV:t}"
export VIRTUAL_ENV_DISABLE_PROMPT=12
fi

# Make sure VIM prompt is reset.
prompt_pure_reset_prompt_symbol

# Print the preprompt.
prompt_pure_preprompt_render "precmd"

if [[ -n $ZSH_THEME ]]; then
print "WARNING: Oh My Zsh themes are enabled (ZSH_THEME='${ZSH_THEME}'). Pure might not be working correctly."
print "For more information, see: https://github.com/sindresorhus/pure#oh-my-zsh"
unset ZSH_THEME # Only show this warning once.
fi
}

prompt_pure_async_git_aliases() {
setopt localoptions noshwordsplit
local -a gitalias pullalias

# List all aliases and split on newline.
gitalias=(${(@f)"$(command git config --get-regexp "^alias\.")"})
for line in $gitalias; do
parts=(${(@)=line}) # Split line on spaces.
aliasname=${parts[1]#alias.} # Grab the name (alias.[name]).
shift parts # Remove `aliasname`

# Check alias for pull or fetch. Must be exact match.
if [[ $parts =~ ^(.*\ )?(pull|fetch)(\ .*)?$ ]]; then
pullalias+=($aliasname)
fi
done

print -- ${(j:|:)pullalias} # Join on pipe, for use in regex.
}

prompt_pure_async_vcs_info() {
setopt localoptions noshwordsplit

# Configure `vcs_info` inside an async task. This frees up `vcs_info`
# to be used or configured as the user pleases.
zstyle ':vcs_info:*' enable git
zstyle ':vcs_info:*' use-simple true
# Only export two message variables from `vcs_info`.
zstyle ':vcs_info:*' max-exports 2
# Export branch (%b) and Git toplevel (%R).
zstyle ':vcs_info:git*' formats '%b' '%R'
zstyle ':vcs_info:git*' actionformats '%b|%a' '%R'

vcs_info

local -A info
info[pwd]=$PWD
info[top]=$vcs_info_msg_1_
info[branch]=$vcs_info_msg_0_

print -r - ${(@kvq)info}
}

# Fastest possible way to check if a Git repo is dirty.
prompt_pure_async_git_dirty() {
setopt localoptions noshwordsplit
local untracked_dirty=$1

if [[ $untracked_dirty = 0 ]]; then
command git diff --no-ext-diff --quiet --exit-code
else
test -z "$(command git status --porcelain --ignore-submodules -unormal)"
fi

return $?
}

prompt_pure_async_git_fetch() {
setopt localoptions noshwordsplit

# Sets `GIT_TERMINAL_PROMPT=0` to disable authentication prompt for Git fetch (Git 2.3+).
export GIT_TERMINAL_PROMPT=0
# Set SSH `BachMode` to disable all interactive SSH password prompting.
export GIT_SSH_COMMAND="${GIT_SSH_COMMAND:-"ssh"} -o BatchMode=yes"

# Default return code, which indicates Git fetch failure.
local fail_code=99

# Guard against all forms of password prompts. By setting the shell into
# MONITOR mode we can notice when a child process prompts for user input
# because it will be suspended. Since we are inside an async worker, we
# have no way of transmitting the password and the only option is to
# kill it. If we don't do it this way, the process will corrupt with the
# async worker.
setopt localtraps monitor

# Make sure local HUP trap is unset to allow for signal propagation when
# the async worker is flushed.
trap - HUP

trap '
# Unset trap to prevent infinite loop
trap - CHLD
if [[ $jobstates = suspended* ]]; then
# Set fail code to password prompt and kill the fetch.
fail_code=98
kill %%
fi
' CHLD

command git -c gc.auto=0 fetch >/dev/null &
wait $! || return $fail_code

unsetopt monitor

# Check arrow status after a successful `git fetch`.
prompt_pure_async_git_arrows
}

prompt_pure_async_git_arrows() {
setopt localoptions noshwordsplit
command git rev-list --left-right --count HEAD...@'{u}'
}

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
}

# Update the current working directory of the async worker.
async_worker_eval "prompt_pure" builtin cd -q $PWD

typeset -gA prompt_pure_vcs_info

local -H MATCH MBEGIN MEND
if [[ $PWD != ${prompt_pure_vcs_info[pwd]}* ]]; then
# Stop any running async jobs.
async_flush_jobs "prompt_pure"

# Reset Git preprompt variables, switching working tree.
unset prompt_pure_git_dirty
unset prompt_pure_git_last_dirty_check_timestamp
unset prompt_pure_git_arrows
unset prompt_pure_git_fetch_pattern
prompt_pure_vcs_info[branch]=
prompt_pure_vcs_info[top]=
fi
unset MATCH MBEGIN MEND

async_job "prompt_pure" prompt_pure_async_vcs_info

# Only perform tasks inside a Git working tree.
[[ -n $prompt_pure_vcs_info[top] ]] || return

prompt_pure_async_refresh
}

prompt_pure_async_refresh() {
setopt localoptions noshwordsplit

if [[ -z $prompt_pure_git_fetch_pattern ]]; then
# We set the pattern here to avoid redoing the pattern check until the
# working three has changed. Pull and fetch are always valid patterns.
typeset -g prompt_pure_git_fetch_pattern="pull|fetch"
async_job "prompt_pure" prompt_pure_async_git_aliases
fi

async_job "prompt_pure" prompt_pure_async_git_arrows

# Do not preform `git fetch` if it is disabled or in home folder.
if (( ${PURE_GIT_PULL:-1} )) && [[ $prompt_pure_vcs_info[top] != $HOME ]]; then
# Tell the async worker to do a `git fetch`.
async_job "prompt_pure" prompt_pure_async_git_fetch
fi

# If dirty checking is sufficiently fast,
# tell the worker to check it again, or wait for timeout.
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
unset prompt_pure_git_last_dirty_check_timestamp
# Check check if there is anything to pull.
async_job "prompt_pure" prompt_pure_async_git_dirty ${PURE_GIT_UNTRACKED_DIRTY:-1}
fi
}

prompt_pure_check_git_arrows() {
setopt localoptions noshwordsplit
local arrows left=${1:-0} right=${2:-0}

(( right > 0 )) && arrows+=${PURE_GIT_DOWN_ARROW:-⇣}
(( left > 0 )) && arrows+=${PURE_GIT_UP_ARROW:-⇡}

[[ -n $arrows ]] || return
typeset -g REPLY=$arrows
}

prompt_pure_async_callback() {
setopt localoptions noshwordsplit
local job=$1 code=$2 output=$3 exec_time=$4 next_pending=$6
local do_render=0

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
fi
;;
prompt_pure_async_vcs_info)
local -A info
typeset -gA prompt_pure_vcs_info

# Parse output (z) and unquote as array (Q@).
info=("${(Q@)${(z)output}}")
local -H MATCH MBEGIN MEND
if [[ $info[pwd] != $PWD ]]; then
# The path has changed since the check started, abort.
return
fi
# Check if Git top-level has changed.
if [[ $info[top] = $prompt_pure_vcs_info[top] ]]; then
# If the stored pwd is part of $PWD, $PWD is shorter and likelier
# to be top-level, so we update pwd.
if [[ $prompt_pure_vcs_info[pwd] = ${PWD}* ]]; then
prompt_pure_vcs_info[pwd]=$PWD
fi
else
# Store $PWD to detect if we (maybe) left the Git path.
prompt_pure_vcs_info[pwd]=$PWD
fi
unset MATCH MBEGIN MEND

# The update has a Git top-level set, which means we just entered a new
# Git directory. Run the async refresh tasks.
[[ -n $info[top] ]] && [[ -z $prompt_pure_vcs_info[top] ]] && prompt_pure_async_refresh

# Always update branch and top-level.
prompt_pure_vcs_info[branch]=$info[branch]
prompt_pure_vcs_info[top]=$info[top]

do_render=1
;;
prompt_pure_async_git_aliases)
if [[ -n $output ]]; then
# Append custom Git aliases to the predefined ones.
prompt_pure_git_fetch_pattern+="|$output"
fi
;;
prompt_pure_async_git_dirty)
local prev_dirty=$prompt_pure_git_dirty
if (( code == 0 )); then
unset prompt_pure_git_dirty
else
typeset -g prompt_pure_git_dirty="*"
fi

[[ $prev_dirty != $prompt_pure_git_dirty ]] && do_render=1

# When `prompt_pure_git_last_dirty_check_timestamp` is set, the Git info is displayed
# in a different color. To distinguish between a "fresh" and a "cached" result, the
# preprompt is rendered before setting this variable. Thus, only upon the next
# rendering of the preprompt will the result appear in a different color.
(( $exec_time > 5 )) && prompt_pure_git_last_dirty_check_timestamp=$EPOCHSECONDS
;;
prompt_pure_async_git_fetch|prompt_pure_async_git_arrows)
# `prompt_pure_async_git_fetch` executes `prompt_pure_async_git_arrows`
# after a successful fetch.
case $code in
0)
local REPLY
prompt_pure_check_git_arrows ${(ps:\t:)output}
if [[ $prompt_pure_git_arrows != $REPLY ]]; then
typeset -g prompt_pure_git_arrows=$REPLY
do_render=1
fi
;;
99|98)
# Git fetch failed.
;;
*)
# Non-zero exit status from `prompt_pure_async_git_arrows`,
# indicating that there is no upstream configured.
if [[ -n $prompt_pure_git_arrows ]]; then
unset prompt_pure_git_arrows
do_render=1
fi
;;
esac
;;
esac

if (( next_pending )); then
(( do_render )) && typeset -g prompt_pure_async_render_requested=1
return
fi

[[ ${prompt_pure_async_render_requested:-$do_render} = 1 ]] && prompt_pure_preprompt_render
unset prompt_pure_async_render_requested
}

prompt_pure_reset_prompt() {
if [[ $CONTEXT == cont ]]; then
# When the context is "cont", PS2 is active and calling
# reset-prompt will have no effect on PS1, but it will
# reset the execution context (%_) of PS2 which we don't
# want. Unfortunately, we can't save the output of "%_"
# either because it is only ever rendered as part of the
# prompt, expanding in-place won't work.
return
fi

zle && zle .reset-prompt
}

prompt_pure_reset_prompt_symbol() {
prompt_pure_state[prompt]=${PURE_PROMPT_SYMBOL:-❯}
}

prompt_pure_update_vim_prompt_widget() {
setopt localoptions noshwordsplit
prompt_pure_state[prompt]=${${KEYMAP/vicmd/${PURE_PROMPT_VICMD_SYMBOL:-❮}}/(main|viins)/${PURE_PROMPT_SYMBOL:-❯}}

prompt_pure_reset_prompt
}

prompt_pure_reset_vim_prompt_widget() {
setopt localoptions noshwordsplit
prompt_pure_reset_prompt_symbol

# We can't perform a prompt reset at this point because it
# removes the prompt marks inserted by macOS Terminal.
}

prompt_pure_state_setup() {
setopt localoptions noshwordsplit

# Check SSH_CONNECTION and the current state.
local ssh_connection=${SSH_CONNECTION:-$PROMPT_PURE_SSH_CONNECTION}
local username hostname
if [[ -z $ssh_connection ]] && (( $+commands[who] )); then
# When changing user on a remote system, the $SSH_CONNECTION
# environment variable can be lost. Attempt detection via `who`.
local who_out
who_out=$(who -m 2>/dev/null)
if (( $? )); then
# Who am I not supported, fallback to plain who.
local -a who_in
who_in=( ${(f)"$(who 2>/dev/null)"} )
who_out="${(M)who_in:#*[[:space:]]${TTY#/dev/}[[:space:]]*}"
fi

local reIPv6='(([0-9a-fA-F]+:)|:){2,}[0-9a-fA-F]+' # Simplified, only checks partial pattern.
local reIPv4='([0-9]{1,3}\.){3}[0-9]+' # Simplified, allows invalid ranges.
# Here we assume two non-consecutive periods represents a
# hostname. This matches `foo.bar.baz`, but not `foo.bar`.
local reHostname='([.][^. ]+){2}'

# Usually the remote address is surrounded by parenthesis, but
# not on all systems (e.g. busybox).
local -H MATCH MBEGIN MEND
if [[ $who_out =~ "\(?($reIPv4|$reIPv6|$reHostname)\)?\$" ]]; then
ssh_connection=$MATCH

# Export variable to allow detection propagation inside
# shells spawned by this one (e.g. tmux does not always
# inherit the same tty, which breaks detection).
export PROMPT_PURE_SSH_CONNECTION=$ssh_connection
fi
unset MATCH MBEGIN MEND
fi

hostname='%F{$prompt_pure_colors[host]}@%m%f'
# Show `username@host` if logged in through SSH.
[[ -n $ssh_connection ]] && 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.9.0"
prompt_pure_state+=(
username "$username"
prompt "${PURE_PROMPT_SYMBOL:-❯}"
)
}

prompt_pure_system_report() {
setopt localoptions noshwordsplit

print - "- Zsh: $(zsh --version)"
print -n - "- Operating system: "
case "$(uname -s)" in
Darwin) print "$(sw_vers -productName) $(sw_vers -productVersion) ($(sw_vers -buildVersion))";;
*) print "$(uname -s) ($(uname -v))";;
esac
print - "- Terminal program: $TERM_PROGRAM ($TERM_PROGRAM_VERSION)"

local git_version
git_version=($(git --version)) # Remove newlines, if hub is present.
print - "- Git: $git_version"

print - "- Pure state:"
for k v in "${(@kv)prompt_pure_state}"; do
print - "\t- $k: \`${(q)v}\`"
done
print - "- Virtualenv: \`$(typeset -p VIRTUAL_ENV_DISABLE_PROMPT)\`"
print - "- Prompt: \`$(typeset -p PROMPT)\`"

local ohmyzsh=0
typeset -la frameworks
(( $+ANTIBODY_HOME )) && frameworks+=("Antibody")
(( $+ADOTDIR )) && frameworks+=("Antigen")
(( $+ANTIGEN_HS_HOME )) && frameworks+=("Antigen-hs")
(( $+functions[upgrade_oh_my_zsh] )) && {
ohmyzsh=1
frameworks+=("Oh My Zsh")
}
(( $+ZPREZTODIR )) && frameworks+=("Prezto")
(( $+ZPLUG_ROOT )) && frameworks+=("Zplug")
(( $+ZPLGM )) && frameworks+=("Zplugin")

(( $#frameworks == 0 )) && frameworks+=("None")
print - "- Detected frameworks: ${(j:, :)frameworks}"

if (( ohmyzsh )); then
print - "\t- Oh My Zsh:"
print - "\t\t- Plugins: ${(j:, :)plugins}"
fi
}

prompt_pure_setup() {
# Prevent percentage showing up if output doesn't end with a newline.
export PROMPT_EOL_MARK=''

prompt_opts=(subst percent)

# Borrowed from `promptinit`. Sets the prompt options in case Pure was not
# initialized via `promptinit`.
setopt noprompt{bang,cr,percent,subst} "prompt${^prompt_opts[@]}"

if [[ -z $prompt_newline ]]; then
# This variable needs to be set, usually set by promptinit.
typeset -g prompt_newline=$'\n%{\r%}'
fi

zmodload zsh/datetime
zmodload zsh/zle
zmodload zsh/parameter
zmodload zsh/zutil

autoload -Uz add-zsh-hook
autoload -Uz vcs_info
autoload -Uz async && async

# The `add-zle-hook-widget` function is not guaranteed to be available.
# It was added in Zsh 5.3.
autoload -Uz +X add-zle-hook-widget 2>/dev/null

# Set the colors.
typeset -gA prompt_pure_colors_default prompt_pure_colors
prompt_pure_colors_default=(
execution_time yellow
git:arrow cyan
git:branch 242
git:branch:cached red
host 242
path blue
prompt:error red
prompt:success magenta
user 242
user:root default
virtualenv 242
)
prompt_pure_colors=("${(@fkv)prompt_pure_colors_default}")

add-zsh-hook precmd prompt_pure_precmd
add-zsh-hook preexec prompt_pure_preexec

prompt_pure_state_setup

zle -N prompt_pure_reset_prompt
zle -N prompt_pure_update_vim_prompt_widget
zle -N prompt_pure_reset_vim_prompt_widget
if (( $+functions[add-zle-hook-widget] )); then
add-zle-hook-widget zle-line-finish prompt_pure_reset_vim_prompt_widget
add-zle-hook-widget zle-keymap-select prompt_pure_update_vim_prompt_widget
fi

# If a virtualenv is activated, display it in grey.
PROMPT='%(12V.%F{$prompt_pure_colors[virtualenv]}%12v%f .)'

# Prompt turns red if the previous command didn't exit with 0.
PROMPT+='%(?.%F{$prompt_pure_colors[prompt:success]}.%F{$prompt_pure_colors[prompt:error]})${prompt_pure_state[prompt]}%f '

# Indicate continuation prompt by ... and use a darker color for it.
PROMPT2='%F{242}... %(1_.%_ .%_)%f%(?.%F{magenta}.%F{red})${prompt_pure_state[prompt]}%f '

# Store prompt expansion symbols for in-place expansion via (%). For
# some reason it does not work without storing them in a variable first.
typeset -ga prompt_pure_debug_depth
prompt_pure_debug_depth=('%e' '%N' '%x')

# Compare is used to check if %N equals %x. When they differ, the main
# prompt is used to allow displaying both filename and function. When
# they match, we use the secondary prompt to avoid displaying duplicate
# information.
local -A ps4_parts
ps4_parts=(
depth '%F{yellow}${(l:${(%)prompt_pure_debug_depth[1]}::+:)}%f'
compare '${${(%)prompt_pure_debug_depth[2]}:#${(%)prompt_pure_debug_depth[3]}}'
main '%F{blue}${${(%)prompt_pure_debug_depth[3]}:t}%f%F{242}:%I%f %F{242}@%f%F{blue}%N%f%F{242}:%i%f'
secondary '%F{blue}%N%f%F{242}:%i'
prompt '%F{242}>%f '
)
# Combine the parts with conditional logic. First the `:+` operator is
# used to replace `compare` either with `main` or an ampty string. Then
# the `:-` operator is used so that if `compare` becomes an empty
# string, it is replaced with `secondary`.
local ps4_symbols='${${'${ps4_parts[compare]}':+"'${ps4_parts[main]}'"}:-"'${ps4_parts[secondary]}'"}'

# Improve the debug prompt (PS4), show depth by repeating the +-sign and
# add colors to highlight essential parts like file and function name.
PROMPT4="${ps4_parts[depth]} ${ps4_symbols}${ps4_parts[prompt]}"

# Guard against Oh My Zsh themes overriding Pure.
unset ZSH_THEME
}

prompt_pure_setup "$@"

+ 0
- 267
pure/readme.md View File

@@ -1,267 +0,0 @@
# Pure

> Pretty, minimal and fast ZSH prompt

<img src="screenshot.png" width="864">


## Overview

Most prompts are cluttered, ugly and slow. I wanted something visually pleasing that stayed out of my way.

### Why?

- Comes with the perfect prompt character.
Author went through the whole Unicode range to find it.
- Shows `git` branch and whether it's dirty (with a `*`).
- 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.
- 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.

### npm

```console
$ npm install --global pure-prompt
```

That's it. Skip to [Getting started](#getting-started).

### Manually

1. Either…
- Clone this repo
- add it as a submodule, or
- just download [`pure.zsh`](pure.zsh) and [`async.zsh`](async.zsh)

2. Symlink `pure.zsh` to somewhere in [`$fpath`](https://www.refining-linux.org/archives/46-ZSH-Gem-12-Autoloading-functions.html) with the name `prompt_pure_setup`.

3. Symlink `async.zsh` in `$fpath` with the name `async`.

#### Example

```console
$ ln -s "$PWD/pure.zsh" /usr/local/share/zsh/site-functions/prompt_pure_setup
$ ln -s "$PWD/async.zsh" /usr/local/share/zsh/site-functions/async
```
*Run `echo $fpath` to see possible locations.*

For a user-specific installation (which would not require escalated privileges), simply add a directory to `$fpath` for that user:

```sh
# .zshenv or .zshrc
fpath=("$HOME/.zfunctions" $fpath)
```

Then install the theme there:

```console
$ ln -s "$PWD/pure.zsh" "$HOME/.zfunctions/prompt_pure_setup"
$ ln -s "$PWD/async.zsh" "$HOME/.zfunctions/async"
```


## Getting started

Initialize the prompt system (if not so already) and choose `pure`:

```sh
# .zshrc
autoload -U promptinit; promptinit
prompt pure
```


## Options

| Option | Description | Default value |
| :------------------------------- | :--------------------------------------------------------------------------------------------- | :------------- |
| **`PURE_CMD_MAX_EXEC_TIME`** | The max execution time of a process before its run time is shown when it exits. | `5` seconds |
| **`PURE_GIT_PULL=0`** | Prevents Pure from checking whether the current Git remote has been updated. | |
| **`PURE_GIT_UNTRACKED_DIRTY=0`** | Do not include untracked files in dirtiness check. Mostly useful on large repos (like WebKit). | |
| **`PURE_GIT_DELAY_DIRTY_CHECK`** | Time in seconds to delay git dirty checking when `git status` takes > 5 seconds. | `1800` seconds |
| **`PURE_PROMPT_SYMBOL`** | Defines the prompt symbol. | `❯` |
| **`PURE_PROMPT_VICMD_SYMBOL`** | Defines the prompt symbol used when the `vicmd` keymap is active (VI-mode). | `❮` |
| **`PURE_GIT_DOWN_ARROW`** | Defines the git down arrow symbol. | `⇣` |
| **`PURE_GIT_UP_ARROW`** | Defines the git up arrow symbol. | `⇡` |


## Colors

As explained in ZSH's [manual](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting), color values can be:
- A decimal integer corresponding to the color index of your terminal. If your `$TERM` is `xterm-256color`, see this [chart](https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg).
- The name of one of the following nine colors: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, and `default` (the terminal’s default foreground)
- `#` followed by an RGB triplet in hexadecimal format, for example `#424242`. Only if your terminal supports 24-bit colors (true color) or when the [`zsh/nearcolor` module](http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fnearcolor-Module) is loaded.

Colors can be changed by using [`zstyle`](http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fzutil-Module) with a pattern of the form `:prompt:pure:$color_name` and style `color`. The color names, their default, and what part they affect are:
- `exec_time` (yellow) - The execution time of the last command when exceeding `PURE_CMD_MAX_EXEC_TIME`.
- `git:arrow` (cyan) - For `PURE_GIT_UP_ARROW` and `PURE_GIT_DOWN_ARROW`.
- `git:branch` (242) - The name of the current branch when in a Git repository.
- `git:branch:cached` (red) - The name of the current branch when the data isn't fresh.
- `host` (242) - The hostname when on a remote machine.
- `path` (blue) - The current path, for example, `PWD`.
- `prompt:error` (red) - The `PURE_PROMPT_SYMBOL` when the previous command has *failed*.
- `prompt:success` (magenta) - The `PURE_PROMPT_SYMBOL` when the previous command has *succeded*.
- `user` (242) - The username when on remote machine.
- `user:root` (default) - The username when the user is root.
- `virtualenv` (242) - The name of the Python `virtualenv` when in use.

The following diagram shows where each color is applied on the prompt:

```
path
| git:branch
| | git:arrow
| | | host
| | | |
~/dev/pure master* ⇡ zaphod@heartofgold 42s
venv ❯ | |
| | | exec_time
| | user
| prompt
virtualenv
```

### RGB colors

There are two ways to use RGB colors with the hexadecimal format. The correct way is to use a [terminal that support 24-bit colors](https://gist.github.com/XVilka/8346728) and enable this feature as explained in the terminal's documentation.

If you can't use such terminal, the module [`zsh/nearcolor`](http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fnearcolor-Module) can be useful. It will map any hexadecimal color to the nearest color in the 88 or 256 color palettes of your termial, but without using the first 16 colors, since their values can be modified by the user. Keep in mind that when using this module you won't be able to display true RGB colors. It only allows you to specify colors in a more convenient way. The following is an example on how to use this module:

```sh
# .zshrc
zmodload zsh/nearcolor
zstyle :prompt:pure:path color '#FF0000'
```


## Example

```sh
# .zshrc

autoload -U promptinit; promptinit

# optionally define some options
PURE_CMD_MAX_EXEC_TIME=10

# change the path color
zstyle :prompt:pure:path color white

# change the color for both `prompt:success` and `prompt:error`
zstyle ':prompt:pure:prompt:*' color cyan

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.

The [Tomorrow Night Eighties](https://github.com/chriskempson/tomorrow-theme) theme with the [Droid Sans Mono](https://www.fontsquirrel.com/fonts/droid-sans-mono) font (15pt) is also a [nice combination](https://github.com/sindresorhus/pure/blob/95ee3e7618c6e2162a1e3cdac2a88a20ac3beb27/screenshot.png).<br>
*Just make sure you have anti-aliasing enabled in your terminal.*

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)

1. Set `ZSH_THEME=""` in your `.zshrc` to disable oh-my-zsh themes.
2. Follow the Pure [Install](#install) instructions.
3. Do not enable the following (incompatible) plugins: `vi-mode`, `virtualenv`.

**NOTE:** `oh-my-zsh` overrides the prompt so Pure must be activated *after* `source $ZSH/oh-my-zsh.sh`.

### [prezto](https://github.com/sorin-ionescu/prezto)

Pure is bundled with Prezto. No need to install it.

Add `prompt pure` to your `~/.zpreztorc`.

### [zim](https://github.com/Eriner/zim)

Pure is bundled with Zim. No need to install it.

Set `zprompt_theme='pure'` in `~/.zimrc`.

### [antigen](https://github.com/zsh-users/antigen)

Update your `.zshrc` file with the following two lines (order matters). Do not use the `antigen theme` function.

```sh
antigen bundle mafredri/zsh-async
antigen bundle sindresorhus/pure
```

### [antibody](https://github.com/getantibody/antibody)

Update your `.zshrc` file with the following two lines (order matters):

```sh
antibody bundle mafredri/zsh-async
antibody bundle sindresorhus/pure
```

### [zplug](https://github.com/zplug/zplug)

Update your `.zshrc` file with the following two lines:

```sh
zplug mafredri/zsh-async, from:github
zplug sindresorhus/pure, use:pure.zsh, from:github, as:theme
```

### [zplugin](https://github.com/zdharma/zplugin)

Update your `.zshrc` file with the following two lines (order matters):

```sh
zplugin ice pick"async.zsh" src"pure.zsh"
zplugin 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.
- [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.
- **Bash**
- [sapegin/dotfiles](https://github.com/sapegin/dotfiles) - [Prompt](https://github.com/sapegin/dotfiles/blob/dd063f9c30de7d2234e8accdb5272a5cc0a3388b/includes/bash_prompt.bash) and [color theme](https://github.com/sapegin/dotfiles/tree/master/color) for Terminal.app.
- **Fish**
- [brandonweiss/pure.fish](https://github.com/brandonweiss/pure.fish) - Pure-inspired prompt for Fish. Not intended to have feature parity.
- [rafaelrinaldi/pure](https://github.com/rafaelrinaldi/pure) - Support for bare Fish and various framework ([Oh-My-Fish](https://github.com//oh-my-fish/oh-my-fish), [Fisherman](https://github.com//fisherman/fisherman), and [Wahoo](https://github.com//bucaran/wahoo)).
- **Rust**
- [xcambar/purs](https://github.com/xcambar/purs) - Pure-inspired prompt in Rust.
- **Go**
- [talal/mimir](https://github.com/talal/mimir) - Pure-inspired prompt in Go with Kubernetes and OpenStack cloud support. Not intended to have feature parity.
- **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) | [Mathias Fredriksson](https://github.com/mafredri)

BIN
pure/screenshot-title-cmd.png View File

Before After
Width: 500  |  Height: 286  |  Size: 24 KiB

BIN
pure/screenshot.png View File

Before After
Width: 1728  |  Height: 1116  |  Size: 70 KiB

+ 0
- 4
z/Makefile View File

@@ -1,4 +0,0 @@
readme:
@groff -man -Tascii z.1 | col -bx

.PHONY: readme

+ 0
- 146
z/README View File

@@ -1,146 +0,0 @@
Z(1) User Commands Z(1)



NAME
z - jump around

SYNOPSIS
z [-chlrtx] [regex1 regex2 ... regexn]

AVAILABILITY
bash, zsh

DESCRIPTION
Tracks your most used directories, based on 'frecency'.

After a short learning phase, z will take you to the most 'frecent'
directory that matches ALL of the regexes given on the command line, in
order.

For example, z foo bar would match /foo/bar but not /bar/foo.

OPTIONS
-c restrict matches to subdirectories of the current directory

-e echo the best match, don't cd

-h show a brief help message

-l list only

-r match by rank only

-t match by recent access only

-x remove the current directory from the datafile

EXAMPLES
z foo cd to most frecent dir matching foo

z foo bar cd to most frecent dir matching foo, then bar

z -r foo cd to highest ranked dir matching foo

z -t foo cd to most recently accessed dir matching foo

z -l foo list all dirs matching foo (by frecency)

NOTES
Installation:
Put something like this in your $HOME/.bashrc or $HOME/.zshrc:

. /path/to/z.sh

cd around for a while to build up the db.

PROFIT!!

Optionally:
Set $_Z_CMD to change the command name (default z).
Set $_Z_DATA to change the datafile (default $HOME/.z).
Set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
Set $_Z_NO_PROMPT_COMMAND to handle PROMPT_COMMAND/precmd your-
self.
Set $_Z_EXCLUDE_DIRS to an array of directory trees to exclude.
Set $_Z_OWNER to allow usage when in 'sudo -s' mode.
(These settings should go in .bashrc/.zshrc before the line
added above.)
Install the provided man page z.1 somewhere in your MANPATH,
like /usr/local/man/man1.

Aging:
The rank of directories maintained by z undergoes aging based on a sim-
ple formula. The rank of each entry is incremented every time it is
accessed. When the sum of ranks is over 9000, all ranks are multiplied
by 0.99. Entries with a rank lower than 1 are forgotten.

Frecency:
Frecency is a portmanteau of 'recent' and 'frequency'. It is a weighted
rank that depends on how often and how recently something occurred. As
far as I know, Mozilla came up with the term.

To z, a directory that has low ranking but has been accessed recently
will quickly have higher rank than a directory accessed frequently a
long time ago.

Frecency is determined at runtime.

Common:
When multiple directories match all queries, and they all have a common
prefix, z will cd to the shortest matching directory, without regard to
priority. This has been in effect, if undocumented, for quite some
time, but should probably be configurable or reconsidered.

Tab Completion:
z supports tab completion. After any number of arguments, press TAB to
complete on directories that match each argument. Due to limitations of
the completion implementations, only the last argument will be com-
pleted in the shell.

Internally, z decides you've requested a completion if the last argu-
ment passed is an absolute path to an existing directory. This may
cause unexpected behavior if the last argument to z begins with /.

ENVIRONMENT
A function _z() is defined.

The contents of the variable $_Z_CMD is aliased to _z 2>&1. If not set,
$_Z_CMD defaults to z.

The environment variable $_Z_DATA can be used to control the datafile
location. If it is not defined, the location defaults to $HOME/.z.

The environment variable $_Z_NO_RESOLVE_SYMLINKS can be set to prevent
resolving of symlinks. If it is not set, symbolic links will be
resolved when added to the datafile.

In bash, z appends a command to the PROMPT_COMMAND environment variable
to maintain its database. In zsh, z appends a function _z_precmd to the
precmd_functions array.

The environment variable $_Z_NO_PROMPT_COMMAND can be set if you want
to handle PROMPT_COMMAND or precmd yourself.

The environment variable $_Z_EXCLUDE_DIRS can be set to an array of
directory trees to exclude from tracking. $HOME is always excluded.
Directories must be full paths without trailing slashes.

The environment variable $_Z_OWNER can be set to your username, to
allow usage of z when your sudo environment keeps $HOME set.

FILES
Data is stored in $HOME/.z. This can be overridden by setting the
$_Z_DATA environment variable. When initialized, z will raise an error
if this path is a directory, and not function correctly.

A man page (z.1) is provided.

SEE ALSO
regex(7), pushd, popd, autojump, cdargs

Please file bugs at https://github.com/rupa/z/



z January 2013 Z(1)

+ 0
- 170
z/z.1 View File

@@ -1,170 +0,0 @@
.TH "Z" "1" "January 2013" "z" "User Commands"
.SH
NAME
z \- jump around
.SH
SYNOPSIS
z [\-chlrtx] [regex1 regex2 ... regexn]
.SH
AVAILABILITY
bash, zsh
.SH
DESCRIPTION
Tracks your most used directories, based on 'frecency'.
.P
After a short learning phase, \fBz\fR will take you to the most 'frecent'
directory that matches ALL of the regexes given on the command line, in order.

For example, \fBz foo bar\fR would match \fB/foo/bar\fR but not \fB/bar/foo\fR.
.SH
OPTIONS
.TP
\fB\-c\fR
restrict matches to subdirectories of the current directory
.TP
\fB\-e\fR
echo the best match, don't cd
.TP
\fB\-h\fR
show a brief help message
.TP
\fB\-l\fR
list only
.TP
\fB\-r\fR
match by rank only
.TP
\fB\-t\fR
match by recent access only
.TP
\fB\-x\fR
remove the current directory from the datafile
.SH EXAMPLES
.TP 14
\fBz foo\fR
cd to most frecent dir matching foo
.TP 14
\fBz foo bar\fR
cd to most frecent dir matching foo, then bar
.TP 14
\fBz -r foo\fR
cd to highest ranked dir matching foo
.TP 14
\fBz -t foo\fR
cd to most recently accessed dir matching foo
.TP 14
\fBz -l foo\fR
list all dirs matching foo (by frecency)
.SH
NOTES
.SS
Installation:
.P
Put something like this in your \fB$HOME/.bashrc\fR or \fB$HOME/.zshrc\fR:
.RS
.P
\fB. /path/to/z.sh\fR
.RE
.P
\fBcd\fR around for a while to build up the db.
.P
PROFIT!!
.P
Optionally:
.RS
Set \fB$_Z_CMD\fR to change the command name (default \fBz\fR).
.RE
.RS
Set \fB$_Z_DATA\fR to change the datafile (default \fB$HOME/.z\fR).
.RE
.RS
Set \fB$_Z_NO_RESOLVE_SYMLINKS\fR to prevent symlink resolution.
.RE
.RS
Set \fB$_Z_NO_PROMPT_COMMAND\fR to handle \fBPROMPT_COMMAND/precmd\fR yourself.
.RE
.RS
Set \fB$_Z_EXCLUDE_DIRS\fR to an array of directory trees to exclude.
.RE
.RS
Set \fB$_Z_OWNER\fR to allow usage when in 'sudo -s' mode.
.RE
.RS
(These settings should go in .bashrc/.zshrc before the line added above.)
.RE
.RS
Install the provided man page \fBz.1\fR somewhere in your \f$MANPATH, like
\fB/usr/local/man/man1\fR.
.RE
.SS
Aging:
The rank of directories maintained by \fBz\fR undergoes aging based on a simple
formula. The rank of each entry is incremented every time it is accessed. When
the sum of ranks is over 9000, all ranks are multiplied by 0.99. Entries with a
rank lower than 1 are forgotten.
.SS
Frecency:
Frecency is a portmanteau of 'recent' and 'frequency'. It is a weighted rank
that depends on how often and how recently something occurred. As far as I
know, Mozilla came up with the term.
.P
To \fBz\fR, a directory that has low ranking but has been accessed recently
will quickly have higher rank than a directory accessed frequently a long time
ago.
.P
Frecency is determined at runtime.
.SS
Common:
When multiple directories match all queries, and they all have a common prefix,
\fBz\fR will cd to the shortest matching directory, without regard to priority.
This has been in effect, if undocumented, for quite some time, but should
probably be configurable or reconsidered.
.SS
Tab Completion:
\fBz\fR supports tab completion. After any number of arguments, press TAB to
complete on directories that match each argument. Due to limitations of the
completion implementations, only the last argument will be completed in the
shell.
.P
Internally, \fBz\fR decides you've requested a completion if the last argument
passed is an absolute path to an existing directory. This may cause unexpected
behavior if the last argument to \fBz\fR begins with \fB/\fR.
.SH
ENVIRONMENT
A function \fB_z()\fR is defined.
.P
The contents of the variable \fB$_Z_CMD\fR is aliased to \fB_z 2>&1\fR. If not
set, \fB$_Z_CMD\fR defaults to \fBz\fR.
.P
The environment variable \fB$_Z_DATA\fR can be used to control the datafile
location. If it is not defined, the location defaults to \fB$HOME/.z\fR.
.P
The environment variable \fB$_Z_NO_RESOLVE_SYMLINKS\fR can be set to prevent
resolving of symlinks. If it is not set, symbolic links will be resolved when
added to the datafile.
.P
In bash, \fBz\fR appends a command to the \fBPROMPT_COMMAND\fR environment
variable to maintain its database. In zsh, \fBz\fR appends a function
\fB_z_precmd\fR to the \fBprecmd_functions\fR array.
.P
The environment variable \fB$_Z_NO_PROMPT_COMMAND\fR can be set if you want to
handle \fBPROMPT_COMMAND\fR or \fBprecmd\fR yourself.
.P
The environment variable \fB$_Z_EXCLUDE_DIRS\fR can be set to an array of
directory trees to exclude from tracking. \fB$HOME\fR is always excluded.
Directories must be full paths without trailing slashes.
.P
The environment variable \fB$_Z_OWNER\fR can be set to your username, to
allow usage of \fBz\fR when your sudo environment keeps \fB$HOME\fR set.
.SH
FILES
Data is stored in \fB$HOME/.z\fR. This can be overridden by setting the
\fB$_Z_DATA\fR environment variable. When initialized, \fBz\fR will raise an
error if this path is a directory, and not function correctly.
.P
A man page (\fBz.1\fR) is provided.
.SH
SEE ALSO
regex(7), pushd, popd, autojump, cdargs
.P
Please file bugs at https://github.com/rupa/z/

+ 0
- 253
z/z.sh View File

@@ -1,253 +0,0 @@
# Copyright (c) 2009 rupa deadwyler. Licensed under the WTFPL license, Version 2

# maintains a jump-list of the directories you actually use
#
# INSTALL:
# * put something like this in your .bashrc/.zshrc:
# . /path/to/z.sh
# * cd around for a while to build up the db
# * PROFIT!!
# * optionally:
# set $_Z_CMD in .bashrc/.zshrc to change the command (default z).
# set $_Z_DATA in .bashrc/.zshrc to change the datafile (default ~/.z).
# set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
# set $_Z_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself.
# set $_Z_EXCLUDE_DIRS to an array of directories to exclude.
# set $_Z_OWNER to your username if you want use z while sudo with $HOME kept
#