This commit is contained in:
Andrey Anurin
2016-05-16 23:46:33 -07:00
commit 916d13f93e
412 changed files with 37846 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
# agnoster.zsh-theme
A ZSH theme optimized for people who use:
- Solarized
- Git
- Unicode-compatible fonts and terminals (I use iTerm2 + Menlo)
For Mac users, I highly recommend iTerm 2 + Solarized Dark
# Compatibility
**NOTE:** In all likelihood, you will need to install a [Powerline-patched font](https://github.com/Lokaltog/powerline-fonts) for this theme to render correctly.
To test if your terminal and font support it, check that all the necessary characters are supported by copying the following command to your terminal: `echo "\ue0b0 \u00b1 \ue0a0 \u27a6 \u2718 \u26a1 \u2699"`. The result should look like this:
![Character Example](https://gist.githubusercontent.com/agnoster/3712874/raw/characters.png)
## What does it show?
- If the previous command failed (✘)
- User @ Hostname (if user is not DEFAULT_USER, which can then be set in your profile)
- Git status
- Branch () or detached head (➦)
- Current branch / SHA1 in detached head state
- Dirty working directory (±, color change)
- Working directory
- Elevated (root) privileges (⚡)
![Screenshot](https://gist.githubusercontent.com/agnoster/3712874/raw/screenshot.png)
## Future Work
I don't want to clutter it up too much, but I am toying with the idea of adding RVM (ruby version) and n (node.js version) display.
It's currently hideously slow, especially inside a git repo. I guess it's not overly so for comparable themes, but it bugs me, and I'd love to hear ideas about how to improve the performance.
Would be nice for the code to be a bit more sane and re-usable. Something to easily append a section with a given FG/BG, and add the correct opening and closing.
Also the dependency on a powerline-patched font is regrettable, but there's really no way to get that effect without it. Ideally there would be a way to check for compatibility, or maybe even fall back to one of the similar unicode glyphs.

View File

@@ -0,0 +1,153 @@
# vim:ft=zsh ts=2 sw=2 sts=2
#
# agnoster's Theme - https://gist.github.com/3712874
# A Powerline-inspired theme for ZSH
#
# # README
#
# In order for this theme to render correctly, you will need a
# [Powerline-patched font](https://gist.github.com/1595572).
#
# In addition, I recommend the
# [Solarized theme](https://github.com/altercation/solarized/) and, if you're
# using it on Mac OS X, [iTerm 2](http://www.iterm2.com/) over Terminal.app -
# it has significantly better color fidelity.
#
# # Goals
#
# The aim of this theme is to only show you *relevant* information. Like most
# prompts, it will only show git information when in a git working directory.
# However, it goes a step further: everything from the current user and
# hostname to whether the last call exited with an error to whether background
# jobs are running in this shell will all be displayed automatically when
# appropriate.
### Segment drawing
# A few utility functions to make it easy and re-usable to draw segmented prompts
CURRENT_BG='NONE'
PRIMARY_FG=black
# Characters
SEGMENT_SEPARATOR="\ue0b0"
PLUSMINUS="\u00b1"
BRANCH="\ue0a0"
DETACHED="\u27a6"
CROSS="\u2718"
LIGHTNING="\u26a1"
GEAR="\u2699"
# Begin a segment
# Takes two arguments, background and foreground. Both can be omitted,
# rendering default background/foreground.
prompt_segment() {
local bg fg
[[ -n $1 ]] && bg="%K{$1}" || bg="%k"
[[ -n $2 ]] && fg="%F{$2}" || fg="%f"
if [[ $CURRENT_BG != 'NONE' && $1 != $CURRENT_BG ]]; then
print -n "%{$bg%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR%{$fg%}"
else
print -n "%{$bg%}%{$fg%}"
fi
CURRENT_BG=$1
[[ -n $3 ]] && print -n $3
}
# End the prompt, closing any open segments
prompt_end() {
if [[ -n $CURRENT_BG ]]; then
print -n "%{%k%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR"
else
print -n "%{%k%}"
fi
print -n "%{%f%}"
CURRENT_BG=''
}
### Prompt components
# Each component will draw itself, and hide itself if no information needs to be shown
# Context: user@hostname (who am I and where am I)
prompt_context() {
local user=`whoami`
if [[ "$user" != "$DEFAULT_USER" || -n "$SSH_CONNECTION" ]]; then
prompt_segment $PRIMARY_FG default " %(!.%{%F{yellow}%}.)$user@%m "
fi
}
# Git: branch/detached head, dirty status
prompt_git() {
local color ref
is_dirty() {
test -n "$(git status --porcelain --ignore-submodules)"
}
ref="$vcs_info_msg_0_"
if [[ -n "$ref" ]]; then
if is_dirty; then
color=yellow
ref="${ref} $PLUSMINUS"
else
color=green
ref="${ref} "
fi
if [[ "${ref/.../}" == "$ref" ]]; then
ref="$BRANCH $ref"
else
ref="$DETACHED ${ref/.../}"
fi
prompt_segment $color $PRIMARY_FG
print -Pn " $ref"
fi
}
# Dir: current working directory
prompt_dir() {
prompt_segment blue $PRIMARY_FG ' %~ '
}
# Status:
# - was there an error
# - am I root
# - are there background jobs?
prompt_status() {
local symbols
symbols=()
[[ $RETVAL -ne 0 ]] && symbols+="%{%F{red}%}$CROSS"
[[ $UID -eq 0 ]] && symbols+="%{%F{yellow}%}$LIGHTNING"
[[ $(jobs -l | wc -l) -gt 0 ]] && symbols+="%{%F{cyan}%}$GEAR"
[[ -n "$symbols" ]] && prompt_segment $PRIMARY_FG default " $symbols "
}
## Main prompt
prompt_agnoster_main() {
RETVAL=$?
CURRENT_BG='NONE'
prompt_status
prompt_context
prompt_dir
prompt_git
prompt_end
}
prompt_agnoster_precmd() {
vcs_info
PROMPT='%{%f%b%k%}$(prompt_agnoster_main) '
}
prompt_agnoster_setup() {
autoload -Uz add-zsh-hook
autoload -Uz vcs_info
prompt_opts=(cr subst percent)
add-zsh-hook precmd prompt_agnoster_precmd
zstyle ':vcs_info:*' enable git
zstyle ':vcs_info:*' check-for-changes false
zstyle ':vcs_info:git*' formats '%b'
zstyle ':vcs_info:git*' actionformats '%b (%a)'
}
prompt_agnoster_setup "$@"

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -0,0 +1,60 @@
Powerline for [Prezto](http://github.com/sorin-ionescu/prezto) ZSH
## Features
* Single line prompt
* Git branch info (current branch and modified states)
* Time since last commit
* RVM current ruby version / gemset
![Example](https://raw.github.com/davidjrice/prezto_powerline/master/prompt.png)
## Dependencies
* [skwp/dotfiles](http://github.com/skwp/dotfiles) *(YADR)*
* [prezto](https://github.com/sorin-ionescu/prezto) (included by YADR)
## Installation
# Install YADR
git clone https://github.com/skwp/dotfiles ~/.yadr
cd ~/.yadr && rake install
# Create a ~/.secrets file (required by YADR)
touch ~/.secrets
# Install the prompt
curl https://raw.github.com/davidjrice/prezto_powerline/master/prompt_powerline_setup > ~/.zsh.prompts/prompt_powerline_setup
# Install Solarized
git clone https://github.com/altercation/solarized
cd solarized
# e.g. for iTerm
cd iterm2-colors-solarized/
open Solarized\ Dark.itermcolors
# this should load the colours for iTerm, but they are not configured yet
# in iTerm2 open preferences
# profiles > default > colours > load presets > Solarized Dark
# profiles > default > terminal > report terminal type > "xterm-256color"
# Enable
echo "prompt powerline" > ~/.zsh.after/prompt.zsh
## Inspiration
This prompt is inspired by:
* [oh-my-zsh-powerline-theme](http://github.com/jeremyFreeAgent/oh-my-zsh-powerline-theme)
* [robbl oh-my-zsh theme](http://github.com/robbl/oh-my-zsh-config)
* [SKWP prezto theme](http://github.com/skwp/dotfiles/blob/master/zsh/prezto-themes/prompt_skwp_setup)
## TODO
* Moar configurable
* Extract functions to Prezto modules?
* Use better Prezto best practices...?
* Handle NVM version info?

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

View File

@@ -0,0 +1,185 @@
#
# A ZSH theme based on a combination of the skwp prezto theme and the robl ohmyzsh theme.
# * RVM info shown on the right
# * Git branch info on the left
# * Single line prompt
# * Time since last commit on the left
# * Time in place of user@hostname
#
# Authors:
# David Rice <me@davidjrice.co.uk>
ZSH_THEME_REP_TIME_SINCE_COMMIT_SHORT="%{$fg[green]%}"
ZSH_THEME_REP_TIME_SINCE_COMMIT_MEDIUM="%{$fg[yellow]%}"
ZSH_THEME_REP_TIME_SINCE_COMMIT_LONG="%{$fg[red]%}"
ZSH_THEME_REP_TIME_SINCE_COMMIT_NEUTRAL="%{$fg[cyan]%}"
# returns the time since last git commit
function git_time_details() {
# only proceed if there is actually a git repository
if `git rev-parse --git-dir > /dev/null 2>&1`; then
# only proceed if there is actually a commit
if [[ $(git log 2>&1 > /dev/null | grep -c "^fatal: bad default revision") == 0 ]]; then
# get the last commit hash
# lc_hash=`git log --pretty=format:'%h' -1 2> /dev/null`
# get the last commit time
lc_time=`git log --pretty=format:'%at' -1 2> /dev/null`
now=`date +%s`
seconds_since_last_commit=$((now-lc_time))
lc_time_since=`time_since_commit $seconds_since_last_commit`
echo "$lc_time_since"
else
echo ""
fi
else
echo ""
fi
}
# returns the time by given seconds
function time_since_commit() {
seconds_since_last_commit=$(($1 + 0))
# totals
MINUTES=$((seconds_since_last_commit / 60))
HOURS=$((seconds_since_last_commit/3600))
# sub-hours and sub-minutes
DAYS=$((seconds_since_last_commit / 86400))
SUB_HOURS=$((HOURS % 24))
SUB_MINUTES=$((MINUTES % 60))
if [ "$HOURS" -gt 24 ]; then
echo "${DAYS}d${SUB_HOURS}h${SUB_MINUTES}m"
elif [ "$MINUTES" -gt 60 ]; then
echo "${HOURS}h${SUB_MINUTES}m"
else
echo "${MINUTES}m"
fi
}
function rvm_info_for_prompt {
if [[ -d ~/.rvm/ ]]; then
local ruby_version=$(~/.rvm/bin/rvm-prompt)
if [ -n "$ruby_version" ]; then
echo "$ruby_version"
fi
else
echo ""
fi
}
function prompt_powerline_precmd {
# Check for untracked files or updated submodules since vcs_info doesn't.
if [[ ! -z $(git ls-files --other --exclude-standard 2> /dev/null) ]]; then
fmt_branch="%b%u%c${__PROMPT_SKWP_COLORS[4]}●%f"
else
fmt_branch="%b%u%c"
fi
zstyle ':vcs_info:*:prompt:*' formats "${fmt_branch}"
vcs_info 'prompt'
RVM_PRECMD_INFO=$(rvm_info_for_prompt)
# zstyle ':prezto:module:ruby' rvm '%r'
}
function prompt_powerline_setup {
setopt LOCAL_OPTIONS
unsetopt XTRACE KSH_ARRAYS
prompt_opts=(cr percent subst)
autoload -Uz add-zsh-hook
autoload -Uz vcs_info
add-zsh-hook precmd prompt_powerline_precmd
# Use extended color pallete if available.
if [[ $TERM = *256color* || $TERM = *rxvt* ]]; then
__PROMPT_SKWP_COLORS=(
"%F{81}" # turquoise
"%F{166}" # orange
"%F{135}" # purple
"%F{161}" # hotpink
"%F{118}" # limegreen
)
else
__PROMPT_SKWP_COLORS=(
"%F{cyan}"
"%F{yellow}"
"%F{magenta}"
"%F{red}"
"%F{green}"
)
fi
# Enable VCS systems you use.
zstyle ':vcs_info:*' enable bzr git hg svn
# check-for-changes can be really slow.
# You should disable it if you work with large repositories.
zstyle ':vcs_info:*:prompt:*' check-for-changes true
# Formats:
# %b - branchname
# %u - unstagedstr (see below)
# %c - stagedstr (see below)
# %a - action (e.g. rebase-i)
# %R - repository path
# %S - path in the repository
# %n - user
# %m - machine hostname
# local fmt_branch="(${__PROMPT_SKWP_COLORS[1]}%b%f%u%c)"
local fmt_branch="${__PROMPT_SKWP_COLORS[2]}%b%f%u%c"
local fmt_action="${__PROMPT_SKWP_COLORS[5]}%a%f"
local fmt_unstaged="${__PROMPT_SKWP_COLORS[2]}●%f"
local fmt_staged="${__PROMPT_SKWP_COLORS[5]}●%f"
zstyle ':vcs_info:*:prompt:*' unstagedstr "${fmt_unstaged}"
zstyle ':vcs_info:*:prompt:*' stagedstr "${fmt_staged}"
zstyle ':vcs_info:*:prompt:*' actionformats "${fmt_branch}${fmt_action}"
zstyle ':vcs_info:*:prompt:*' formats "${fmt_branch}"
zstyle ':vcs_info:*:prompt:*' nvcsformats ""
# SPLIT RVM PROMPT INFO
# TODO: should assign this to local variable? somehow doesn't work correctly.
rvm_split=("${(s/@/)$(rvm_info_for_prompt)}")
# if [ "$POWERLINE_RIGHT_B" = "" ]; then
# POWERLINE_RIGHT_B=%D{%H:%M:%S}
local powerline_right_b=$rvm_split[1]
# fi
# if [ "$POWERLINE_RIGHT_A" = "" ]; then
local powerline_right_a=$rvm_split[2]
# fi
# Setup powerline style colouring
POWERLINE_COLOR_BG_GRAY=%K{240}
POWERLINE_COLOR_BG_LIGHT_GRAY=%K{240}
POWERLINE_COLOR_BG_WHITE=%K{255}
POWERLINE_COLOR_FG_GRAY=%F{240}
POWERLINE_COLOR_FG_LIGHT_GRAY=%F{240}
POWERLINE_COLOR_FG_WHITE=%F{255}
POWERLINE_SEPARATOR=$'\u2b80'
POWERLINE_R_SEPARATOR=$'\u2b82'
POWERLINE_LEFT_A="%K{green}%F{white} %~ %k%f%F{green}%K{blue}"$POWERLINE_SEPARATOR
POWERLINE_LEFT_B="%k%f%F{white}%K{blue} "'${vcs_info_msg_0_}'" %k%f%F{blue}%K{black}"$POWERLINE_SEPARATOR
POWERLINE_LEFT_C=" %k%f%F{white}%K{black}"'$(git_time_details)'" %k%f%F{black}"$POWERLINE_SEPARATOR"%f "
PROMPT=$POWERLINE_LEFT_A$POWERLINE_LEFT_B$POWERLINE_LEFT_C
# RPROMPT=$POWERLINE_COLOR_FG_WHITE$POWERLINE_R_SEPARATOR"%f$POWERLINE_COLOR_BG_WHITE $POWERLINE_COLOR_FG_GRAY$powerline_right_b "$POWERLINE_R_SEPARATOR"%f%k$POWERLINE_COLOR_BG_GRAY$POWERLINE_COLOR_FG_WHITE $powerline_right_a %f%k"
# RPROMPT=$POWERLINE_COLOR_FG_WHITE$POWERLINE_R_SEPARATOR"%f$POWERLINE_COLOR_BG_WHITE $POWERLINE_COLOR_FG_GRAY"'$powerline_right_b'" "$POWERLINE_R_SEPARATOR"%f%k$POWERLINE_COLOR_BG_GRAY$POWERLINE_COLOR_FG_WHITE "'$powerline_right_a'" %f%k"
RPROMPT=$POWERLINE_COLOR_FG_WHITE$POWERLINE_R_SEPARATOR"%f$POWERLINE_COLOR_BG_WHITE $POWERLINE_COLOR_FG_GRAY"'$(rvm_info_for_prompt)'" "
}
prompt_powerline_setup "$@"

View File

@@ -0,0 +1,15 @@
root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[package.json]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false

View File

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

View File

@@ -0,0 +1,26 @@
# 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"
}

View File

@@ -0,0 +1,276 @@
#!/usr/bin/env zsh
#
# zsh-async
#
# version: 1.0.0
# author: Mathias Fredriksson
# url: https://github.com/mafredri/zsh-async
#
# Wrapper for jobs executed by the async worker, gives output in parseable format with execution time
_async_job() {
# Store start time as double precision (+E disables scientific notation)
float -F duration=$EPOCHREALTIME
# Run the command
#
# What is happening here is that we are assigning stdout, stderr and ret to
# variables, and then we are printing out the variable assignment through
# typeset -p. This way when we run eval we get something along the lines of:
# eval "
# typeset stdout=' M async.test.sh\n M async.zsh'
# typeset ret=0
# typeset stderr=''
# "
unset stdout stderr ret
eval "$(
{
stdout=$(eval "$@")
ret=$?
typeset -p stdout ret
} 2> >(stderr=$(cat); typeset -p stderr)
)"
# Calculate duration
duration=$(( EPOCHREALTIME - duration ))
# stip all null-characters from stdout and stderr
stdout="${stdout//$'\0'/}"
stderr="${stderr//$'\0'/}"
# if ret is missing for some unknown reason, set it to -1 to indicate we
# have run into a bug
ret=${ret:--1}
# Grab mutex lock
read -ep >/dev/null
# return output (<job_name> <return_code> <stdout> <duration> <stderr>)
print -r -N -n -- "$1" "$ret" "$stdout" "$duration" "$stderr"$'\0'
# Unlock mutex
print -p "t"
}
# The background worker manages all tasks and runs them without interfering with other processes
_async_worker() {
local -A storage
local unique=0
# Process option parameters passed to worker
while getopts "np:u" opt; do
case "$opt" in
# Use SIGWINCH since many others seem to cause zsh to freeze, e.g. ALRM, INFO, etc.
n) trap 'kill -WINCH $ASYNC_WORKER_PARENT_PID' CHLD;;
p) ASYNC_WORKER_PARENT_PID=$OPTARG;;
u) unique=1;;
esac
done
# Create a mutex for writing to the terminal through coproc
coproc cat
# Insert token into coproc
print -p "t"
while read -r cmd; do
# Separate on spaces into an array
cmd=(${=cmd})
local job=$cmd[1]
# Check for non-job commands sent to worker
case "$job" in
_killjobs)
kill -KILL ${${(v)jobstates##*:*:}%\=*} &>/dev/null
continue
;;
esac
# 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
# run task in background
_async_job $cmd &
# store pid because zsh job manager is extremely unflexible (show jobname as non-unique '$job')...
storage[$job]=$!
done
}
#
# Get results from finnished 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.
#
# 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
#
async_process_results() {
integer count=0
local worker=$1
local callback=$2
local -a items
local IFS=$'\0'
typeset -gA ASYNC_PROCESS_BUFFER
# Read output from zpty and parse it if available
while zpty -rt "$worker" line 2>/dev/null; do
# Remove unwanted \r from output
ASYNC_PROCESS_BUFFER[$worker]+=${line//$'\r'$'\n'/$'\n'}
# Split buffer on null characters, preserve empty elements
items=("${(@)=ASYNC_PROCESS_BUFFER[$worker]}")
# Remove last element since it's due to the return string separator structure
items=("${(@)items[1,${#items}-1]}")
# Continue until we receive all information
(( ${#items} % 5 )) && continue
# Work through all results
while (( ${#items} > 0 )); do
"$callback" "${(@)=items[1,5]}"
shift 5 items
count+=1
done
# Empty the buffer
ASYNC_PROCESS_BUFFER[$worker]=""
done
# If we processed any results, return success
(( $count )) && return 0
# No results were processed
return 1
}
#
# Start a new asynchronous job on specified worker, assumes the worker is running.
#
# usage:
# async_job <worker_name> <my_function> [<function_params>]
#
async_job() {
local worker=$1; shift
zpty -w "$worker" "$@"
}
# This function traps notification signals and calls all registered callbacks
_async_notify_trap() {
for k in ${(k)ASYNC_CALLBACKS}; do
async_process_results "${k}" "${ASYNC_CALLBACKS[$k]}"
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() {
typeset -gA ASYNC_CALLBACKS
local worker=$1; shift
ASYNC_CALLBACKS[$worker]="$*"
trap '_async_notify_trap' WINCH
}
#
# 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() {
local worker=$1; shift
# Check if the worker exists
zpty -t "$worker" &>/dev/null || return 1
# Send kill command to worker
zpty -w "$worker" "_killjobs"
# Clear all output buffers
while zpty -r "$worker" line; do true; done
# Clear any partial buffers
typeset -gA ASYNC_PROCESS_BUFFER
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() {
local worker=$1; shift
zpty -t "$worker" &>/dev/null || zpty -b "$worker" _async_worker -p $$ "$@" || async_stop_worker "$worker"
}
#
# 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() {
local ret=0
for worker in "$@"; do
async_unregister_callback "$worker"
zpty -d "$worker" 2>/dev/null || ret=$?
done
return $ret
}
#
# Initialize the required modules for zsh-async. To be called before using the zsh-async library.
#
# usage:
# async_init
#
async_init() {
zmodload zsh/zpty
zmodload zsh/datetime
}
async() {
async_init
}
async "$@"

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
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.

View File

@@ -0,0 +1,43 @@
{
"name": "pure-prompt",
"version": "1.2.0",
"description": "Pretty, minimal and fast ZSH prompt",
"license": "MIT",
"repository": "sindresorhus/pure",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"maintainers": [
{
"name": "Mathias Fredriksson",
"url": "github.com/mafredri"
}
],
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"postinstall": "dest=/usr/local/share/zsh/site-functions/; mkdir -p $dest && ln -sf \"$PWD/pure.zsh\" $dest/prompt_pure_setup && ln -sf \"$PWD/async.zsh\" $dest/async || echo 'Could not automagically symlink the prompt. Check out the readme on how to do it manually: https://github.com/sindresorhus/pure#manually'"
},
"files": [
"pure.zsh",
"async.zsh"
],
"keywords": [
"zsh",
"zshell",
"sh",
"shell",
"bash",
"pure",
"prompt",
"theme",
"git",
"async",
"fast",
"minimal",
"pretty"
]
}

View File

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

View File

@@ -0,0 +1,348 @@
# 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 variable as specified by caller
typeset -g "${var}"="${human}"
}
# stores (into prompt_pure_cmd_exec_time) the exec time of the last command if set threshold was exceeded
prompt_pure_check_cmd_exec_time() {
integer elapsed
(( elapsed = EPOCHSECONDS - ${prompt_pure_cmd_timestamp:-$EPOCHSECONDS} ))
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_clear_screen() {
# enable output to terminal
zle -I
# clear screen and move cursor to (0, 0)
print -n '\e[2J\e[0;0H'
# print preprompt
prompt_pure_preprompt_render precmd
}
prompt_pure_check_git_arrows() {
# reset git arrows
prompt_pure_git_arrows=
# check if there is an upstream configured for this branch
command git rev-parse --abbrev-ref @'{u}' &>/dev/null || return
local arrow_status
# check git left and right arrow_status
arrow_status="$(command git rev-list --left-right --count HEAD...@'{u}' 2>/dev/null)"
# exit if the command failed
(( !$? )) || return
# left and right are tab-separated, split on tab and store as array
arrow_status=(${(ps:\t:)arrow_status})
local arrows left=${arrow_status[1]} right=${arrow_status[2]}
(( ${right:-0} > 0 )) && arrows+="${PURE_GIT_DOWN_ARROW:-}"
(( ${left:-0} > 0 )) && arrows+="${PURE_GIT_UP_ARROW:-}"
[[ -n $arrows ]] && prompt_pure_git_arrows=" ${arrows}"
}
prompt_pure_set_title() {
# tell the terminal we are setting the title
print -n '\e]0;'
# show hostname if connected through ssh
[[ -n $SSH_CONNECTION ]] && print -Pn '(%m) '
case $1 in
expand-prompt)
print -Pn $2;;
ignore-escape)
print -rn $2;;
esac
# end set title
print -n '\a'
}
prompt_pure_preexec() {
prompt_pure_cmd_timestamp=$EPOCHSECONDS
# shows the current dir and executed command in the title while a process is active
prompt_pure_set_title 'ignore-escape' "$PWD:t: $2"
}
# string length ignoring ansi escapes
prompt_pure_string_length_to_var() {
local str=$1 var=$2 length
# perform expansion on str and check length
length=$(( ${#${(S%%)str//(\%([KF1]|)\{*\}|\%[Bbkf])}} ))
# store string length in variable as specified by caller
typeset -g "${var}"="${length}"
}
prompt_pure_preprompt_render() {
# check that no command is currently running, the preprompt will otherwise be rendered in the wrong place
[[ -n ${prompt_pure_cmd_timestamp+x} && "$1" != "precmd" ]] && return
# set color for git branch/dirty status, change color if dirty checking has been delayed
local git_color=242
[[ -n ${prompt_pure_git_last_dirty_check_timestamp+x} ]] && git_color=red
# construct preprompt, beginning with path
local preprompt="%F{blue}%~%f"
# git info
preprompt+="%F{$git_color}${vcs_info_msg_0_}${prompt_pure_git_dirty}%f"
# git pull/push arrows
preprompt+="%F{cyan}${prompt_pure_git_arrows}%f"
# username and machine if applicable
preprompt+=$prompt_pure_username
# execution time
preprompt+="%F{yellow}${prompt_pure_cmd_exec_time}%f"
# if executing through precmd, do not perform fancy terminal editing
if [[ "$1" == "precmd" ]]; then
print -P "\n${preprompt}"
else
# only redraw if preprompt has changed
[[ "${prompt_pure_last_preprompt}" != "${preprompt}" ]] || return
# calculate length of preprompt and store it locally in preprompt_length
integer preprompt_length lines
prompt_pure_string_length_to_var "${preprompt}" "preprompt_length"
# calculate number of preprompt lines for redraw purposes
(( lines = ( preprompt_length - 1 ) / COLUMNS + 1 ))
# calculate previous preprompt lines to figure out how the new preprompt should behave
integer last_preprompt_length last_lines
prompt_pure_string_length_to_var "${prompt_pure_last_preprompt}" "last_preprompt_length"
(( last_lines = ( last_preprompt_length - 1 ) / COLUMNS + 1 ))
# clr_prev_preprompt erases visual artifacts from previous preprompt
local clr_prev_preprompt
if (( last_lines > lines )); then
# move cursor up by last_lines, clear the line and move it down by one line
clr_prev_preprompt="\e[${last_lines}A\e[2K\e[1B"
while (( last_lines - lines > 1 )); do
# clear the line and move cursor down by one
clr_prev_preprompt+='\e[2K\e[1B'
(( last_lines-- ))
done
# move cursor into correct position for preprompt update
clr_prev_preprompt+="\e[${lines}B"
# create more space for preprompt if new preprompt has more lines than last
elif (( last_lines < lines )); then
# move cursor using newlines because ansi cursor movement can't push the cursor beyond the last line
printf $'\n'%.0s {1..$(( lines - last_lines ))}
# redraw the prompt since it has been moved by print
zle && zle .reset-prompt
fi
# disable clearing of line if last char of preprompt is last column of terminal
local clr='\e[K'
(( COLUMNS * lines == preprompt_length )) && clr=
# modify previous preprompt
print -Pn "\e7${clr_prev_preprompt}\e[${lines}A\e[1G${preprompt}${clr}\e8"
fi
# store previous preprompt for comparison
prompt_pure_last_preprompt=$preprompt
}
prompt_pure_precmd() {
# check exec time and store it in a variable
prompt_pure_check_cmd_exec_time
# by making sure that prompt_pure_cmd_timestamp is defined here the async functions are prevented from interfering
# with the initial preprompt rendering
prompt_pure_cmd_timestamp=
# check for git arrows
prompt_pure_check_git_arrows
# shows the full path in the title
prompt_pure_set_title 'expand-prompt' '%~'
# get vcs info
vcs_info
# preform async git dirty check and fetch
prompt_pure_async_tasks
# print the preprompt
prompt_pure_preprompt_render "precmd"
# remove the prompt_pure_cmd_timestamp, indicating that precmd has completed
unset prompt_pure_cmd_timestamp
}
# fastest possible way to check if repo is dirty
prompt_pure_async_git_dirty() {
local untracked_dirty=$1; shift
# use cd -q to avoid side effects of changing directory, e.g. chpwd hooks
cd -q "$*"
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
(( $? )) && echo "*"
}
prompt_pure_async_git_fetch() {
# use cd -q to avoid side effects of changing directory, e.g. chpwd hooks
cd -q "$*"
# set GIT_TERMINAL_PROMPT=0 to disable auth prompting for git fetch (git 2.3+)
GIT_TERMINAL_PROMPT=0 command git -c gc.auto=0 fetch
}
prompt_pure_async_tasks() {
# initialize async worker
((!${prompt_pure_async_init:-0})) && {
async_start_worker "prompt_pure" -u -n
async_register_callback "prompt_pure" prompt_pure_async_callback
prompt_pure_async_init=1
}
# store working_tree without the "x" prefix
local working_tree="${vcs_info_msg_1_#x}"
# check if the working tree changed (prompt_pure_current_working_tree is prefixed by "x")
if [[ ${prompt_pure_current_working_tree#x} != $working_tree ]]; 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
# set the new working tree and prefix with "x" to prevent the creation of a named path by AUTO_NAME_DIRS
prompt_pure_current_working_tree="x${working_tree}"
fi
# only perform tasks inside git working tree
[[ -n $working_tree ]] || return
# do not preform git fetch if it is disabled or working_tree == HOME
if (( ${PURE_GIT_PULL:-1} )) && [[ $working_tree != $HOME ]]; then
# tell worker to do a git fetch
async_job "prompt_pure" prompt_pure_async_git_fetch "${working_tree}"
fi
# if dirty checking is sufficiently fast, tell 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}" "${working_tree}"
fi
}
prompt_pure_async_callback() {
local job=$1
local output=$3
local exec_time=$4
case "${job}" in
prompt_pure_async_git_dirty)
prompt_pure_git_dirty=$output
prompt_pure_preprompt_render
# 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 next rendering of the preprompt will the result appear in a different color.
(( $exec_time > 2 )) && prompt_pure_git_last_dirty_check_timestamp=$EPOCHSECONDS
;;
prompt_pure_async_git_fetch)
prompt_pure_check_git_arrows
prompt_pure_preprompt_render
;;
esac
}
prompt_pure_setup() {
# prevent percentage showing up
# if output doesn't end with a newline
export PROMPT_EOL_MARK=''
prompt_opts=(subst percent)
zmodload zsh/datetime
zmodload zsh/zle
autoload -Uz add-zsh-hook
autoload -Uz vcs_info
autoload -Uz async && async
add-zsh-hook precmd prompt_pure_precmd
add-zsh-hook preexec prompt_pure_preexec
zstyle ':vcs_info:*' enable git
zstyle ':vcs_info:*' use-simple true
# only export two msg variables from vcs_info
zstyle ':vcs_info:*' max-exports 2
# vcs_info_msg_0_ = ' %b' (for branch)
# vcs_info_msg_1_ = 'x%R' git top level (%R), x-prefix prevents creation of a named path (AUTO_NAME_DIRS)
zstyle ':vcs_info:git*' formats ' %b' 'x%R'
zstyle ':vcs_info:git*' actionformats ' %b|%a' 'x%R'
# if the user has not registered a custom zle widget for clear-screen,
# override the builtin one so that the preprompt is displayed correctly when
# ^L is issued.
if [[ $widgets[clear-screen] == 'builtin' ]]; then
zle -N clear-screen prompt_pure_clear_screen
fi
# show username@host if logged in through SSH
[[ "$SSH_CONNECTION" != '' ]] && prompt_pure_username=' %F{242}%n@%m%f'
# show username@host if root, with username in white
[[ $UID -eq 0 ]] && prompt_pure_username=' %F{white}%n%f%F{242}@%m%f'
# prompt turns red if the previous command didn't exit with 0
PROMPT="%(?.%F{magenta}.%F{red})${PURE_PROMPT_SYMBOL:-}%f "
}
prompt_pure_setup "$@"

View File

@@ -0,0 +1,192 @@
# Pure
> Pretty, minimal and fast ZSH prompt
![](screenshot.png)
## 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.
- 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.
- 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.0.0+.
### npm
```
$ 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`
2. Symlink `pure.zsh` to somewhere in [`$fpath`](http://www.refining-linux.org/archives/46/ZSH-Gem-12-Autoloading-functions/) with the name `prompt_pure_setup`.
3. Symlink `async.zsh` in `$fpath` with the name `async`.
#### Example
```
$ 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:
```sh
$ 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
### `PURE_CMD_MAX_EXEC_TIME`
The max execution time of a process before its run time is shown when it exits. Defaults to `5` seconds.
### `PURE_GIT_PULL`
Set `PURE_GIT_PULL=0` to prevent Pure from checking whether the current Git remote has been updated.
### `PURE_GIT_UNTRACKED_DIRTY`
Set `PURE_GIT_UNTRACKED_DIRTY=0` to not include untracked files in dirtiness check. Only really useful on extremely huge repos like the WebKit repo.
### `PURE_GIT_DELAY_DIRTY_CHECK`
Time in seconds to delay git dirty checking for large repositories (git status takes > 2 seconds). The check is performed asynchronously, this is to save CPU. Defaults to `1800` seconds.
### `PURE_PROMPT_SYMBOL`
Defines the prompt symbol. The default value is ``.
### `PURE_GIT_DOWN_ARROW`
Defines the git down arrow symbol. The default value is `⇣`.
### `PURE_GIT_UP_ARROW`
Defines the git up arrow symbol. The default value is `⇡`.
## Example
```sh
# .zshrc
autoload -U promptinit && promptinit
# optionally define some options
PURE_CMD_MAX_EXEC_TIME=10
prompt pure
```
## Tips
[Tomorrow Night Eighties](https://github.com/chriskempson/tomorrow-theme) theme with the [Droid Sans Mono](http://www.google.com/webfonts/specimen/Droid+Sans+Mono) font (15pt) is a beautiful combination, as seen in the screenshot above. 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. Remove competing theme included in oh-my-zsh `~/.oh-my-zsh/themes/pure.zsh-theme`
2. Symlink (or copy) `pure.zsh` to `~/.oh-my-zsh/custom/pure.zsh-theme`
3. Symlink (or copy) `async.zsh` to `~/.oh-my-zsh/custom/async.zsh`
4. Add `ZSH_THEME="pure"` to your `.zshrc` file.
### [prezto](https://github.com/sorin-ionescu/prezto)
Set `zstyle ':prezto:module:prompt' theme 'pure'` in `~/.zpreztorc`.
### [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.
```
antigen bundle mafredri/zsh-async
antigen bundle sindresorhus/pure
```
## FAQ
### My preprompt is missing when I clear the screen with Ctrl+L
Pure doesn't register its custom *clear-screen* widget if it has been previously modified. If you haven't registered your own zle widget with `zle -N clear-screen custom-clear-screen` it might have been done by third-party modules. For example `zsh-syntax-highlighting` and `zsh-history-substring-search` are known to do this and they should for that reason be **the very last thing** in your `.zshrc` (as pointed out in their documentation).
To find out the culprit that is overriding your *clear-screen* widget, you can run the following command: `zle -l | grep clear-screen`.
### I am stuck in a shell loop in my terminal that ask me to authenticate. What should I do ?
[This is a known issue](https://github.com/sindresorhus/pure/issues/76).
Using `git pull` when you get the username prompt should help you to break the loop by giving you a real prompt for this. **[This has been fixed in git 2.3](https://github.com/sindresorhus/pure/commit/f43ab97e1cf4a276b7a6e33eac055ee16610be15)**
### I am seeing the error `zpty: can't open pseudo terminal: bad file descriptor`.
[This is a known issue](https://github.com/sindresorhus/pure/issues/117). `zsh/zpty` requires either legacy bsd ptys or access to `/dev/ptmx`. Here are some known solutions.
#### Gentoo
```
sudo sh -c "echo 'SANDBOX_WRITE=\"/dev/ptmx\"' > /etc/sandbox.d/10zsh"
sudo emerge -1 zsh
```
#### FreeBSD 10.1
On a default setup, running the command `kldload pty` should do the trick. If you have a custom kernel, you might need to add `device pty` to the configuration file ([example](https://github.com/nbari/freebsd/blob/58646a9c3c4aaabf6f6467ff505f27f09e29dc75/kernels/xen.kernel#L188)).
## Team
[![Sindre Sorhus](https://avatars.githubusercontent.com/u/170270?v=3&s=100)](http://sindresorhus.com) | [![Mathias Fredriksson](https://avatars.githubusercontent.com/u/147409?v=3&s=100)](https://github.com/mafredri)
---|---
[Sindre Sorhus](http://sindresorhus.com) | [Mathias Fredriksson](https://github.com/mafredri)
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB