conditionally define t()

if user has enabled the todo plugin, skip defining the 'one thing'
todo function t().
diff --git a/bash_it.sh b/bash_it.sh
index cd97ab3..693c024 100755
--- a/bash_it.sh
+++ b/bash_it.sh
@@ -82,11 +82,13 @@
   echo
   echo "Here is a list of commands you can use to get help screens for specific pieces of Bash it:"
   echo
-  echo "  rails-help                  This will list out all the aliases you can use with rails."
-  echo "  git-help                    This will list out all the aliases you can use with git."
-  echo "  todo-help                   This will list out all the aliases you can use with todo.txt-cli"
-  echo "  brew-help                   This will list out all the aliases you can use with Homebrew"
-  echo "  aliases-help                Generic list of aliases."
-  echo "  plugins-help                This will list out all the plugins and functions you can use with bash-it"
+  echo "  rails-help                  list out all aliases you can use with rails."
+  echo "  git-help                    list out all aliases you can use with git."
+  echo "  todo-help                   list out all aliases you can use with todo.txt-cli"
+  echo "  brew-help                   list out all aliases you can use with Homebrew"
+  echo "  aliases-help                generic list of aliases."
+  echo "  plugins-help                list out all functions you have installed with bash-it"
+  echo "  bash-it-plugins             summarize bash-it plugins, and their installation status"
+  echo "  reference <function name>   detailed help for a specific function"
   echo
 }
diff --git a/completion/available/git.completion.bash b/completion/available/git.completion.bash
index 35dbf04..1496c6d 100644
--- a/completion/available/git.completion.bash
+++ b/completion/available/git.completion.bash
@@ -1,6 +1,6 @@
 #!bash
 #
-# bash completion support for core Git.
+# bash/zsh completion support for core Git.
 #
 # Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
 # Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
@@ -18,27 +18,48 @@
 # To use these routines:
 #
 #    1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
-#    2) Added the following line to your .bashrc:
+#    2) Add the following line to your .bashrc/.zshrc:
 #        source ~/.git-completion.sh
 #
-#    3) You may want to make sure the git executable is available
-#       in your PATH before this script is sourced, as some caching
-#       is performed while the script loads.  If git isn't found
-#       at source time then all lookups will be done on demand,
-#       which may be slightly slower.
-#
-#    4) Consider changing your PS1 to also show the current branch:
-#        PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
+#    3) Consider changing your PS1 to also show the current branch:
+#         Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
+#         ZSH:  PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
 #
 #       The argument to __git_ps1 will be displayed only if you
 #       are currently in a git repository.  The %s token will be
 #       the name of the current branch.
 #
-#	In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty
-#	value, unstaged (*) and staged (+) changes will be shown next
-#	to the branch name.  You can configure this per-repository
-#	with the bash.showDirtyState variable, which defaults to true
-#	once GIT_PS1_SHOWDIRTYSTATE is enabled.
+#       In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty
+#       value, unstaged (*) and staged (+) changes will be shown next
+#       to the branch name.  You can configure this per-repository
+#       with the bash.showDirtyState variable, which defaults to true
+#       once GIT_PS1_SHOWDIRTYSTATE is enabled.
+#
+#       You can also see if currently something is stashed, by setting
+#       GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
+#       then a '$' will be shown next to the branch name.
+#
+#       If you would like to see if there're untracked files, then you can
+#       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
+#       untracked files, then a '%' will be shown next to the branch name.
+#
+#       If you would like to see the difference between HEAD and its
+#       upstream, set GIT_PS1_SHOWUPSTREAM="auto".  A "<" indicates
+#       you are behind, ">" indicates you are ahead, and "<>"
+#       indicates you have diverged.  You can further control
+#       behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated
+#       list of values:
+#           verbose       show number of commits ahead/behind (+/-) upstream
+#           legacy        don't use the '--count' option available in recent
+#                         versions of git-rev-list
+#           git           always compare HEAD to @{upstream}
+#           svn           always compare HEAD to your SVN upstream
+#       By default, __git_ps1 will compare HEAD to your SVN upstream
+#       if it can find one, or @{upstream} otherwise.  Once you have
+#       set GIT_PS1_SHOWUPSTREAM, you can override it on a
+#       per-repository basis by setting the bash.showUpstream config
+#       variable.
+#
 #
 # To submit patches:
 #
@@ -52,6 +73,10 @@
 #       git@vger.kernel.org
 #
 
+if [[ -n ${ZSH_VERSION-} ]]; then
+	autoload -U +X bashcompinit && bashcompinit
+fi
+
 case "$COMP_WORDBREAKS" in
 *:*) : great ;;
 *)   COMP_WORDBREAKS="$COMP_WORDBREAKS:"
@@ -62,7 +87,7 @@
 __gitdir ()
 {
 	if [ -z "${1-}" ]; then
-		if [ -n "$__git_dir" ]; then
+		if [ -n "${__git_dir-}" ]; then
 			echo "$__git_dir"
 		elif [ -d .git ]; then
 			echo .git
@@ -76,73 +101,219 @@
 	fi
 }
 
+# stores the divergence from upstream in $p
+# used by GIT_PS1_SHOWUPSTREAM
+__git_ps1_show_upstream ()
+{
+	local key value
+	local svn_remote=() svn_url_pattern count n
+	local upstream=git legacy="" verbose=""
+
+	# get some config options from git-config
+	local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
+	while read -r key value; do
+		case "$key" in
+		bash.showupstream)
+			GIT_PS1_SHOWUPSTREAM="$value"
+			if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
+				p=""
+				return
+			fi
+			;;
+		svn-remote.*.url)
+			svn_remote[ $((${#svn_remote[@]} + 1)) ]="$value"
+			svn_url_pattern+="\\|$value"
+			upstream=svn+git # default upstream is SVN if available, else git
+			;;
+		esac
+	done <<< "$output"
+
+	# parse configuration values
+	for option in ${GIT_PS1_SHOWUPSTREAM}; do
+		case "$option" in
+		git|svn) upstream="$option" ;;
+		verbose) verbose=1 ;;
+		legacy)  legacy=1  ;;
+		esac
+	done
+
+	# Find our upstream
+	case "$upstream" in
+	git)    upstream="@{upstream}" ;;
+	svn*)
+		# get the upstream from the "git-svn-id: ..." in a commit message
+		# (git-svn uses essentially the same procedure internally)
+		local svn_upstream=($(git log --first-parent -1 \
+					--grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null))
+		if [[ 0 -ne ${#svn_upstream[@]} ]]; then
+			svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]}
+			svn_upstream=${svn_upstream%@*}
+			local n_stop="${#svn_remote[@]}"
+			for ((n=1; n <= n_stop; ++n)); do
+				svn_upstream=${svn_upstream#${svn_remote[$n]}}
+			done
+
+			if [[ -z "$svn_upstream" ]]; then
+				# default branch name for checkouts with no layout:
+				upstream=${GIT_SVN_ID:-git-svn}
+			else
+				upstream=${svn_upstream#/}
+			fi
+		elif [[ "svn+git" = "$upstream" ]]; then
+			upstream="@{upstream}"
+		fi
+		;;
+	esac
+
+	# Find how many commits we are ahead/behind our upstream
+	if [[ -z "$legacy" ]]; then
+		count="$(git rev-list --count --left-right \
+				"$upstream"...HEAD 2>/dev/null)"
+	else
+		# produce equivalent output to --count for older versions of git
+		local commits
+		if commits="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null)"
+		then
+			local commit behind=0 ahead=0
+			for commit in $commits
+			do
+				case "$commit" in
+				"<"*) let ++behind
+					;;
+				*)    let ++ahead
+					;;
+				esac
+			done
+			count="$behind	$ahead"
+		else
+			count=""
+		fi
+	fi
+
+	# calculate the result
+	if [[ -z "$verbose" ]]; then
+		case "$count" in
+		"") # no upstream
+			p="" ;;
+		"0	0") # equal to upstream
+			p="=" ;;
+		"0	"*) # ahead of upstream
+			p=">" ;;
+		*"	0") # behind upstream
+			p="<" ;;
+		*)	    # diverged from upstream
+			p="<>" ;;
+		esac
+	else
+		case "$count" in
+		"") # no upstream
+			p="" ;;
+		"0	0") # equal to upstream
+			p=" u=" ;;
+		"0	"*) # ahead of upstream
+			p=" u+${count#0	}" ;;
+		*"	0") # behind upstream
+			p=" u-${count%	0}" ;;
+		*)	    # diverged from upstream
+			p=" u+${count#*	}-${count%	*}" ;;
+		esac
+	fi
+
+}
+
+
 # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
 # returns text to add to bash PS1 prompt (includes branch name)
 __git_ps1 ()
 {
-	local g="$(git rev-parse --git-dir 2>/dev/null)"
+	local g="$(__gitdir)"
 	if [ -n "$g" ]; then
-		local r
-		local b
-		if [ -d "$g/rebase-apply" ]
-		then
-			if test -f "$g/rebase-apply/rebasing"
-			then
-				r="|REBASE"
-			elif test -f "$g/rebase-apply/applying"
-			then
-				r="|AM"
-			else
-				r="|AM/REBASE"
-			fi
-			b="$(git symbolic-ref HEAD 2>/dev/null)"
-		elif [ -f "$g/rebase-merge/interactive" ]
-		then
+		local r=""
+		local b=""
+		if [ -f "$g/rebase-merge/interactive" ]; then
 			r="|REBASE-i"
 			b="$(cat "$g/rebase-merge/head-name")"
-		elif [ -d "$g/rebase-merge" ]
-		then
+		elif [ -d "$g/rebase-merge" ]; then
 			r="|REBASE-m"
 			b="$(cat "$g/rebase-merge/head-name")"
-		elif [ -f "$g/MERGE_HEAD" ]
-		then
-			r="|MERGING"
-			b="$(git symbolic-ref HEAD 2>/dev/null)"
 		else
-			if [ -f "$g/BISECT_LOG" ]
-			then
+			if [ -d "$g/rebase-apply" ]; then
+				if [ -f "$g/rebase-apply/rebasing" ]; then
+					r="|REBASE"
+				elif [ -f "$g/rebase-apply/applying" ]; then
+					r="|AM"
+				else
+					r="|AM/REBASE"
+				fi
+			elif [ -f "$g/MERGE_HEAD" ]; then
+				r="|MERGING"
+			elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+				r="|CHERRY-PICKING"
+			elif [ -f "$g/BISECT_LOG" ]; then
 				r="|BISECTING"
 			fi
-			if ! b="$(git symbolic-ref HEAD 2>/dev/null)"
-			then
-				if ! b="$(git describe --exact-match HEAD 2>/dev/null)"
-				then
-					b="$(cut -c1-7 "$g/HEAD")..."
+
+			b="$(git symbolic-ref HEAD 2>/dev/null)" || {
+
+				b="$(
+				case "${GIT_PS1_DESCRIBE_STYLE-}" in
+				(contains)
+					git describe --contains HEAD ;;
+				(branch)
+					git describe --contains --all HEAD ;;
+				(describe)
+					git describe HEAD ;;
+				(* | default)
+					git describe --tags --exact-match HEAD ;;
+				esac 2>/dev/null)" ||
+
+				b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." ||
+				b="unknown"
+				b="($b)"
+			}
+		fi
+
+		local w=""
+		local i=""
+		local s=""
+		local u=""
+		local c=""
+		local p=""
+
+		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
+			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
+				c="BARE:"
+			else
+				b="GIT_DIR!"
+			fi
+		elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
+			if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ]; then
+				if [ "$(git config --bool bash.showDirtyState)" != "false" ]; then
+					git diff --no-ext-diff --quiet --exit-code || w="*"
+					if git rev-parse --quiet --verify HEAD >/dev/null; then
+						git diff-index --cached --quiet HEAD -- || i="+"
+					else
+						i="#"
+					fi
 				fi
 			fi
+			if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
+			        git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
+			fi
+
+			if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ]; then
+			   if [ -n "$(git ls-files --others --exclude-standard)" ]; then
+			      u="%"
+			   fi
+			fi
+
+			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+				__git_ps1_show_upstream
+			fi
 		fi
 
-		local w
-		local i
-
-		if test -n "$GIT_PS1_SHOWDIRTYSTATE"; then
-			if test "$(git config --bool bash.showDirtyState)" != "false"; then
-				git diff --no-ext-diff --ignore-submodules \
-					--quiet --exit-code || w="*"
-				if git rev-parse --quiet --verify HEAD >/dev/null; then
-					git diff-index --cached --quiet \
-						--ignore-submodules HEAD -- || i="+"
-				else
-					i="#"
-				fi
-			fi
-		fi
-
-		if [ -n "${1-}" ]; then
-			printf "$1" "${b##refs/heads/}$w$i$r"
-		else
-			printf " (%s)" "${b##refs/heads/}$w$i$r"
-		fi
+		local f="$w$i$s$u"
+		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r$p"
 	fi
 }
 
@@ -159,15 +330,177 @@
 	done
 }
 
-# __gitcomp accepts 1, 2, 3, or 4 arguments
-# generates completion reply with compgen
+# The following function is based on code from:
+#
+#   bash_completion - programmable completion functions for bash 3.2+
+#
+#   Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
+#             © 2009-2010, Bash Completion Maintainers
+#                     <bash-completion-devel@lists.alioth.debian.org>
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2, or (at your option)
+#   any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software Foundation,
+#   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#   The latest version of this software can be obtained here:
+#
+#   http://bash-completion.alioth.debian.org/
+#
+#   RELEASE: 2.x
+
+# This function can be used to access a tokenized list of words
+# on the command line:
+#
+#	__git_reassemble_comp_words_by_ref '=:'
+#	if test "${words_[cword_-1]}" = -w
+#	then
+#		...
+#	fi
+#
+# The argument should be a collection of characters from the list of
+# word completion separators (COMP_WORDBREAKS) to treat as ordinary
+# characters.
+#
+# This is roughly equivalent to going back in time and setting
+# COMP_WORDBREAKS to exclude those characters.  The intent is to
+# make option types like --date=<type> and <rev>:<path> easy to
+# recognize by treating each shell word as a single token.
+#
+# It is best not to set COMP_WORDBREAKS directly because the value is
+# shared with other completion scripts.  By the time the completion
+# function gets called, COMP_WORDS has already been populated so local
+# changes to COMP_WORDBREAKS have no effect.
+#
+# Output: words_, cword_, cur_.
+
+__git_reassemble_comp_words_by_ref()
+{
+	local exclude i j first
+	# Which word separators to exclude?
+	exclude="${1//[^$COMP_WORDBREAKS]}"
+	cword_=$COMP_CWORD
+	if [ -z "$exclude" ]; then
+		words_=("${COMP_WORDS[@]}")
+		return
+	fi
+	# List of word completion separators has shrunk;
+	# re-assemble words to complete.
+	for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
+		# Append each nonempty word consisting of just
+		# word separator characters to the current word.
+		first=t
+		while
+			[ $i -gt 0 ] &&
+			[ -n "${COMP_WORDS[$i]}" ] &&
+			# word consists of excluded word separators
+			[ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
+		do
+			# Attach to the previous token,
+			# unless the previous token is the command name.
+			if [ $j -ge 2 ] && [ -n "$first" ]; then
+				((j--))
+			fi
+			first=
+			words_[$j]=${words_[j]}${COMP_WORDS[i]}
+			if [ $i = $COMP_CWORD ]; then
+				cword_=$j
+			fi
+			if (($i < ${#COMP_WORDS[@]} - 1)); then
+				((i++))
+			else
+				# Done.
+				return
+			fi
+		done
+		words_[$j]=${words_[j]}${COMP_WORDS[i]}
+		if [ $i = $COMP_CWORD ]; then
+			cword_=$j
+		fi
+	done
+}
+
+if ! type _get_comp_words_by_ref >/dev/null 2>&1; then
+if [[ -z ${ZSH_VERSION:+set} ]]; then
+_get_comp_words_by_ref ()
+{
+	local exclude cur_ words_ cword_
+	if [ "$1" = "-n" ]; then
+		exclude=$2
+		shift 2
+	fi
+	__git_reassemble_comp_words_by_ref "$exclude"
+	cur_=${words_[cword_]}
+	while [ $# -gt 0 ]; do
+		case "$1" in
+		cur)
+			cur=$cur_
+			;;
+		prev)
+			prev=${words_[$cword_-1]}
+			;;
+		words)
+			words=("${words_[@]}")
+			;;
+		cword)
+			cword=$cword_
+			;;
+		esac
+		shift
+	done
+}
+else
+_get_comp_words_by_ref ()
+{
+	while [ $# -gt 0 ]; do
+		case "$1" in
+		cur)
+			cur=${COMP_WORDS[COMP_CWORD]}
+			;;
+		prev)
+			prev=${COMP_WORDS[COMP_CWORD-1]}
+			;;
+		words)
+			words=("${COMP_WORDS[@]}")
+			;;
+		cword)
+			cword=$COMP_CWORD
+			;;
+		-n)
+			# assume COMP_WORDBREAKS is already set sanely
+			shift
+			;;
+		esac
+		shift
+	done
+}
+fi
+fi
+
+# Generates completion reply with compgen, appending a space to possible
+# completion words, if necessary.
+# It accepts 1 to 4 arguments:
+# 1: List of possible completion words.
+# 2: A prefix to be added to each possible completion word (optional).
+# 3: Generate possible completion matches for this word (optional).
+# 4: A suffix to be appended to each possible completion word (optional).
 __gitcomp ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur_="$cur"
+
 	if [ $# -gt 2 ]; then
-		cur="$3"
+		cur_="$3"
 	fi
-	case "$cur" in
+	case "$cur_" in
 	--*=)
 		COMPREPLY=()
 		;;
@@ -175,80 +508,118 @@
 		local IFS=$'\n'
 		COMPREPLY=($(compgen -P "${2-}" \
 			-W "$(__gitcomp_1 "${1-}" "${4-}")" \
-			-- "$cur"))
+			-- "$cur_"))
 		;;
 	esac
 }
 
-# __git_heads accepts 0 or 1 arguments (to pass to __gitdir)
+# Generates completion reply with compgen from newline-separated possible
+# completion words by appending a space to all of them.
+# It accepts 1 to 4 arguments:
+# 1: List of possible completion words, separated by a single newline.
+# 2: A prefix to be added to each possible completion word (optional).
+# 3: Generate possible completion matches for this word (optional).
+# 4: A suffix to be appended to each possible completion word instead of
+#    the default space (optional).  If specified but empty, nothing is
+#    appended.
+__gitcomp_nl ()
+{
+	local s=$'\n' IFS=' '$'\t'$'\n'
+	local cur_="$cur" suffix=" "
+
+	if [ $# -gt 2 ]; then
+		cur_="$3"
+		if [ $# -gt 3 ]; then
+			suffix="$4"
+		fi
+	fi
+
+	IFS=$s
+	COMPREPLY=($(compgen -P "${2-}" -S "$suffix" -W "$1" -- "$cur_"))
+}
+
 __git_heads ()
 {
-	local cmd i is_hash=y dir="$(__gitdir "${1-}")"
+	local dir="$(__gitdir)"
 	if [ -d "$dir" ]; then
 		git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
 			refs/heads
 		return
 	fi
-	for i in $(git ls-remote "${1-}" 2>/dev/null); do
-		case "$is_hash,$i" in
-		y,*) is_hash=n ;;
-		n,*^{}) is_hash=y ;;
-		n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
-		n,*) is_hash=y; echo "$i" ;;
-		esac
-	done
 }
 
-# __git_tags accepts 0 or 1 arguments (to pass to __gitdir)
 __git_tags ()
 {
-	local cmd i is_hash=y dir="$(__gitdir "${1-}")"
+	local dir="$(__gitdir)"
 	if [ -d "$dir" ]; then
 		git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
 			refs/tags
 		return
 	fi
-	for i in $(git ls-remote "${1-}" 2>/dev/null); do
-		case "$is_hash,$i" in
-		y,*) is_hash=n ;;
-		n,*^{}) is_hash=y ;;
-		n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
-		n,*) is_hash=y; echo "$i" ;;
-		esac
-	done
 }
 
-# __git_refs accepts 0 or 1 arguments (to pass to __gitdir)
+# __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments
+# presence of 2nd argument means use the guess heuristic employed
+# by checkout for tracking branches
 __git_refs ()
 {
-	local i is_hash=y dir="$(__gitdir "${1-}")"
-	local cur="${COMP_WORDS[COMP_CWORD]}" format refs
+	local i hash dir="$(__gitdir "${1-}")" track="${2-}"
+	local format refs
 	if [ -d "$dir" ]; then
 		case "$cur" in
 		refs|refs/*)
 			format="refname"
 			refs="${cur%/*}"
+			track=""
 			;;
 		*)
-			if [ -e "$dir/HEAD" ]; then echo HEAD; fi
+			for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
+				if [ -e "$dir/$i" ]; then echo $i; fi
+			done
 			format="refname:short"
 			refs="refs/tags refs/heads refs/remotes"
 			;;
 		esac
 		git --git-dir="$dir" for-each-ref --format="%($format)" \
 			$refs
+		if [ -n "$track" ]; then
+			# employ the heuristic used by git checkout
+			# Try to find a remote branch that matches the completion word
+			# but only output if the branch name is unique
+			local ref entry
+			git --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \
+				"refs/remotes/" | \
+			while read -r entry; do
+				eval "$entry"
+				ref="${ref#*/}"
+				if [[ "$ref" == "$cur"* ]]; then
+					echo "$ref"
+				fi
+			done | uniq -u
+		fi
 		return
 	fi
-	for i in $(git ls-remote "$dir" 2>/dev/null); do
-		case "$is_hash,$i" in
-		y,*) is_hash=n ;;
-		n,*^{}) is_hash=y ;;
-		n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
-		n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
-		n,refs/remotes/*) is_hash=y; echo "${i#refs/remotes/}" ;;
-		n,*) is_hash=y; echo "$i" ;;
-		esac
-	done
+	case "$cur" in
+	refs|refs/*)
+		git ls-remote "$dir" "$cur*" 2>/dev/null | \
+		while read -r hash i; do
+			case "$i" in
+			*^{}) ;;
+			*) echo "$i" ;;
+			esac
+		done
+		;;
+	*)
+		git ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \
+		while read -r hash i; do
+			case "$i" in
+			*^{}) ;;
+			refs/*) echo "${i#refs/*/}" ;;
+			*) echo "$i" ;;
+			esac
+		done
+		;;
+	esac
 }
 
 # __git_refs2 requires 1 argument (to pass to __git_refs)
@@ -263,46 +634,30 @@
 # __git_refs_remotes requires 1 argument (to pass to ls-remote)
 __git_refs_remotes ()
 {
-	local cmd i is_hash=y
-	for i in $(git ls-remote "$1" 2>/dev/null); do
-		case "$is_hash,$i" in
-		n,refs/heads/*)
-			is_hash=y
-			echo "$i:refs/remotes/$1/${i#refs/heads/}"
-			;;
-		y,*) is_hash=n ;;
-		n,*^{}) is_hash=y ;;
-		n,refs/tags/*) is_hash=y;;
-		n,*) is_hash=y; ;;
-		esac
+	local i hash
+	git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \
+	while read -r hash i; do
+		echo "$i:refs/remotes/$1/${i#refs/heads/}"
 	done
 }
 
 __git_remotes ()
 {
 	local i ngoff IFS=$'\n' d="$(__gitdir)"
-	shopt -q nullglob || ngoff=1
-	shopt -s nullglob
+	__git_shopt -q nullglob || ngoff=1
+	__git_shopt -s nullglob
 	for i in "$d/remotes"/*; do
 		echo ${i#$d/remotes/}
 	done
-	[ "$ngoff" ] && shopt -u nullglob
-	for i in $(git --git-dir="$d" config --list); do
-		case "$i" in
-		remote.*.url=*)
-			i="${i#remote.}"
-			echo "${i/.url=*/}"
-			;;
-		esac
+	[ "$ngoff" ] && __git_shopt -u nullglob
+	for i in $(git --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do
+		i="${i#remote.}"
+		echo "${i/.url*/}"
 	done
 }
 
-__git_merge_strategies ()
+__git_list_merge_strategies ()
 {
-	if [ -n "$__git_merge_strategylist" ]; then
-		echo "$__git_merge_strategylist"
-		return
-	fi
 	git merge -s help 2>&1 |
 	sed -n -e '/[Aa]vailable strategies are: /,/^$/{
 		s/\.$//
@@ -312,27 +667,39 @@
 		p
 	}'
 }
-__git_merge_strategylist=
-__git_merge_strategylist=$(__git_merge_strategies 2>/dev/null)
 
-__git_complete_file ()
+__git_merge_strategies=
+# 'git merge -s help' (and thus detection of the merge strategy
+# list) fails, unfortunately, if run outside of any git working
+# tree.  __git_merge_strategies is set to the empty string in
+# that case, and the detection will be repeated the next time it
+# is needed.
+__git_compute_merge_strategies ()
 {
-	local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
-	case "$cur" in
+	: ${__git_merge_strategies:=$(__git_list_merge_strategies)}
+}
+
+__git_complete_revlist_file ()
+{
+	local pfx ls ref cur_="$cur"
+	case "$cur_" in
+	*..?*:*)
+		return
+		;;
 	?*:*)
-		ref="${cur%%:*}"
-		cur="${cur#*:}"
-		case "$cur" in
+		ref="${cur_%%:*}"
+		cur_="${cur_#*:}"
+		case "$cur_" in
 		?*/*)
-			pfx="${cur%/*}"
-			cur="${cur##*/}"
+			pfx="${cur_%/*}"
+			cur_="${cur_##*/}"
 			ls="$ref:$pfx"
 			pfx="$pfx/"
 			;;
 		*)
 			ls="$ref"
 			;;
-	    esac
+		esac
 
 		case "$COMP_WORDBREAKS" in
 		*:*) : great ;;
@@ -355,42 +722,127 @@
 				           s,$,/,
 				       }
 				       s/^.*	//')" \
-			-- "$cur"))
+			-- "$cur_"))
+		;;
+	*...*)
+		pfx="${cur_%...*}..."
+		cur_="${cur_#*...}"
+		__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+		;;
+	*..*)
+		pfx="${cur_%..*}.."
+		cur_="${cur_#*..}"
+		__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
 		;;
 	*)
-		__gitcomp "$(__git_refs)"
+		__gitcomp_nl "$(__git_refs)"
 		;;
 	esac
 }
 
+
+__git_complete_file ()
+{
+	__git_complete_revlist_file
+}
+
 __git_complete_revlist ()
 {
-	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
-	case "$cur" in
-	*...*)
-		pfx="${cur%...*}..."
-		cur="${cur#*...}"
-		__gitcomp "$(__git_refs)" "$pfx" "$cur"
+	__git_complete_revlist_file
+}
+
+__git_complete_remote_or_refspec ()
+{
+	local cur_="$cur" cmd="${words[1]}"
+	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
+		case "$i" in
+		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
+		--all)
+			case "$cmd" in
+			push) no_complete_refspec=1 ;;
+			fetch)
+				COMPREPLY=()
+				return
+				;;
+			*) ;;
+			esac
+			;;
+		-*) ;;
+		*) remote="$i"; break ;;
+		esac
+		c=$((++c))
+	done
+	if [ -z "$remote" ]; then
+		__gitcomp_nl "$(__git_remotes)"
+		return
+	fi
+	if [ $no_complete_refspec = 1 ]; then
+		COMPREPLY=()
+		return
+	fi
+	[ "$remote" = "." ] && remote=
+	case "$cur_" in
+	*:*)
+		case "$COMP_WORDBREAKS" in
+		*:*) : great ;;
+		*)   pfx="${cur_%%:*}:" ;;
+		esac
+		cur_="${cur_#*:}"
+		lhs=0
 		;;
-	*..*)
-		pfx="${cur%..*}.."
-		cur="${cur#*..}"
-		__gitcomp "$(__git_refs)" "$pfx" "$cur"
+	+*)
+		pfx="+"
+		cur_="${cur_#+}"
 		;;
-	*)
-		__gitcomp "$(__git_refs)"
+	esac
+	case "$cmd" in
+	fetch)
+		if [ $lhs = 1 ]; then
+			__gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_"
+		else
+			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+		fi
+		;;
+	pull)
+		if [ $lhs = 1 ]; then
+			__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
+		else
+			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+		fi
+		;;
+	push)
+		if [ $lhs = 1 ]; then
+			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+		else
+			__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
+		fi
 		;;
 	esac
 }
 
-__git_all_commands ()
+__git_complete_strategy ()
 {
-	if [ -n "$__git_all_commandlist" ]; then
-		echo "$__git_all_commandlist"
-		return
-	fi
+	__git_compute_merge_strategies
+	case "$prev" in
+	-s|--strategy)
+		__gitcomp "$__git_merge_strategies"
+		return 0
+	esac
+	case "$cur" in
+	--strategy=*)
+		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
+		return 0
+		;;
+	esac
+	return 1
+}
+
+__git_list_all_commands ()
+{
 	local i IFS=" "$'\n'
-	for i in $(git help -a|egrep '^ ')
+	for i in $(git help -a|egrep '^  [a-zA-Z0-9]')
 	do
 		case $i in
 		*--*)             : helper pattern;;
@@ -398,17 +850,18 @@
 		esac
 	done
 }
-__git_all_commandlist=
-__git_all_commandlist="$(__git_all_commands 2>/dev/null)"
 
-__git_porcelain_commands ()
+__git_all_commands=
+__git_compute_all_commands ()
 {
-	if [ -n "$__git_porcelain_commandlist" ]; then
-		echo "$__git_porcelain_commandlist"
-		return
-	fi
+	: ${__git_all_commands:=$(__git_list_all_commands)}
+}
+
+__git_list_porcelain_commands ()
+{
 	local i IFS=" "$'\n'
-	for i in "help" $(__git_all_commands)
+	__git_compute_all_commands
+	for i in "help" $__git_all_commands
 	do
 		case $i in
 		*--*)             : helper pattern;;
@@ -459,7 +912,7 @@
 		quiltimport)      : import;;
 		read-tree)        : plumbing;;
 		receive-pack)     : plumbing;;
-		reflog)           : plumbing;;
+		remote-*)         : transport;;
 		repo-config)      : deprecated;;
 		rerere)           : plumbing;;
 		rev-list)         : plumbing;;
@@ -489,17 +942,35 @@
 		esac
 	done
 }
-__git_porcelain_commandlist=
-__git_porcelain_commandlist="$(__git_porcelain_commands 2>/dev/null)"
+
+__git_porcelain_commands=
+__git_compute_porcelain_commands ()
+{
+	__git_compute_all_commands
+	: ${__git_porcelain_commands:=$(__git_list_porcelain_commands)}
+}
+
+__git_pretty_aliases ()
+{
+	local i IFS=$'\n'
+	for i in $(git --git-dir="$(__gitdir)" config --get-regexp "pretty\..*" 2>/dev/null); do
+		case "$i" in
+		pretty.*)
+			i="${i#pretty.}"
+			echo "${i/ */}"
+			;;
+		esac
+	done
+}
 
 __git_aliases ()
 {
 	local i IFS=$'\n'
-	for i in $(git --git-dir="$(__gitdir)" config --list); do
+	for i in $(git --git-dir="$(__gitdir)" config --get-regexp "alias\..*" 2>/dev/null); do
 		case "$i" in
 		alias.*)
 			i="${i#alias.}"
-			echo "${i/=*/}"
+			echo "${i/ */}"
 			;;
 		esac
 	done
@@ -511,20 +982,28 @@
 	local word cmdline=$(git --git-dir="$(__gitdir)" \
 		config --get "alias.$1")
 	for word in $cmdline; do
-		if [ "${word##-*}" ]; then
-			echo $word
+		case "$word" in
+		\!gitk|gitk)
+			echo "gitk"
 			return
-		fi
+			;;
+		\!*)	: shell command alias ;;
+		-*)	: option ;;
+		*=*)	: setting env ;;
+		git)	: git itself ;;
+		*)
+			echo "$word"
+			return
+		esac
 	done
 }
 
-# __git_find_subcommand requires 1 argument
-__git_find_subcommand ()
+# __git_find_on_cmdline requires 1 argument
+__git_find_on_cmdline ()
 {
 	local word subcommand c=1
-
-	while [ $c -lt $COMP_CWORD ]; do
-		word="${COMP_WORDS[c]}"
+	while [ $c -lt $cword ]; do
+		word="${words[c]}"
 		for subcommand in $1; do
 			if [ "$subcommand" = "$word" ]; then
 				echo "$subcommand"
@@ -538,8 +1017,8 @@
 __git_has_doubledash ()
 {
 	local c=1
-	while [ $c -lt $COMP_CWORD ]; do
-		if [ "--" = "${COMP_WORDS[c]}" ]; then
+	while [ $c -lt $cword ]; do
+		if [ "--" = "${words[c]}" ]; then
 			return 0
 		fi
 		c=$((++c))
@@ -551,9 +1030,9 @@
 
 _git_am ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local dir="$(__gitdir)"
 	if [ -d "$dir"/rebase-apply ]; then
-		__gitcomp "--skip --resolved --abort"
+		__gitcomp "--skip --continue --resolved --abort"
 		return
 	fi
 	case "$cur" in
@@ -563,8 +1042,10 @@
 		;;
 	--*)
 		__gitcomp "
-			--signoff --utf8 --binary --3way --interactive
-			--whitespace=
+			--3way --committer-date-is-author-date --ignore-date
+			--ignore-whitespace --ignore-space-change
+			--interactive --keep --no-utf8 --signoff --utf8
+			--whitespace= --scissors
 			"
 		return
 	esac
@@ -573,7 +1054,6 @@
 
 _git_apply ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -584,6 +1064,7 @@
 			--stat --numstat --summary --check --index
 			--cached --index-info --reverse --reject --unidiff-zero
 			--apply --no-add --exclude=
+			--ignore-whitespace --ignore-space-change
 			--whitespace= --inaccurate-eof --verbose
 			"
 		return
@@ -595,7 +1076,6 @@
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -609,14 +1089,13 @@
 
 _git_archive ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
 		return
 		;;
 	--remote=*)
-		__gitcomp "$(__git_remotes)" "" "${cur##--remote=}"
+		__gitcomp_nl "$(__git_remotes)" "" "${cur##--remote=}"
 		return
 		;;
 	--*)
@@ -635,15 +1114,19 @@
 	__git_has_doubledash && return
 
 	local subcommands="start bad good skip reset visualize replay log run"
-	local subcommand="$(__git_find_subcommand "$subcommands")"
+	local subcommand="$(__git_find_on_cmdline "$subcommands")"
 	if [ -z "$subcommand" ]; then
-		__gitcomp "$subcommands"
+		if [ -f "$(__gitdir)"/BISECT_START ]; then
+			__gitcomp "$subcommands"
+		else
+			__gitcomp "replay start"
+		fi
 		return
 	fi
 
 	case "$subcommand" in
-	bad|good|reset|skip)
-		__gitcomp "$(__git_refs)"
+	bad|good|reset|skip|start)
+		__gitcomp_nl "$(__git_refs)"
 		;;
 	*)
 		COMPREPLY=()
@@ -655,8 +1138,8 @@
 {
 	local i c=1 only_local_ref="n" has_r="n"
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-m)	only_local_ref="y" ;;
 		-r)	has_r="y" ;;
@@ -664,18 +1147,19 @@
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD]}" in
+	case "$cur" in
 	--*)
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
 			--track --no-track --contains --merged --no-merged
+			--set-upstream
 			"
 		;;
 	*)
 		if [ $only_local_ref = "y" -a $has_r = "n" ]; then
-			__gitcomp "$(__git_heads)"
+			__gitcomp_nl "$(__git_heads)"
 		else
-			__gitcomp "$(__git_refs)"
+			__gitcomp_nl "$(__git_refs)"
 		fi
 		;;
 	esac
@@ -683,8 +1167,8 @@
 
 _git_bundle ()
 {
-	local cmd="${COMP_WORDS[2]}"
-	case "$COMP_CWORD" in
+	local cmd="${words[2]}"
+	case "$cword" in
 	2)
 		__gitcomp "create list-heads verify unbundle"
 		;;
@@ -705,7 +1189,26 @@
 {
 	__git_has_doubledash && return
 
-	__gitcomp "$(__git_refs)"
+	case "$cur" in
+	--conflict=*)
+		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
+		;;
+	--*)
+		__gitcomp "
+			--quiet --ours --theirs --track --no-track --merge
+			--conflict= --orphan --patch
+			"
+		;;
+	*)
+		# check if --track, --no-track, or --no-guess was specified
+		# if so, disable DWIM mode
+		local flags="--track --no-track --no-guess" track=1
+		if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
+			track=''
+		fi
+		__gitcomp_nl "$(__git_refs '' $track)"
+		;;
+	esac
 }
 
 _git_cherry ()
@@ -715,13 +1218,12 @@
 
 _git_cherry_pick ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit"
 		;;
 	*)
-		__gitcomp "$(__git_refs)"
+		__gitcomp_nl "$(__git_refs)"
 		;;
 	esac
 }
@@ -730,7 +1232,6 @@
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run --quiet"
@@ -742,7 +1243,6 @@
 
 _git_clone ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -769,12 +1269,29 @@
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
+	--cleanup=*)
+		__gitcomp "default strip verbatim whitespace
+			" "" "${cur##--cleanup=}"
+		return
+		;;
+	--reuse-message=*|--reedit-message=*|\
+	--fixup=*|--squash=*)
+		__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
+		return
+		;;
+	--untracked-files=*)
+		__gitcomp "all no normal" "" "${cur##--untracked-files=}"
+		return
+		;;
 	--*)
 		__gitcomp "
 			--all --author= --signoff --verify --no-verify
 			--edit --amend --include --only --interactive
+			--dry-run --reuse-message= --reedit-message=
+			--reset-author --file= --message= --template=
+			--cleanup= --untracked-files --untracked-files=
+			--verbose --quiet --fixup= --squash=
 			"
 		return
 	esac
@@ -783,7 +1300,6 @@
 
 _git_describe ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -792,7 +1308,7 @@
 			"
 		return
 	esac
-	__gitcomp "$(__git_refs)"
+	__gitcomp_nl "$(__git_refs)"
 }
 
 __git_diff_common_options="--stat --numstat --shortstat --summary
@@ -807,61 +1323,85 @@
 			--inter-hunk-context=
 			--patience
 			--raw
+			--dirstat --dirstat= --dirstat-by-file
+			--dirstat-by-file= --cumulative
 "
 
 _git_diff ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
-		__gitcomp "--cached --pickaxe-all --pickaxe-regex
-			--base --ours --theirs
+		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
+			--base --ours --theirs --no-index
 			$__git_diff_common_options
 			"
 		return
 		;;
 	esac
+	__git_complete_revlist_file
+}
+
+__git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff
+			tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc3
+"
+
+_git_difftool ()
+{
+	__git_has_doubledash && return
+
+	case "$cur" in
+	--tool=*)
+		__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
+		return
+		;;
+	--*)
+		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
+			--base --ours --theirs
+			--no-renames --diff-filter= --find-copies-harder
+			--relative --ignore-submodules
+			--tool="
+		return
+		;;
+	esac
 	__git_complete_file
 }
 
+__git_fetch_options="
+	--quiet --verbose --append --upload-pack --force --keep --depth=
+	--tags --no-tags --all --prune --dry-run
+"
+
 _git_fetch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-
-	if [ "$COMP_CWORD" = 2 ]; then
-		__gitcomp "$(__git_remotes)"
-	else
-		case "$cur" in
-		*:*)
-			local pfx=""
-			case "$COMP_WORDBREAKS" in
-			*:*) : great ;;
-			*)   pfx="${cur%%:*}:" ;;
-			esac
-			__gitcomp "$(__git_refs)" "$pfx" "${cur#*:}"
-			;;
-		*)
-			__gitcomp "$(__git_refs2 "${COMP_WORDS[2]}")"
-			;;
-		esac
-	fi
+	case "$cur" in
+	--*)
+		__gitcomp "$__git_fetch_options"
+		return
+		;;
+	esac
+	__git_complete_remote_or_refspec
 }
 
 _git_format_patch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
+	--thread=*)
+		__gitcomp "
+			deep shallow
+			" "" "${cur##--thread=}"
+		return
+		;;
 	--*)
 		__gitcomp "
-			--stdout --attach --thread
+			--stdout --attach --no-attach --thread --thread=
 			--output-directory
 			--numbered --start-number
 			--numbered-files
 			--keep-subject
-			--signoff
-			--in-reply-to=
+			--signoff --signature --no-signature
+			--in-reply-to= --cc=
 			--full-index --binary
 			--not --all
 			--cover-letter
@@ -875,9 +1415,22 @@
 	__git_complete_revlist
 }
 
+_git_fsck ()
+{
+	case "$cur" in
+	--*)
+		__gitcomp "
+			--tags --root --unreachable --cache --no-reflogs --full
+			--strict --verbose --lost-found
+			"
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
 _git_gc ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "--prune --aggressive"
@@ -887,49 +1440,68 @@
 	COMPREPLY=()
 }
 
+_git_gitk ()
+{
+	_gitk
+}
+
+__git_match_ctag() {
+	awk "/^${1////\\/}/ { print \$1 }" "$2"
+}
+
 _git_grep ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "
 			--cached
 			--text --ignore-case --word-regexp --invert-match
-			--full-name
+			--full-name --line-number
 			--extended-regexp --basic-regexp --fixed-strings
+			--perl-regexp
 			--files-with-matches --name-only
 			--files-without-match
+			--max-depth
 			--count
 			--and --or --not --all-match
 			"
 		return
 		;;
 	esac
-	COMPREPLY=()
+
+	case "$cword,$prev" in
+	2,*|*,-*)
+		if test -r tags; then
+			__gitcomp_nl "$(__git_match_ctag "$cur" tags)"
+			return
+		fi
+		;;
+	esac
+
+	__gitcomp_nl "$(__git_refs)"
 }
 
 _git_help ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "--all --info --man --web"
 		return
 		;;
 	esac
-	__gitcomp "$(__git_all_commands)
+	__git_compute_all_commands
+	__gitcomp "$__git_all_commands $(__git_aliases)
 		attributes cli core-tutorial cvs-migration
 		diffcore gitk glossary hooks ignore modules
-		repository-layout tutorial tutorial-2
+		namespaces repository-layout tutorial tutorial-2
 		workflows
 		"
 }
 
 _git_init ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -949,7 +1521,6 @@
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --deleted --modified --others --ignored
@@ -967,7 +1538,7 @@
 
 _git_ls_remote ()
 {
-	__gitcomp "$(__git_remotes)"
+	__gitcomp_nl "$(__git_remotes)"
 }
 
 _git_ls_tree ()
@@ -975,43 +1546,71 @@
 	__git_complete_file
 }
 
+# Options that go well for log, shortlog and gitk
+__git_log_common_options="
+	--not --all
+	--branches --tags --remotes
+	--first-parent --merges --no-merges
+	--max-count=
+	--max-age= --since= --after=
+	--min-age= --until= --before=
+	--min-parents= --max-parents=
+	--no-min-parents --no-max-parents
+"
+# Options that go well for log and gitk (not shortlog)
+__git_log_gitk_options="
+	--dense --sparse --full-history
+	--simplify-merges --simplify-by-decoration
+	--left-right --notes --no-notes
+"
+# Options that go well for log and shortlog (not gitk)
+__git_log_shortlog_options="
+	--author= --committer= --grep=
+	--all-match
+"
+
 __git_log_pretty_formats="oneline short medium full fuller email raw format:"
+__git_log_date_formats="relative iso8601 rfc2822 short local default raw"
 
 _git_log ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local g="$(git rev-parse --git-dir 2>/dev/null)"
+	local merge=""
+	if [ -f "$g/MERGE_HEAD" ]; then
+		merge="--merge"
+	fi
 	case "$cur" in
-	--pretty=*)
-		__gitcomp "$__git_log_pretty_formats
-			" "" "${cur##--pretty=}"
+	--pretty=*|--format=*)
+		__gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
+			" "" "${cur#*=}"
 		return
 		;;
 	--date=*)
-		__gitcomp "
-			relative iso8601 rfc2822 short local default
-		" "" "${cur##--date=}"
+		__gitcomp "$__git_log_date_formats" "" "${cur##--date=}"
+		return
+		;;
+	--decorate=*)
+		__gitcomp "long short" "" "${cur##--decorate=}"
 		return
 		;;
 	--*)
 		__gitcomp "
-			--max-count= --max-age= --since= --after=
-			--min-age= --before= --until=
+			$__git_log_common_options
+			$__git_log_shortlog_options
+			$__git_log_gitk_options
 			--root --topo-order --date-order --reverse
-			--no-merges --follow
+			--follow --full-diff
 			--abbrev-commit --abbrev=
 			--relative-date --date=
-			--author= --committer= --grep=
-			--all-match
-			--pretty=
-			--not --all
-			--left-right --cherry-pick
+			--pretty= --format= --oneline
+			--cherry-pick
 			--graph
-			--decorate
+			--decorate --decorate=
 			--walk-reflogs
-			--parents --children --full-history
-			--merge
+			--parents --children
+			$merge
 			$__git_diff_common_options
 			--pickaxe-all --pickaxe-regex
 			"
@@ -1021,37 +1620,28 @@
 	__git_complete_revlist
 }
 
+__git_merge_options="
+	--no-commit --no-stat --log --no-log --squash --strategy
+	--commit --stat --no-squash --ff --no-ff --ff-only
+"
+
 _git_merge ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
-	-s|--strategy)
-		__gitcomp "$(__git_merge_strategies)"
-		return
-	esac
+	__git_complete_strategy && return
+
 	case "$cur" in
-	--strategy=*)
-		__gitcomp "$(__git_merge_strategies)" "" "${cur##--strategy=}"
-		return
-		;;
 	--*)
-		__gitcomp "
-			--no-commit --no-stat --log --no-log --squash --strategy
-			"
+		__gitcomp "$__git_merge_options"
 		return
 	esac
-	__gitcomp "$(__git_refs)"
+	__gitcomp_nl "$(__git_refs)"
 }
 
 _git_mergetool ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--tool=*)
-		__gitcomp "
-			kdiff3 tkdiff meld xxdiff emerge
-			vimdiff gvimdiff ecmerge opendiff
-			" "" "${cur##--tool=}"
+		__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
 		return
 		;;
 	--*)
@@ -1064,12 +1654,11 @@
 
 _git_merge_base ()
 {
-	__gitcomp "$(__git_refs)"
+	__gitcomp_nl "$(__git_refs)"
 }
 
 _git_mv ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run"
@@ -1084,80 +1673,164 @@
 	__gitcomp "--tags --all --stdin"
 }
 
+_git_notes ()
+{
+	local subcommands='add append copy edit list prune remove show'
+	local subcommand="$(__git_find_on_cmdline "$subcommands")"
+
+	case "$subcommand,$cur" in
+	,--*)
+		__gitcomp '--ref'
+		;;
+	,*)
+		case "${words[cword-1]}" in
+		--ref)
+			__gitcomp_nl "$(__git_refs)"
+			;;
+		*)
+			__gitcomp "$subcommands --ref"
+			;;
+		esac
+		;;
+	add,--reuse-message=*|append,--reuse-message=*|\
+	add,--reedit-message=*|append,--reedit-message=*)
+		__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
+		;;
+	add,--*|append,--*)
+		__gitcomp '--file= --message= --reedit-message=
+				--reuse-message='
+		;;
+	copy,--*)
+		__gitcomp '--stdin'
+		;;
+	prune,--*)
+		__gitcomp '--dry-run --verbose'
+		;;
+	prune,*)
+		;;
+	*)
+		case "${words[cword-1]}" in
+		-m|-F)
+			;;
+		*)
+			__gitcomp_nl "$(__git_refs)"
+			;;
+		esac
+		;;
+	esac
+}
+
 _git_pull ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	__git_complete_strategy && return
 
-	if [ "$COMP_CWORD" = 2 ]; then
-		__gitcomp "$(__git_remotes)"
-	else
-		__gitcomp "$(__git_refs "${COMP_WORDS[2]}")"
-	fi
+	case "$cur" in
+	--*)
+		__gitcomp "
+			--rebase --no-rebase
+			$__git_merge_options
+			$__git_fetch_options
+		"
+		return
+		;;
+	esac
+	__git_complete_remote_or_refspec
 }
 
 _git_push ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-
-	if [ "$COMP_CWORD" = 2 ]; then
-		__gitcomp "$(__git_remotes)"
-	else
-		case "$cur" in
-		*:*)
-			local pfx=""
-			case "$COMP_WORDBREAKS" in
-			*:*) : great ;;
-			*)   pfx="${cur%%:*}:" ;;
-			esac
-
-			__gitcomp "$(__git_refs "${COMP_WORDS[2]}")" "$pfx" "${cur#*:}"
-			;;
-		+*)
-			__gitcomp "$(__git_refs)" + "${cur#+}"
-			;;
-		*)
-			__gitcomp "$(__git_refs)"
-			;;
-		esac
-	fi
+	case "$prev" in
+	--repo)
+		__gitcomp_nl "$(__git_remotes)"
+		return
+	esac
+	case "$cur" in
+	--repo=*)
+		__gitcomp_nl "$(__git_remotes)" "" "${cur##--repo=}"
+		return
+		;;
+	--*)
+		__gitcomp "
+			--all --mirror --tags --dry-run --force --verbose
+			--receive-pack= --repo= --set-upstream
+		"
+		return
+		;;
+	esac
+	__git_complete_remote_or_refspec
 }
 
 _git_rebase ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local dir="$(__gitdir)"
 	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
 	fi
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
-	-s|--strategy)
-		__gitcomp "$(__git_merge_strategies)"
-		return
-	esac
+	__git_complete_strategy && return
 	case "$cur" in
-	--strategy=*)
-		__gitcomp "$(__git_merge_strategies)" "" "${cur##--strategy=}"
+	--whitespace=*)
+		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
 		return
 		;;
 	--*)
-		__gitcomp "--onto --merge --strategy --interactive"
+		__gitcomp "
+			--onto --merge --strategy --interactive
+			--preserve-merges --stat --no-stat
+			--committer-date-is-author-date --ignore-date
+			--ignore-whitespace --whitespace=
+			--autosquash
+			"
+
 		return
 	esac
-	__gitcomp "$(__git_refs)"
+	__gitcomp_nl "$(__git_refs)"
 }
 
+_git_reflog ()
+{
+	local subcommands="show delete expire"
+	local subcommand="$(__git_find_on_cmdline "$subcommands")"
+
+	if [ -z "$subcommand" ]; then
+		__gitcomp "$subcommands"
+	else
+		__gitcomp_nl "$(__git_refs)"
+	fi
+}
+
+__git_send_email_confirm_options="always never auto cc compose"
+__git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
+
 _git_send_email ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
+	--confirm=*)
+		__gitcomp "
+			$__git_send_email_confirm_options
+			" "" "${cur##--confirm=}"
+		return
+		;;
+	--suppress-cc=*)
+		__gitcomp "
+			$__git_send_email_suppresscc_options
+			" "" "${cur##--suppress-cc=}"
+
+		return
+		;;
+	--smtp-encryption=*)
+		__gitcomp "ssl tls" "" "${cur##--smtp-encryption=}"
+		return
+		;;
 	--*)
-		__gitcomp "--bcc --cc --cc-cmd --chain-reply-to --compose
-			--dry-run --envelope-sender --from --identity
+		__gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to
+			--compose --confirm= --dry-run --envelope-sender
+			--from --identity
 			--in-reply-to --no-chain-reply-to --no-signed-off-by-cc
 			--no-suppress-from --no-thread --quiet
 			--signed-off-by-cc --smtp-pass --smtp-server
-			--smtp-server-port --smtp-ssl --smtp-user --subject
-			--suppress-cc --suppress-from --thread --to
+			--smtp-server-port --smtp-encryption= --smtp-user
+			--subject --suppress-cc= --suppress-from --thread --to
 			--validate --no-validate"
 		return
 		;;
@@ -1165,41 +1838,84 @@
 	COMPREPLY=()
 }
 
+_git_stage ()
+{
+	_git_add
+}
+
+__git_config_get_set_variables ()
+{
+	local prevword word config_file= c=$cword
+	while [ $c -gt 1 ]; do
+		word="${words[c]}"
+		case "$word" in
+		--global|--system|--file=*)
+			config_file="$word"
+			break
+			;;
+		-f|--file)
+			config_file="$word $prevword"
+			break
+			;;
+		esac
+		prevword=$word
+		c=$((--c))
+	done
+
+	git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
+	while read -r line
+	do
+		case "$line" in
+		*.*=*)
+			echo "${line/=*/}"
+			;;
+		esac
+	done
+}
+
 _git_config ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	local prv="${COMP_WORDS[COMP_CWORD-1]}"
-	case "$prv" in
+	case "$prev" in
 	branch.*.remote)
-		__gitcomp "$(__git_remotes)"
+		__gitcomp_nl "$(__git_remotes)"
 		return
 		;;
 	branch.*.merge)
-		__gitcomp "$(__git_refs)"
+		__gitcomp_nl "$(__git_refs)"
 		return
 		;;
 	remote.*.fetch)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.fetch}"
-		__gitcomp "$(__git_refs_remotes "$remote")"
+		if [ -z "$cur" ]; then
+			COMPREPLY=("refs/heads/")
+			return
+		fi
+		__gitcomp_nl "$(__git_refs_remotes "$remote")"
 		return
 		;;
 	remote.*.push)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.push}"
-		__gitcomp "$(git --git-dir="$(__gitdir)" \
+		__gitcomp_nl "$(git --git-dir="$(__gitdir)" \
 			for-each-ref --format='%(refname):%(refname)' \
 			refs/heads)"
 		return
 		;;
 	pull.twohead|pull.octopus)
-		__gitcomp "$(__git_merge_strategies)"
+		__git_compute_merge_strategies
+		__gitcomp "$__git_merge_strategies"
 		return
 		;;
-	color.branch|color.diff|color.status)
+	color.branch|color.diff|color.interactive|\
+	color.showbranch|color.status|color.ui)
 		__gitcomp "always never auto"
 		return
 		;;
+	color.pager)
+		__gitcomp "false true"
+		return
+		;;
 	color.*.*)
 		__gitcomp "
 			normal black red green yellow blue magenta cyan white
@@ -1207,6 +1923,30 @@
 			"
 		return
 		;;
+	help.format)
+		__gitcomp "man info web html"
+		return
+		;;
+	log.date)
+		__gitcomp "$__git_log_date_formats"
+		return
+		;;
+	sendemail.aliasesfiletype)
+		__gitcomp "mutt mailrc pine elm gnus"
+		return
+		;;
+	sendemail.confirm)
+		__gitcomp "$__git_send_email_confirm_options"
+		return
+		;;
+	sendemail.suppresscc)
+		__gitcomp "$__git_send_email_suppresscc_options"
+		return
+		;;
+	--get|--get-all|--unset|--unset-all)
+		__gitcomp_nl "$(__git_config_get_set_variables)"
+		return
+		;;
 	*.*)
 		COMPREPLY=()
 		return
@@ -1224,56 +1964,113 @@
 		return
 		;;
 	branch.*.*)
-		local pfx="${cur%.*}."
-		cur="${cur##*.}"
-		__gitcomp "remote merge mergeoptions" "$pfx" "$cur"
+		local pfx="${cur%.*}." cur_="${cur##*.}"
+		__gitcomp "remote merge mergeoptions rebase" "$pfx" "$cur_"
 		return
 		;;
 	branch.*)
-		local pfx="${cur%.*}."
-		cur="${cur#*.}"
-		__gitcomp "$(__git_heads)" "$pfx" "$cur" "."
+		local pfx="${cur%.*}." cur_="${cur#*.}"
+		__gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "."
+		return
+		;;
+	guitool.*.*)
+		local pfx="${cur%.*}." cur_="${cur##*.}"
+		__gitcomp "
+			argprompt cmd confirm needsfile noconsole norescan
+			prompt revprompt revunmerged title
+			" "$pfx" "$cur_"
+		return
+		;;
+	difftool.*.*)
+		local pfx="${cur%.*}." cur_="${cur##*.}"
+		__gitcomp "cmd path" "$pfx" "$cur_"
+		return
+		;;
+	man.*.*)
+		local pfx="${cur%.*}." cur_="${cur##*.}"
+		__gitcomp "cmd path" "$pfx" "$cur_"
+		return
+		;;
+	mergetool.*.*)
+		local pfx="${cur%.*}." cur_="${cur##*.}"
+		__gitcomp "cmd path trustExitCode" "$pfx" "$cur_"
+		return
+		;;
+	pager.*)
+		local pfx="${cur%.*}." cur_="${cur#*.}"
+		__git_compute_all_commands
+		__gitcomp_nl "$__git_all_commands" "$pfx" "$cur_"
 		return
 		;;
 	remote.*.*)
-		local pfx="${cur%.*}."
-		cur="${cur##*.}"
+		local pfx="${cur%.*}." cur_="${cur##*.}"
 		__gitcomp "
 			url proxy fetch push mirror skipDefaultUpdate
-			receivepack uploadpack tagopt
-			" "$pfx" "$cur"
+			receivepack uploadpack tagopt pushurl
+			" "$pfx" "$cur_"
 		return
 		;;
 	remote.*)
-		local pfx="${cur%.*}."
-		cur="${cur#*.}"
-		__gitcomp "$(__git_remotes)" "$pfx" "$cur" "."
+		local pfx="${cur%.*}." cur_="${cur#*.}"
+		__gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "."
+		return
+		;;
+	url.*.*)
+		local pfx="${cur%.*}." cur_="${cur##*.}"
+		__gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_"
 		return
 		;;
 	esac
 	__gitcomp "
+		add.ignoreErrors
+		advice.commitBeforeMerge
+		advice.detachedHead
+		advice.implicitIdentity
+		advice.pushNonFastForward
+		advice.resolveConflict
+		advice.statusHints
+		alias.
+		am.keepcr
+		apply.ignorewhitespace
 		apply.whitespace
 		branch.autosetupmerge
 		branch.autosetuprebase
+		browser.
 		clean.requireForce
 		color.branch
 		color.branch.current
 		color.branch.local
 		color.branch.plain
 		color.branch.remote
+		color.decorate.HEAD
+		color.decorate.branch
+		color.decorate.remoteBranch
+		color.decorate.stash
+		color.decorate.tag
 		color.diff
 		color.diff.commit
 		color.diff.frag
+		color.diff.func
 		color.diff.meta
 		color.diff.new
 		color.diff.old
 		color.diff.plain
 		color.diff.whitespace
+		color.grep
+		color.grep.context
+		color.grep.filename
+		color.grep.function
+		color.grep.linenumber
+		color.grep.match
+		color.grep.selected
+		color.grep.separator
 		color.interactive
+		color.interactive.error
 		color.interactive.header
 		color.interactive.help
 		color.interactive.prompt
 		color.pager
+		color.showbranch
 		color.status
 		color.status.added
 		color.status.changed
@@ -1282,20 +2079,29 @@
 		color.status.untracked
 		color.status.updated
 		color.ui
+		commit.status
 		commit.template
+		core.abbrev
+		core.askpass
+		core.attributesfile
 		core.autocrlf
 		core.bare
+		core.bigFileThreshold
 		core.compression
+		core.createObject
 		core.deltaBaseCacheLimit
 		core.editor
+		core.eol
 		core.excludesfile
 		core.fileMode
 		core.fsyncobjectfiles
 		core.gitProxy
 		core.ignoreCygwinFSTricks
 		core.ignoreStat
+		core.ignorecase
 		core.logAllRefUpdates
 		core.loosecompression
+		core.notesRef
 		core.packedGitLimit
 		core.packedGitWindowSize
 		core.pager
@@ -1305,6 +2111,7 @@
 		core.repositoryFormatVersion
 		core.safecrlf
 		core.sharedRepository
+		core.sparseCheckout
 		core.symlinks
 		core.trustctime
 		core.warnAmbiguousRefs
@@ -1312,15 +2119,30 @@
 		core.worktree
 		diff.autorefreshindex
 		diff.external
+		diff.ignoreSubmodules
 		diff.mnemonicprefix
+		diff.noprefix
 		diff.renameLimit
-		diff.renameLimit.
 		diff.renames
+		diff.suppressBlankEmpty
+		diff.tool
+		diff.wordRegex
+		difftool.
+		difftool.prompt
+		fetch.recurseSubmodules
 		fetch.unpackLimit
+		format.attach
+		format.cc
 		format.headers
 		format.numbered
 		format.pretty
+		format.signature
+		format.signoff
+		format.subjectprefix
 		format.suffix
+		format.thread
+		format.to
+		gc.
 		gc.aggressiveWindow
 		gc.auto
 		gc.autopacklimit
@@ -1331,6 +2153,7 @@
 		gc.rerereresolved
 		gc.rerereunresolved
 		gitcvs.allbinary
+		gitcvs.commitmsgannotation
 		gitcvs.dbTableNamePrefix
 		gitcvs.dbdriver
 		gitcvs.dbname
@@ -1339,6 +2162,7 @@
 		gitcvs.enabled
 		gitcvs.logfile
 		gitcvs.usecrlfattr
+		guitool.
 		gui.blamehistoryctx
 		gui.commitmsgwidth
 		gui.copyblamethreshold
@@ -1356,30 +2180,59 @@
 		http.lowSpeedLimit
 		http.lowSpeedTime
 		http.maxRequests
+		http.minSessions
 		http.noEPSV
+		http.postBuffer
 		http.proxy
 		http.sslCAInfo
 		http.sslCAPath
 		http.sslCert
+		http.sslCertPasswordProtected
 		http.sslKey
 		http.sslVerify
+		http.useragent
 		i18n.commitEncoding
 		i18n.logOutputEncoding
+		imap.authMethod
+		imap.folder
+		imap.host
+		imap.pass
+		imap.port
+		imap.preformattedHTML
+		imap.sslverify
+		imap.tunnel
+		imap.user
+		init.templatedir
 		instaweb.browser
 		instaweb.httpd
 		instaweb.local
 		instaweb.modulepath
 		instaweb.port
+		interactive.singlekey
 		log.date
+		log.decorate
 		log.showroot
+		mailmap.file
+		man.
 		man.viewer
+		merge.
 		merge.conflictstyle
 		merge.log
 		merge.renameLimit
+		merge.renormalize
 		merge.stat
 		merge.tool
 		merge.verbosity
+		mergetool.
 		mergetool.keepBackup
+		mergetool.keepTemporaries
+		mergetool.prompt
+		notes.displayRef
+		notes.rewrite.
+		notes.rewrite.amend
+		notes.rewrite.rebase
+		notes.rewriteMode
+		notes.rewriteRef
 		pack.compression
 		pack.deltaCacheLimit
 		pack.deltaCacheSize
@@ -1389,21 +2242,58 @@
 		pack.threads
 		pack.window
 		pack.windowMemory
+		pager.
+		pretty.
 		pull.octopus
 		pull.twohead
+		push.default
+		rebase.autosquash
+		rebase.stat
+		receive.autogc
 		receive.denyCurrentBranch
+		receive.denyDeleteCurrent
 		receive.denyDeletes
 		receive.denyNonFastForwards
 		receive.fsckObjects
 		receive.unpackLimit
+		receive.updateserverinfo
+		remotes.
 		repack.usedeltabaseoffset
 		rerere.autoupdate
 		rerere.enabled
+		sendemail.
+		sendemail.aliasesfile
+		sendemail.aliasfiletype
+		sendemail.bcc
+		sendemail.cc
+		sendemail.cccmd
+		sendemail.chainreplyto
+		sendemail.confirm
+		sendemail.envelopesender
+		sendemail.from
+		sendemail.identity
+		sendemail.multiedit
+		sendemail.signedoffbycc
+		sendemail.smtpdomain
+		sendemail.smtpencryption
+		sendemail.smtppass
+		sendemail.smtpserver
+		sendemail.smtpserveroption
+		sendemail.smtpserverport
+		sendemail.smtpuser
+		sendemail.suppresscc
+		sendemail.suppressfrom
+		sendemail.thread
+		sendemail.to
+		sendemail.validate
 		showbranch.default
 		status.relativePaths
 		status.showUntrackedFiles
+		status.submodulesummary
+		submodule.
 		tar.umask
 		transfer.unpackLimit
+		url.
 		user.email
 		user.name
 		user.signingkey
@@ -1414,8 +2304,8 @@
 
 _git_remote ()
 {
-	local subcommands="add rename rm show prune update"
-	local subcommand="$(__git_find_subcommand "$subcommands")"
+	local subcommands="add rename rm show prune update set-head"
+	local subcommand="$(__git_find_on_cmdline "$subcommands")"
 	if [ -z "$subcommand" ]; then
 		__gitcomp "$subcommands"
 		return
@@ -1423,17 +2313,13 @@
 
 	case "$subcommand" in
 	rename|rm|show|prune)
-		__gitcomp "$(__git_remotes)"
+		__gitcomp_nl "$(__git_remotes)"
 		;;
 	update)
 		local i c='' IFS=$'\n'
-		for i in $(git --git-dir="$(__gitdir)" config --list); do
-			case "$i" in
-			remotes.*)
-				i="${i#remotes.}"
-				c="$c ${i/=*/}"
-				;;
-			esac
+		for i in $(git --git-dir="$(__gitdir)" config --get-regexp "remotes\..*" 2>/dev/null); do
+			i="${i#remotes.}"
+			c="$c ${i/ */}"
 		done
 		__gitcomp "$c"
 		;;
@@ -1443,37 +2329,39 @@
 	esac
 }
 
+_git_replace ()
+{
+	__gitcomp_nl "$(__git_refs)"
+}
+
 _git_reset ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
-		__gitcomp "--merge --mixed --hard --soft"
+		__gitcomp "--merge --mixed --hard --soft --patch"
 		return
 		;;
 	esac
-	__gitcomp "$(__git_refs)"
+	__gitcomp_nl "$(__git_refs)"
 }
 
 _git_revert ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
 		return
 		;;
 	esac
-	__gitcomp "$(__git_refs)"
+	__gitcomp_nl "$(__git_refs)"
 }
 
 _git_rm ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -1487,16 +2375,11 @@
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "
-			--max-count= --max-age= --since= --after=
-			--min-age= --before= --until=
-			--no-merges
-			--author= --committer= --grep=
-			--all-match
-			--not --all
+			$__git_log_common_options
+			$__git_log_shortlog_options
 			--numbered --summary
 			"
 		return
@@ -1509,15 +2392,14 @@
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
-	--pretty=*)
-		__gitcomp "$__git_log_pretty_formats
-			" "" "${cur##--pretty=}"
+	--pretty=*|--format=*)
+		__gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
+			" "" "${cur#*=}"
 		return
 		;;
 	--*)
-		__gitcomp "--pretty=
+		__gitcomp "--pretty= --format= --abbrev-commit --oneline
 			$__git_diff_common_options
 			"
 		return
@@ -1528,13 +2410,13 @@
 
 _git_show_branch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--*)
 		__gitcomp "
 			--all --remotes --topo-order --current --more=
 			--list --independent --merge-base --no-name
-			--sha1-name --topics --reflog
+			--color --no-color
+			--sha1-name --sparse --topics --reflog
 			"
 		return
 		;;
@@ -1544,24 +2426,35 @@
 
 _git_stash ()
 {
+	local save_opts='--keep-index --no-keep-index --quiet --patch'
 	local subcommands='save list show apply clear drop pop create branch'
-	local subcommand="$(__git_find_subcommand "$subcommands")"
+	local subcommand="$(__git_find_on_cmdline "$subcommands")"
 	if [ -z "$subcommand" ]; then
-		__gitcomp "$subcommands"
+		case "$cur" in
+		--*)
+			__gitcomp "$save_opts"
+			;;
+		*)
+			if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then
+				__gitcomp "$subcommands"
+			else
+				COMPREPLY=()
+			fi
+			;;
+		esac
 	else
-		local cur="${COMP_WORDS[COMP_CWORD]}"
 		case "$subcommand,$cur" in
 		save,--*)
-			__gitcomp "--keep-index"
+			__gitcomp "$save_opts"
 			;;
-		apply,--*)
-			__gitcomp "--index"
+		apply,--*|pop,--*)
+			__gitcomp "--index --quiet"
 			;;
-		show,--*|drop,--*|pop,--*|branch,--*)
+		show,--*|drop,--*|branch,--*)
 			COMPREPLY=()
 			;;
 		show,*|apply,*|drop,*|pop,*|branch,*)
-			__gitcomp "$(git --git-dir="$(__gitdir)" stash list \
+			__gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \
 					| sed -n -e 's/:.*//p')"
 			;;
 		*)
@@ -1576,8 +2469,7 @@
 	__git_has_doubledash && return
 
 	local subcommands="add status init update summary foreach sync"
-	if [ -z "$(__git_find_subcommand "$subcommands")" ]; then
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
 		case "$cur" in
 		--*)
 			__gitcomp "--quiet --cached"
@@ -1595,9 +2487,10 @@
 	local subcommands="
 		init fetch clone rebase dcommit log find-rev
 		set-tree commit-diff info create-ignore propget
-		proplist show-ignore show-externals
+		proplist show-ignore show-externals branch tag blame
+		migrate mkdirs reset gc
 		"
-	local subcommand="$(__git_find_subcommand "$subcommands")"
+	local subcommand="$(__git_find_on_cmdline "$subcommands")"
 	if [ -z "$subcommand" ]; then
 		__gitcomp "$subcommands"
 	else
@@ -1606,19 +2499,20 @@
 			--follow-parent --authors-file= --repack=
 			--no-metadata --use-svm-props --use-svnsync-props
 			--log-window-size= --no-checkout --quiet
-			--repack-flags --user-log-author --localtime $remote_opts
+			--repack-flags --use-log-author --localtime
+			--ignore-paths= $remote_opts
 			"
 		local init_opts="
 			--template= --shared= --trunk= --tags=
 			--branches= --stdlayout --minimize-url
 			--no-metadata --use-svm-props --use-svnsync-props
-			--rewrite-root= $remote_opts
+			--rewrite-root= --prefix= --use-log-author
+			--add-author-from $remote_opts
 			"
 		local cmt_opts="
 			--edit --rmdir --find-copies-harder --copy-similarity=
 			"
 
-		local cur="${COMP_WORDS[COMP_CWORD]}"
 		case "$subcommand,$cur" in
 		fetch,--*)
 			__gitcomp "--revision= --fetch-all $fc_opts"
@@ -1632,27 +2526,28 @@
 		dcommit,--*)
 			__gitcomp "
 				--merge --strategy= --verbose --dry-run
-				--fetch-all --no-rebase $cmt_opts $fc_opts
+				--fetch-all --no-rebase --commit-url
+				--revision $cmt_opts $fc_opts
 				"
 			;;
 		set-tree,--*)
 			__gitcomp "--stdin $cmt_opts $fc_opts"
 			;;
 		create-ignore,--*|propget,--*|proplist,--*|show-ignore,--*|\
-		show-externals,--*)
+		show-externals,--*|mkdirs,--*)
 			__gitcomp "--revision="
 			;;
 		log,--*)
 			__gitcomp "
 				--limit= --revision= --verbose --incremental
 				--oneline --show-commit --non-recursive
-				--authors-file=
+				--authors-file= --color
 				"
 			;;
 		rebase,--*)
 			__gitcomp "
 				--merge --verbose --strategy= --local
-				--fetch-all $fc_opts
+				--fetch-all --dry-run $fc_opts
 				"
 			;;
 		commit-diff,--*)
@@ -1661,6 +2556,24 @@
 		info,--*)
 			__gitcomp "--url"
 			;;
+		branch,--*)
+			__gitcomp "--dry-run --message --tag"
+			;;
+		tag,--*)
+			__gitcomp "--dry-run --message"
+			;;
+		blame,--*)
+			__gitcomp "--git-format"
+			;;
+		migrate,--*)
+			__gitcomp "
+				--config-dir= --ignore-paths= --minimize
+				--no-auth-cache --username=
+				"
+			;;
+		reset,--*)
+			__gitcomp "--revision= --parent"
+			;;
 		*)
 			COMPREPLY=()
 			;;
@@ -1671,11 +2584,11 @@
 _git_tag ()
 {
 	local i c=1 f=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-v)
-			__gitcomp "$(__git_tags)"
+			__gitcomp_nl "$(__git_tags)"
 			return
 			;;
 		-f)
@@ -1685,29 +2598,49 @@
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "$prev" in
 	-m|-F)
 		COMPREPLY=()
 		;;
 	-*|tag)
 		if [ $f = 1 ]; then
-			__gitcomp "$(__git_tags)"
+			__gitcomp_nl "$(__git_tags)"
 		else
 			COMPREPLY=()
 		fi
 		;;
 	*)
-		__gitcomp "$(__git_refs)"
+		__gitcomp_nl "$(__git_refs)"
 		;;
 	esac
 }
 
+_git_whatchanged ()
+{
+	_git_log
+}
+
 _git ()
 {
 	local i c=1 command __git_dir
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	if [[ -n ${ZSH_VERSION-} ]]; then
+		emulate -L bash
+		setopt KSH_TYPESET
+
+		# workaround zsh's bug that leaves 'words' as a special
+		# variable in versions < 4.3.12
+		typeset -h words
+
+		# workaround zsh's bug that quotes spaces in the COMPREPLY
+		# array if IFS doesn't contain spaces.
+		typeset -h IFS
+	fi
+
+	local cur words cword prev
+	_get_comp_words_by_ref -n =: cur words cword prev
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
@@ -1719,7 +2652,7 @@
 	done
 
 	if [ -z "$command" ]; then
-		case "${COMP_WORDS[COMP_CWORD]}" in
+		case "$cur" in
 		--*)   __gitcomp "
 			--paginate
 			--no-pager
@@ -1727,84 +2660,60 @@
 			--bare
 			--version
 			--exec-path
+			--html-path
 			--work-tree=
+			--namespace=
 			--help
 			"
 			;;
-		*)     __gitcomp "$(__git_porcelain_commands) $(__git_aliases)" ;;
+		*)     __git_compute_porcelain_commands
+		       __gitcomp "$__git_porcelain_commands $(__git_aliases)" ;;
 		esac
 		return
 	fi
 
-	local expansion=$(__git_aliased_command "$command")
-	[ "$expansion" ] && command="$expansion"
+	local completion_func="_git_${command//-/_}"
+	declare -f $completion_func >/dev/null && $completion_func && return
 
-	case "$command" in
-	am)          _git_am ;;
-	add)         _git_add ;;
-	apply)       _git_apply ;;
-	archive)     _git_archive ;;
-	bisect)      _git_bisect ;;
-	bundle)      _git_bundle ;;
-	branch)      _git_branch ;;
-	checkout)    _git_checkout ;;
-	cherry)      _git_cherry ;;
-	cherry-pick) _git_cherry_pick ;;
-	clean)       _git_clean ;;
-	clone)       _git_clone ;;
-	commit)      _git_commit ;;
-	config)      _git_config ;;
-	describe)    _git_describe ;;
-	diff)        _git_diff ;;
-	fetch)       _git_fetch ;;
-	format-patch) _git_format_patch ;;
-	gc)          _git_gc ;;
-	grep)        _git_grep ;;
-	help)        _git_help ;;
-	init)        _git_init ;;
-	log)         _git_log ;;
-	ls-files)    _git_ls_files ;;
-	ls-remote)   _git_ls_remote ;;
-	ls-tree)     _git_ls_tree ;;
-	merge)       _git_merge;;
-	mergetool)   _git_mergetool;;
-	merge-base)  _git_merge_base ;;
-	mv)          _git_mv ;;
-	name-rev)    _git_name_rev ;;
-	pull)        _git_pull ;;
-	push)        _git_push ;;
-	rebase)      _git_rebase ;;
-	remote)      _git_remote ;;
-	reset)       _git_reset ;;
-	revert)      _git_revert ;;
-	rm)          _git_rm ;;
-	send-email)  _git_send_email ;;
-	shortlog)    _git_shortlog ;;
-	show)        _git_show ;;
-	show-branch) _git_show_branch ;;
-	stash)       _git_stash ;;
-	stage)       _git_add ;;
-	submodule)   _git_submodule ;;
-	svn)         _git_svn ;;
-	tag)         _git_tag ;;
-	whatchanged) _git_log ;;
-	*)           COMPREPLY=() ;;
-	esac
+	local expansion=$(__git_aliased_command "$command")
+	if [ -n "$expansion" ]; then
+		completion_func="_git_${expansion//-/_}"
+		declare -f $completion_func >/dev/null && $completion_func
+	fi
 }
 
 _gitk ()
 {
+	if [[ -n ${ZSH_VERSION-} ]]; then
+		emulate -L bash
+		setopt KSH_TYPESET
+
+		# workaround zsh's bug that leaves 'words' as a special
+		# variable in versions < 4.3.12
+		typeset -h words
+
+		# workaround zsh's bug that quotes spaces in the COMPREPLY
+		# array if IFS doesn't contain spaces.
+		typeset -h IFS
+	fi
+
+	local cur words cword prev
+	_get_comp_words_by_ref -n =: cur words cword prev
+
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	local g="$(git rev-parse --git-dir 2>/dev/null)"
+	local g="$(__gitdir)"
 	local merge=""
-	if [ -f $g/MERGE_HEAD ]; then
+	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
 	case "$cur" in
 	--*)
-		__gitcomp "--not --all $merge"
+		__gitcomp "
+			$__git_log_common_options
+			$__git_log_gitk_options
+			$merge
+			"
 		return
 		;;
 	esac
@@ -1815,3 +2724,42 @@
 	|| complete -o default -o nospace -F _git git
 complete -o bashdefault -o default -o nospace -F _gitk gitk 2>/dev/null \
 	|| complete -o default -o nospace -F _gitk gitk
+
+# The following are necessary only for Cygwin, and only are needed
+# when the user has tab-completed the executable name and consequently
+# included the '.exe' suffix.
+#
+if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
+complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \
+	|| complete -o default -o nospace -F _git git.exe
+fi
+
+if [[ -n ${ZSH_VERSION-} ]]; then
+	__git_shopt () {
+		local option
+		if [ $# -ne 2 ]; then
+			echo "USAGE: $0 (-q|-s|-u) <option>" >&2
+			return 1
+		fi
+		case "$2" in
+		nullglob)
+			option="$2"
+			;;
+		*)
+			echo "$0: invalid option: $2" >&2
+			return 1
+		esac
+		case "$1" in
+		-q)	setopt | grep -q "$option" ;;
+		-u)	unsetopt "$option" ;;
+		-s)	setopt "$option" ;;
+		*)
+			echo "$0: invalid flag: $1" >&2
+			return 1
+		esac
+	}
+else
+	__git_shopt () {
+		shopt "$@"
+	}
+fi
diff --git a/install.sh b/install.sh
index 92f3d7c..19f6f52 100755
--- a/install.sh
+++ b/install.sh
@@ -36,18 +36,19 @@
 
 function load_some() {
     file_type=$1
-    for file in `ls $BASH_IT/${file_type}/available/[^_]*`
+    for path in `ls $BASH_IT/${file_type}/available/[^_]*`
     do
       if [ ! -d "$BASH_IT/$file_type/enabled" ]
       then
         mkdir "$BASH_IT/$file_type/enabled"
       fi
+      file_name=$(basename "$path")
       while true
       do
-        read -p "Would you like to enable the ${file%.*.*} $file_type? [Y/N] " RESP
+        read -p "Would you like to enable the ${file_name%%.*} $file_type? [Y/N] " RESP
         case $RESP in
         [yY])
-          ln -s "$BASH_IT/$file_type/available/$file" "$BASH_IT/$file_type/enabled"
+          ln -s "$path" "$BASH_IT/$file_type/enabled"
           break
           ;;
         [nN])
diff --git a/lib/composure.sh b/lib/composure.sh
index 1bbf400..beaf13a 100644
--- a/lib/composure.sh
+++ b/lib/composure.sh
@@ -1,191 +1,27 @@
 # composure - by erichs
-# light-hearted shell functions for intuitive shell programming
+# light-hearted functions for intuitive shell programming
 
 # install: source this script in your ~/.profile or ~/.${SHELL}rc script
 
 # latest source available at http://git.io/composure
 # known to work on bash, zsh, and ksh93
 
-# define default metadata keywords:
-about ()   { :; }
-group ()   { :; }
-param ()   { :; }
-author ()  { :; }
-example () { :; }
+# 'plumbing' functions
 
-cite ()
+composure_keywords ()
 {
-    about creates a new meta keyword for use in your functions
-    param 1: keyword
-    example $ cite url
-    example $ url http://somewhere.com
-    group composure
-
-    # this is the storage half of the 'metadata' system:
-    # we create dynamic metadata keywords with function wrappers around
-    # the NOP command, ':'
-
-    # anything following a keyword will get parsed as a positional
-    # parameter, but stay resident in the ENV. As opposed to shell
-    # comments, '#', which do not get parsed, thus are not available
-    # at runtime.
-
-    # a BIG caveat--your metadata must be roughly parsable: do not use
-    # contractions, and consider single or double quoting if it contains
-    # non-alphanumeric characters
-
-    typeset keyword
-    for keyword in $*; do
-        eval "function $keyword { :; }"
-    done
-}
-
-draft ()
-{
-    about wraps last command into a new function
-    param 1: name to give function
-    example $ ls
-    example $ draft list
-    example $ list
-    group composure
-
-    typeset func=$1
-    eval 'function ' $func ' { ' $(fc -ln -1) '; }'
-    typeset file=$(mktemp /tmp/draft.XXXX)
-    typeset -f $func > $file
-    transcribe $func $file draft
-    rm $file 2>/dev/null
-}
-
-glossary ()
-{
-    about displays help summary for all functions, or summary for a group of functions
-    param 1: optional, group name
-    example $ glossary
-    example $ glossary misc
-    group composure
-
-    typeset targetgroup=${1:-}
-
-    for func in $(listfunctions); do
-        typeset about="$(metafor $func about)"
-        if [ -n "$targetgroup" ]; then
-            typeset group="$(metafor $func group)"
-            if [ "$group" != "$targetgroup" ]; then
-                continue  # skip non-matching groups, if specified
-            fi
-        fi
-        letterpress "$about" $func
-    done
+    echo "about author example group param version"
 }
 
 letterpress ()
 {
-    typeset metadata=$1 leftcol=${2:- } rightcol
+    typeset rightcol="$1" leftcol="${2:- }"
 
-    if [ -z "$metadata" ]; then
+    if [ -z "$rightcol" ]; then
         return
     fi
 
-    OLD=$IFS; IFS=$'\n'
-    for rightcol in $metadata; do
-        printf "%-20s%s\n" $leftcol $rightcol
-    done
-    IFS=$OLD
-}
-
-listfunctions ()
-{
-    # unfortunately, there does not seem to be a easy, portable way to list just the
-    # names of the defined shell functions...
-
-    # here's a hack I modified from a StackOverflow post:
-    # we loop over the ps listing for the current process ($$), and print the last column (CMD)
-    # stripping any leading hyphens bash sometimes throws in there
-
-    typeset x ans
-    typeset this=$(for x in $(ps -p $$); do ans=$x; done; printf "%s\n" $ans | sed 's/^-*//')
-    case "$this" in
-        bash)
-            typeset -F | awk '{print $3}'
-            ;;
-        *)
-            # trim everything following '()' in ksh
-            typeset +f | sed 's/().*$//'
-            ;;
-    esac
-}
-
-metafor ()
-{
-    about prints function metadata associated with keyword
-    param 1: function name
-    param 2: meta keyword
-    example $ metafor glossary example
-    group composure
-    typeset func=$1 keyword=$2
-
-    # this sed-fu is the retrieval half of the 'metadata' system:
-    # first 'cat' the function definition,
-    # then 'grep' for the metadata keyword, and
-    # then parse and massage the matching line
-    typeset -f $func | sed -n "s/;$//;s/^[ 	]*$keyword \([^([].*\)*$/\1/p"
-}
-
-reference ()
-{
-    about displays apidoc help for a specific function
-    param 1: function name
-    example $ reference revise
-    group composure
-
-    typeset func=$1
-
-    typeset about="$(metafor $func about)"
-    letterpress "$about" $func
-
-    typeset params="$(metafor $func param)"
-    if [ -n "$params" ]; then
-        printf "parameters:\n"
-        letterpress "$params"
-    fi
-
-    typeset examples="$(metafor $func example)"
-    if [ -n "$examples" ]; then
-        printf "examples:\n"
-        letterpress "$examples"
-    fi
-}
-
-revise ()
-{
-    about loads function into editor for revision
-    param 1: name of function
-    example $ revise myfunction
-    group composure
-
-    typeset func=$1
-    typeset temp=$(mktemp /tmp/revise.XXXX)
-
-    # populate tempfile...
-    if [ -f ~/.composure/$func.inc ]; then
-        # ...with contents of latest git revision...
-        cat ~/.composure/$func.inc >> $temp
-    else
-        # ...or from ENV if not previously versioned
-        typeset -f $func >> $temp
-    fi
-
-    if [ -z "$EDITOR" ]
-    then
-      typeset EDITOR=vi
-    fi
-
-    $EDITOR $temp
-    source $temp
-
-    transcribe $func $temp revise
-    rm $temp
+    printf "%-20s%s\n" "$leftcol" "$rightcol"
 }
 
 transcribe ()
@@ -246,6 +82,338 @@
     fi
 }
 
+transcribe ()
+{
+    typeset func=$1
+    typeset file=$2
+    typeset operation="$3"
+
+    if git --version >/dev/null 2>&1; then
+        if [ -d ~/.composure ]; then
+            (
+                cd ~/.composure
+                if git rev-parse 2>/dev/null; then
+                    if [ ! -f $file ]; then
+                        printf "%s\n" "Oops! Couldn't find $file to version it for you..."
+                        return
+                    fi
+                    cp $file ~/.composure/$func.inc
+                    git add --all .
+                    git commit -m "$operation $func"
+                fi
+            )
+        else
+            if [ "$USE_COMPOSURE_REPO" = "0" ]; then
+                return  # if you say so...
+            fi
+            printf "%s\n" "I see you don't have a ~/.composure repo..."
+            typeset input
+            typeset valid=0
+            while [ $valid != 1 ]; do
+                printf "\n%s" 'would you like to create one? y/n: '
+                read input
+                case $input in
+                    y|yes|Y|Yes|YES)
+                        (
+                            echo 'creating git repository for your functions...'
+                            mkdir ~/.composure
+                            cd ~/.composure
+                            git init
+                            echo "composure stores your function definitions here" > README.txt
+                            git add README.txt
+                            git commit -m 'initial commit'
+                        )
+                        # if at first you don't succeed...
+                        transcribe "$func" "$file" "$operation"
+                        valid=1
+                        ;;
+                    n|no|N|No|NO)
+                        printf "%s\n" "ok. add 'export USE_COMPOSURE_REPO=0' to your startup script to disable this message."
+                        valid=1
+                    ;;
+                    *)
+                        printf "%s\n" "sorry, didn't get that..."
+                    ;;
+                esac
+            done
+       fi
+    fi
+}
+
+typeset_functions ()
+{
+    # unfortunately, there does not seem to be a easy, portable way to list just the
+    # names of the defined shell functions...
+
+    # first, determine our shell:
+    typeset shell
+    if [ -n "$SHELL" ]; then
+        shell=$(basename $SHELL)  # we assume this is set correctly!
+    else
+        # we'll have to try harder
+        # here's a hack I modified from a StackOverflow post:
+        # we loop over the ps listing for the current process ($$), and print the last column (CMD)
+        # stripping any leading hyphens bash sometimes throws in there
+        typeset x ans
+        typeset this=$(for x in $(ps -p $$); do ans=$x; done; printf "%s\n" $ans | sed 's/^-*//')
+        typeset shell=$(basename $this)  # e.g. /bin/bash => bash
+    fi
+    case "$shell" in
+        bash)
+            typeset -F | awk '{print $3}'
+            ;;
+        *)
+            # trim everything following '()' in ksh
+            typeset +f | sed 's/().*$//'
+            ;;
+    esac
+}
+
+
+# bootstrap metadata keywords for porcelain functions
+for f in $(composure_keywords)
+do
+    eval "$f() { :; }"
+done
+unset f
+
+
+# 'porcelain' functions
+
+cite ()
+{
+    about creates one or more meta keywords for use in your functions
+    param one or more keywords
+    example '$ cite url username'
+    example '$ url http://somewhere.com'
+    example '$ username alice'
+    group composure
+
+    # this is the storage half of the 'metadata' system:
+    # we create dynamic metadata keywords with function wrappers around
+    # the NOP command, ':'
+
+    # anything following a keyword will get parsed as a positional
+    # parameter, but stay resident in the ENV. As opposed to shell
+    # comments, '#', which do not get parsed and are not available
+    # at runtime.
+
+    # a BIG caveat--your metadata must be roughly parsable: do not use
+    # contractions, and consider single or double quoting if it contains
+    # non-alphanumeric characters
+
+    if [ -z "$1" ]; then
+        printf '%s\n' 'missing parameter(s)'
+        reference cite
+        return
+    fi
+
+    typeset keyword
+    for keyword in $*; do
+        eval "$keyword() { :; }"
+    done
+}
+
+draft ()
+{
+    about wraps command from history into a new function, default is last command
+    param 1: name to give function
+    param 2: optional history line number
+    example '$ ls'
+    example '$ draft list'
+    example '$ draft newfunc 1120  # wraps command at history line 1120 in newfunc()'
+    group composure
+
+    typeset func=$1
+    typeset num=$2
+    typeset cmd
+
+    if [ -z "$func" ]; then
+        printf '%s\n' 'missing parameter(s)'
+        reference draft
+        return
+    fi
+
+    # aliases bind tighter than function names, disallow them
+    if [ -n "$(type -a $func 2>/dev/null | grep 'is.*alias')" ]; then
+        printf '%s\n' "sorry, $(type -a $func). please choose another name."
+        return
+    fi
+
+    if [ -z "$num" ]; then
+        # parse last command from fc output
+        # some versions of 'fix command, fc' need corrective lenses...
+        typeset myopic=$(fc -ln -1 | grep draft)
+        typeset lines=1
+        if [ -n "$myopic" ]; then
+            lines=2
+        fi
+        cmd=$(fc -ln -$lines | head -1 | sed 's/^[[:blank:]]*//')
+    else
+        # parse command from history line number
+        cmd=$(eval "history | grep '^[[:blank:]]*$num' | head -1" | sed 's/^[[:blank:][:digit:]]*//')
+    fi
+    eval "$func() { $cmd; }"
+    typeset file=$(mktemp /tmp/draft.XXXX)
+    typeset -f $func > $file
+    transcribe $func $file draft
+    rm $file 2>/dev/null
+}
+
+glossary ()
+{
+    about displays help summary for all functions, or summary for a group of functions
+    param 1: optional, group name
+    example '$ glossary'
+    example '$ glossary misc'
+    group composure
+
+    typeset targetgroup=${1:-}
+
+    for func in $(typeset_functions); do
+        if [ -n "$targetgroup" ]; then
+            typeset group="$(typeset -f $func | metafor group)"
+            if [ "$group" != "$targetgroup" ]; then
+                continue  # skip non-matching groups, if specified
+            fi
+        fi
+        typeset about="$(typeset -f $func | metafor about)"
+        letterpress "$about" $func
+    done
+}
+
+metafor ()
+{
+    about prints function metadata associated with keyword
+    param 1: meta keyword
+    example '$ typeset -f glossary | metafor example'
+    group composure
+
+    typeset keyword=$1
+
+    if [ -z "$keyword" ]; then
+        printf '%s\n' 'missing parameter(s)'
+        reference metafor
+        return
+    fi
+
+    # this sed-fu is the retrieval half of the 'metadata' system:
+    # 'grep' for the metadata keyword, and then parse/filter the matching line
+
+    # grep keyword # strip trailing '|"|; # ignore thru keyword and leading '|"
+    sed -n "/$keyword / s/['\";]*$//;s/^[ 	]*$keyword ['\"]*\([^([].*\)*$/\1/p"
+}
+
+reference ()
+{
+    about displays apidoc help for a specific function
+    param 1: function name
+    example '$ reference revise'
+    group composure
+
+    typeset func=$1
+    if [ -z "$func" ]; then
+        printf '%s\n' 'missing parameter(s)'
+        reference reference
+        return
+    fi
+
+    typeset line
+
+    typeset about="$(typeset -f $func | metafor about)"
+    letterpress "$about" $func
+
+    typeset author="$(typeset -f $func | metafor author)"
+    if [ -n "$author" ]; then
+        letterpress "$author" 'author:'
+    fi
+
+    typeset version="$(typeset -f $func | metafor version)"
+    if [ -n "$version" ]; then
+        letterpress "$version" 'version:'
+    fi
+
+    if [ -n "$(typeset -f $func | metafor param)" ]; then
+        printf "parameters:\n"
+        typeset -f $func | metafor param | while read line
+        do
+            letterpress "$line"
+        done
+    fi
+
+    if [ -n "$(typeset -f $func | metafor example)" ]; then
+        printf "examples:\n"
+        typeset -f $func | metafor example | while read line
+        do
+            letterpress "$line"
+        done
+    fi
+}
+
+revise ()
+{
+    about loads function into editor for revision
+    param 1: name of function
+    example '$ revise myfunction'
+    group composure
+
+    typeset func=$1
+    typeset temp=$(mktemp /tmp/revise.XXXX)
+
+    if [ -z "$func" ]; then
+        printf '%s\n' 'missing parameter(s)'
+        reference revise
+        return
+    fi
+
+    # populate tempfile...
+    if [ -f ~/.composure/$func.inc ]; then
+        # ...with contents of latest git revision...
+        cat ~/.composure/$func.inc >> $temp
+    else
+        # ...or from ENV if not previously versioned
+        typeset -f $func >> $temp
+    fi
+
+    if [ -z "$EDITOR" ]
+    then
+      typeset EDITOR=vi
+    fi
+
+    $EDITOR $temp
+    . $temp  # source edited file
+
+    transcribe $func $temp revise
+    rm $temp
+}
+
+write ()
+{
+    about writes one or more composed function definitions to stdout
+    param one or more function names
+    example '$ write finddown foo'
+    example '$ write finddown'
+    group composure
+
+    if [ -z "$1" ]; then
+        printf '%s\n' 'missing parameter(s)'
+        reference write
+        return
+    fi
+
+# bootstrap metadata
+cat <<END
+for f in $(composure_keywords)
+do
+    eval "\$f() { :; }"
+done
+unset f
+END
+
+    # include cite() to enable custom keywords
+    typeset -f cite $*
+}
+
 : <<EOF
 License: The MIT License
 
diff --git a/lib/helpers.bash b/lib/helpers.bash
index ec6587e..d0c16b8 100644
--- a/lib/helpers.bash
+++ b/lib/helpers.bash
@@ -28,3 +28,147 @@
 function reload_plugins() {
   _load_bash_it_files "plugins"
 }
+
+bash-it-plugins ()
+{
+    about 'summarizes available bash_it plugins'
+    group 'lib'
+
+    typeset f
+    typeset enabled
+    printf "%-20s%-10s%s\n" 'Plugin' 'Enabled?' 'Description'
+    for f in $BASH_IT/plugins/available/*.bash
+    do
+        if [ -e $BASH_IT/plugins/enabled/$(basename $f) ]; then
+            enabled='x'
+        else
+            enabled=' '
+        fi
+        printf "%-20s%-10s%s\n" "$(basename $f | cut -d'.' -f1)" "  [$enabled]" "$(cat $f | metafor about-plugin)"
+    done
+    printf '\n%s\n' 'to enable a plugin, do:'
+    printf '%s\n' '$ enable-plugin  <plugin name> -or- $ enable-plugin all'
+    printf '\n%s\n' 'to disable a plugin, do:'
+    printf '%s\n' '$ disable-plugin <plugin name> -or- $ disable-plugin all'
+}
+
+disable-plugin ()
+{
+    about 'disables bash_it plugin'
+    param '1: plugin name'
+    example '$ disable-plugin rvm'
+    group 'lib'
+
+    if [ -z "$1" ]; then
+        reference disable-plugin
+        return
+    fi
+
+    if [ "$1" = "all" ]; then
+        typeset f plugin
+        for f in $BASH_IT/plugins/available/*.bash
+        do
+            plugin=$(basename $f)
+            if [ -e $BASH_IT/plugins/enabled/$plugin ]; then
+                rm $BASH_IT/plugins/enabled/$(basename $plugin)
+            fi
+        done
+    else
+        typeset plugin=$(ls $BASH_IT/plugins/enabled/$1.*bash 2>/dev/null | head -1)
+        if [ ! -h $plugin ]; then
+            printf '%s\n' 'sorry, that does not appear to be an enabled plugin.'
+            return
+        fi
+        rm $BASH_IT/plugins/enabled/$(basename $plugin)
+    fi
+
+    printf '%s\n' "$1 disabled."
+}
+
+enable-plugin ()
+{
+    about 'enables bash_it plugin'
+    param '1: plugin name'
+    example '$ enable-plugin rvm'
+    group 'lib'
+
+    if [ -z "$1" ]; then
+        reference enable-plugin
+        return
+    fi
+
+    if [ "$1" = "all" ]; then
+        typeset f plugin
+        for f in $BASH_IT/plugins/available/*.bash
+        do
+            plugin=$(basename $f)
+            if [ ! -h $BASH_IT/plugins/enabled/$plugin ]; then
+                ln -s $BASH_IT/plugins/available/$plugin $BASH_IT/plugins/enabled/$plugin
+            fi
+        done
+    else
+        typeset plugin=$(ls $BASH_IT/plugins/available/$1.*bash 2>/dev/null | head -1)
+        if [ -z "$plugin" ]; then
+            printf '%s\n' 'sorry, that does not appear to be an available plugin.'
+            return
+        fi
+
+        plugin=$(basename $plugin)
+        if [ -e $BASH_IT/plugins/enabled/$plugin ]; then
+            printf '%s\n' "$1 is already enabled."
+            return
+        fi
+
+        ln -s $BASH_IT/plugins/available/$plugin $BASH_IT/plugins/enabled/$plugin
+    fi
+
+    printf '%s\n' "$1 enabled."
+}
+
+plugins-help ()
+{
+    about 'summarize all functions defined by enabled bash-it plugins'
+    group 'lib'
+
+    # display a brief progress message...
+    printf '%s' 'please wait, building help...'
+    typeset grouplist=$(mktemp /tmp/grouplist.XXXX)
+    typeset func
+    for func in $(typeset_functions)
+    do
+        typeset group="$(typeset -f $func | metafor group)"
+        if [ -z "$group" ]; then
+            group='misc'
+        fi
+        typeset about="$(typeset -f $func | metafor about)"
+        letterpress "$about" $func >> $grouplist.$group
+        echo $grouplist.$group >> $grouplist
+    done
+    # clear progress message
+    printf '\r%s\n' '                              '
+    typeset group
+    typeset gfile
+    for gfile in $(cat $grouplist | sort | uniq)
+    do
+        printf '%s\n' "${gfile##*.}:"
+        cat $gfile
+        printf '\n'
+        rm $gfile 2> /dev/null
+    done | less
+    rm $grouplist 2> /dev/null
+}
+
+all_groups ()
+{
+    about 'displays all unique metadata groups'
+    group 'lib'
+
+    typeset func
+    typeset file=$(mktemp /tmp/composure.XXXX)
+    for func in $(typeset_functions)
+    do
+        typeset -f $func | metafor group >> $file
+    done
+    cat $file | sort | uniq
+    rm $file
+}
diff --git a/plugins/available/_xterm.plugins.bash b/plugins/available/_xterm.plugin.bash
similarity index 85%
rename from plugins/available/_xterm.plugins.bash
rename to plugins/available/_xterm.plugin.bash
index 9c8c668..b3810e7 100644
--- a/plugins/available/_xterm.plugins.bash
+++ b/plugins/available/_xterm.plugin.bash
@@ -6,6 +6,9 @@
 #
 # [issue 108]: https://github.com/revans/bash-it/issues/108
 
+cite about-plugin
+about-plugin 'automatically set your xterm title with host and location info'
+
 set_xterm_title () {
     local title="$1"
     echo -ne "\e]0;$title\007"
diff --git a/plugins/available/base.plugin.bash b/plugins/available/base.plugin.bash
old mode 100755
new mode 100644
index 137b812..e07401b
--- a/plugins/available/base.plugin.bash
+++ b/plugins/available/base.plugin.bash
@@ -1,24 +1,26 @@
-#!/usr/bin/env bash
-
-# For generic functions.
+cite about-plugin
+about-plugin 'miscellaneous tools'
 
 ips ()
 {
-    about display all ip addresses for this host
+    about 'display all ip addresses for this host'
+    group 'base'
     ifconfig | grep "inet " | awk '{ print $2 }'
 }
 
 down4me ()
 {
-    about checks whether a website is down for you, or everybody
-    param 1: website url
+    about 'checks whether a website is down for you, or everybody'
+    param '1: website url'
     example '$ down4me http://www.google.com'
+    group 'base'
     curl -s "http://www.downforeveryoneorjustme.com/$1" | sed '/just you/!d;s/<[^>]*>//g'
 }
 
 myip ()
 {
-    about displays your ip address, as seen by the Internet
+    about 'displays your ip address, as seen by the Internet'
+    group 'base'
     res=$(curl -s checkip.dyndns.org | grep -Eo '[0-9\.]+')
     echo -e "Your public IP is: ${echo_bold_green} $res ${echo_normal}"
 }
@@ -26,9 +28,10 @@
 
 pickfrom ()
 {
-    about picks random line from file
-    param 1: filename
+    about 'picks random line from file'
+    param '1: filename'
     example '$ pickfrom /usr/share/dict/words'
+    group 'base'
     local file=$1
     [ -z "$file" ] && reference $FUNCNAME && return
     length=$(cat $file | wc -l)
@@ -38,11 +41,12 @@
 
 pass ()
 {
-    about generates random password from dictionary words
-    param optional integer length
-    param if unset, defaults to 4
+    about 'generates random password from dictionary words'
+    param 'optional integer length'
+    param 'if unset, defaults to 4'
     example '$ pass'
     example '$ pass 6'
+    group 'base'
     local i pass length=${1:-4}
     pass=$(echo $(for i in $(eval echo "{1..$length}"); do pickfrom /usr/share/dict/words; done))
     echo "With spaces (easier to memorize): $pass"
@@ -51,9 +55,10 @@
 
 pmdown ()
 {
-    about preview markdown file in a browser
-    param 1: markdown file
+    about 'preview markdown file in a browser'
+    param '1: markdown file'
     example '$ pmdown README.md'
+    group 'base'
     if command -v markdown &>/dev/null
     then
       markdown $1 | browser
@@ -64,54 +69,62 @@
 
 mkcd ()
 {
-    about make a directory and cd into it
-    param path to create
+    about 'make a directory and cd into it'
+    param 'path to create'
     example '$ mkcd foo'
     example '$ mkcd /tmp/img/photos/large'
+    group 'base'
     mkdir -p "$*"
     cd "$*"
 }
 
 lsgrep ()
 {
-    about search through directory contents with grep
+    about 'search through directory contents with grep'
+    group 'base'
     ls | grep "$*"
 }
 
 
 pman ()
 {
-    about view man documentation in Preview
-    param 1: man page to view
+    about 'view man documentation in Preview'
+    param '1: man page to view'
     example '$ pman bash'
+    group 'base'
     man -t "${1}" | open -f -a $PREVIEW
 }
 
 
 pcurl ()
 {
-    about download file and Preview it
-    param 1: download URL
+    about 'download file and Preview it'
+    param '1: download URL'
     example '$ pcurl http://www.irs.gov/pub/irs-pdf/fw4.pdf'
+    group 'base'
     curl "${1}" | open -f -a $PREVIEW
 }
 
 pri ()
 {
-    about display information about Ruby classes, modules, or methods, in Preview
-    param 1: Ruby method, module, or class
+    about 'display information about Ruby classes, modules, or methods, in Preview'
+    param '1: Ruby method, module, or class'
     example '$ pri Array'
+    group 'base'
     ri -T "${1}" | open -f -a $PREVIEW
 }
 
 quiet ()
 {
+    about 'what *does* this do?'
+    group 'base'
 	$* &> /dev/null &
 }
 
 banish-cookies ()
 {
-    about redirect .adobe and .macromedia files to /dev/null
+    about 'redirect .adobe and .macromedia files to /dev/null'
+    group 'base'
 	rm -r ~/.macromedia ~/.adobe
 	ln -s /dev/null ~/.adobe
 	ln -s /dev/null ~/.macromedia
@@ -119,8 +132,9 @@
 
 usage ()
 {
-    about disk usage per directory, in Mac OS X and Linux
-    param 1: directory name
+    about 'disk usage per directory, in Mac OS X and Linux'
+    param '1: directory name'
+    group 'base'
     if [ $(uname) = "Darwin" ]; then
         if [ -n $1 ]; then
             du -hd $1
@@ -154,35 +168,19 @@
 
 command_exists ()
 {
-    about checks for existence of a command
-    param 1: command to check
+    about 'checks for existence of a command'
+    param '1: command to check'
     example '$ command_exists ls && echo exists'
+    group 'base'
     type "$1" &> /dev/null ;
 }
 
-plugins-help ()
-{
-    about list all plugins and functions defined by bash-it
-    echo "bash-it Plugins Help-Message"
-    echo
-
-    set | grep "()" \
-    | sed -e "/^_/d" | grep -v "BASH_ARGC=()" \
-    | sed -e "/^\s/d" | grep -v "BASH_LINENO=()" \
-    | grep -v "BASH_ARGV=()" \
-    | grep -v "BASH_SOURCE=()" \
-    | grep -v "DIRSTACK=()" \
-    | grep -v "GROUPS=()" \
-    | grep -v "BASH_CMDS=()" \
-    | grep -v "BASH_ALIASES=()" \
-    | grep -v "COMPREPLY=()" | sed -e "s/()//"
-}
-
 # useful for administrators and configs
 buf ()
 {
-    about back up file with timestamp
-    param filename
+    about 'back up file with timestamp'
+    param 'filename'
+    group 'base'
     local filename=$1
     local filetime=$(date +%Y%m%d_%H%M%S)
     cp ${filename} ${filename}_${filetime}
diff --git a/plugins/available/battery.plugin.bash b/plugins/available/battery.plugin.bash
index 4b9d4b9..002d42f 100644
--- a/plugins/available/battery.plugin.bash
+++ b/plugins/available/battery.plugin.bash
@@ -1,11 +1,15 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'display info about your battery charge level'
 
 battery_percentage(){
+  about 'displays battery charge as a percentage of full (100%)'
+  group 'battery'
+
   if command_exists acpi;
   then
     local ACPI_OUTPUT=$(acpi -b)
     case $ACPI_OUTPUT in
-      *" Unknown"*) 
+      *" Unknown"*)
         local PERC_OUTPUT=$(echo $ACPI_OUTPUT | head -c 22 | tail -c 2)
         case $PERC_OUTPUT in
           *%)
@@ -16,7 +20,7 @@
             ;;
         esac
         ;;
-      *" Discharging"*) 
+      *" Discharging"*)
         local PERC_OUTPUT=$(echo $ACPI_OUTPUT | head -c 26 | tail -c 2)
         case $PERC_OUTPUT in
           *%)
@@ -27,7 +31,7 @@
             ;;
         esac
         ;;
-      *" Charging"*) 
+      *" Charging"*)
         local PERC_OUTPUT=$(echo $ACPI_OUTPUT | head -c 23 | tail -c 2)
         case $PERC_OUTPUT in
           *%)
@@ -38,7 +42,7 @@
             ;;
         esac
         ;;
-      *" Full"*) 
+      *" Full"*)
         echo '99'
         ;;
       *)
@@ -52,7 +56,7 @@
     #local IOREG_OUTPUT_10_5=$(ioreg -l | grep -i capacity | grep -v Legacy| tr '\n' ' | ' | awk '{printf("%.2f%%", $14/$7 * 100)}')
     local IOREG_OUTPUT=$(ioreg -n AppleSmartBattery -r | awk '$1~/Capacity/{c[$1]=$3} END{OFMT="%.2f%%"; max=c["\"MaxCapacity\""]; print (max>0? 100*c["\"CurrentCapacity\""]/max: "?")}')
     case $IOREG_OUTPUT in
-      100*) 
+      100*)
         echo '99'
         ;;
       *)
@@ -65,6 +69,9 @@
 }
 
 battery_charge(){
+  about 'graphical display of your battery charge'
+  group 'battery'
+
   # Full char
   local F_C='▸'
   # Depleted char
diff --git a/plugins/available/browser.plugin.bash b/plugins/available/browser.plugin.bash
index fdfba4f..f7d820a 100644
--- a/plugins/available/browser.plugin.bash
+++ b/plugins/available/browser.plugin.bash
@@ -1,42 +1,34 @@
 # based on https://gist.github.com/318247
 
-# Usage: browser
-# pipe html to a browser
-# e.g.
-# $ echo "<h1>hi mom!</h1>" | browser
-# $ ron -5 man/rip.5.ron | browser
+cite about-plugin
+about-plugin 'render commandline output in your browser'
 
 function browser() {
+    about 'pipe html to a browser'
+    example '$ echo "<h1>hi mom!</h1>" | browser'
+    example '$ ron -5 man/rip.5.ron | browser'
+    group 'browser'
+
     if [ -t 0 ]; then
         if [ -n "$1" ]; then
             open $1
         else
-            cat <<usage
-Usage: browser
-pipe html to a browser
-
-$ echo '<h1>hi mom!</h1>' | browser
-$ ron -5 man/rip.5.ron | browser
-usage
-
-    fi
+            reference browser
+        fi
 
     else
         f="/tmp/browser.$RANDOM.html"
         cat /dev/stdin > $f
-        open $f 
+        open $f
     fi
 }
 
 
-# pipe hot spicy interwebs into textmate and cleanup!
-#
-# Usage: wmate
-# wget into a pipe into TextMate and force Tidy (you can undo in textmate)
-# e.g.
-# $ wmate google.com
-
 function wmate() {
+    about 'pipe hot spicy interwebs into textmate and cleanup!'
+    example '$ wmate google.com'
+    group 'browser'
+
     if [ -t 0 ]; then
         if [ -n "$1" ]; then
             wget -qO- $1 | /usr/bin/mate
@@ -64,34 +56,21 @@
 EOT`
 
         else
-            cat <<usage
-Usage: wmate google.com
-wget into a pipe into TextMate and force Tidy (you can undo in textmate)
-
-$ wmate google.com
-usage
-
+            reference wmate
       fi
     fi
 }
 
-#
-# Usage: raw google.com
-# wget into a temp file and pump it into your browser
-#
-# e.g.
-# $ raw google.com
 function raw() {
+    about 'write wget into a temp file and pump it into your browser'
+    example '$ raw google.com'
+    group 'browser'
+
     if [ -t 0 ]; then
         if [ -n "$1" ]; then
             wget -qO- $1 | browser
         else
-            cat <<usage
-Usage: raw google.com
-wget into a temp file and pump it into your browser
-
-$ raw google.com
-usage
-      fi
+            reference raw
+        fi
     fi
 }
diff --git a/plugins/available/dirs.plugins.bash b/plugins/available/dirs.plugin.bash
old mode 100755
new mode 100644
similarity index 85%
rename from plugins/available/dirs.plugins.bash
rename to plugins/available/dirs.plugin.bash
index e03ccf5..bb1fb02
--- a/plugins/available/dirs.plugins.bash
+++ b/plugins/available/dirs.plugin.bash
@@ -1,5 +1,3 @@
-#!/usr/bin/env bash
-
 # Directory stack navigation:
 #
 # Add to stack with: pu /path/to/directory
@@ -7,6 +5,9 @@
 # Show stack with: d
 # Jump to location by number.
 
+cite about-plugin
+about-plugin 'directory stack navigation'
+
 # Show directory stack
 alias d="dirs -v -l"
 
@@ -31,6 +32,9 @@
 alias po="popd"
 
 function dirs-help() {
+  about 'directory navigation alias usage'
+  group 'dirs'
+
   echo "Directory Navigation Alias Usage"
   echo
   echo "Use the power of directory stacking to move"
@@ -64,10 +68,18 @@
 alias L='cat ~/.dirs'
 
 G () {				# goes to distination dir otherwise , stay in the dir
+    about 'goes to destination dir'
+    param '1: directory'
+    example '$ G ..'
+    group 'dirs'
+
     cd ${1:-$(pwd)} ;
 }
 
 S () {				# SAVE a BOOKMARK
+    about 'save a bookmark'
+    group 'dirs'
+
     sed "/$@/d" ~/.dirs > ~/.dirs1;
     \mv ~/.dirs1 ~/.dirs;
     echo "$@"=\"`pwd`\" >> ~/.dirs;
@@ -75,6 +87,9 @@
 }
 
 R () {				# remove a BOOKMARK
+    about 'remove a bookmark'
+    group 'dirs'
+
     sed "/$@/d" ~/.dirs > ~/.dirs1;
     \mv ~/.dirs1 ~/.dirs;
 }
diff --git a/plugins/available/extract.plugin.bash b/plugins/available/extract.plugin.bash
index 1c3e9b1..bb52045 100644
--- a/plugins/available/extract.plugin.bash
+++ b/plugins/available/extract.plugin.bash
@@ -1,3 +1,5 @@
+cite about-plugin
+about-plugin 'one command to extract them all...'
 extract () {
   if [ $# -ne 1 ]
   then
diff --git a/plugins/available/fasd.bash b/plugins/available/fasd.plugin.bash
similarity index 99%
rename from plugins/available/fasd.bash
rename to plugins/available/fasd.plugin.bash
index 984f630..ee810e2 100755
--- a/plugins/available/fasd.bash
+++ b/plugins/available/fasd.plugin.bash
@@ -584,7 +584,8 @@
 fasd --init env
 
 case $- in
-  *i*) alias fasd=$BASH_IT'/plugins/enabled/fasd.bash'
+  *i*) cite about-plugin
+       about-plugin 'navigate "frecently" used files and directories'
        eval "$(fasd --init auto)"
       ;;
   *) # assume being executed as an executable
diff --git a/plugins/available/git.plugins.bash b/plugins/available/git.plugin.bash
similarity index 83%
rename from plugins/available/git.plugins.bash
rename to plugins/available/git.plugin.bash
index 41b031f..0b77111 100644
--- a/plugins/available/git.plugins.bash
+++ b/plugins/available/git.plugin.bash
@@ -1,26 +1,42 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'git helper functions'
 
 function git_remote {
+  about 'adds remote $GIT_HOSTING:$1 to current repo'
+  group 'git'
+
   echo "Running: git remote add origin ${GIT_HOSTING}:$1.git"
   git remote add origin $GIT_HOSTING:$1.git
 }
 
 function git_first_push {
+  about 'push into origin refs/heads/master'
+  group 'git'
+
   echo "Running: git push origin master:refs/heads/master"
   git push origin master:refs/heads/master
 }
 
 function git_remove_missing_files() {
+  about "git rm's missing files"
+  group 'git'
+
   git ls-files -d -z | xargs -0 git update-index --remove
 }
 
 # Adds files to git's exclude file (same as .gitignore)
 function local-ignore() {
+  about 'adds file or path to git exclude file'
+  param '1: file or path fragment to ignore'
+  group 'git'
   echo "$1" >> .git/info/exclude
 }
 
 # get a quick overview for your git repo
 function git_info() {
+    about 'overview for your git repo'
+    group 'git'
+
     if [ -n "$(git symbolic-ref HEAD 2> /dev/null)" ]; then
         # print informations
         echo "git repo overview"
@@ -29,7 +45,7 @@
 
         # print all remotes and thier details
         for remote in $(git remote show); do
-            echo $remote:  
+            echo $remote:
             git remote show $remote
             echo
         done
@@ -43,10 +59,10 @@
         fi
 
         # print at least 5 last log entries
-        echo 
+        echo
         echo "log:"
         git log -5 --oneline
-        echo 
+        echo
 
     else
         echo "you're currently not in a git repository"
@@ -55,6 +71,9 @@
 }
 
 function git_stats {
+    about 'display stats per author'
+    group 'git'
+
 # awesome work from https://github.com/esc/git-stats
 # including some modifications
 
diff --git a/plugins/available/hg.plugin.bash b/plugins/available/hg.plugin.bash
new file mode 100644
index 0000000..020b920
--- /dev/null
+++ b/plugins/available/hg.plugin.bash
@@ -0,0 +1,25 @@
+cite about-plugin
+about-plugin 'hg helper functions'
+
+hg_dirty() {
+    about 'displays dirty status of hg repository'
+    group 'hg'
+
+    hg status --no-color 2> /dev/null \
+    | awk '$1 == "?" { print "?" } $1 != "?" { print "!" }' \
+    | sort | uniq | head -c1
+}
+
+hg_in_repo() {
+    about 'determine if pwd is an hg repo'
+    group 'hg'
+
+    [[ `hg branch 2> /dev/null` ]] && echo 'on '
+}
+
+hg_branch() {
+    about 'display current hg branch'
+    group 'hg'
+
+    hg branch 2> /dev/null
+}
diff --git a/plugins/available/hg.plugins.bash b/plugins/available/hg.plugins.bash
deleted file mode 100644
index 33c81d3..0000000
--- a/plugins/available/hg.plugins.bash
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-hg_dirty() {
-    hg status --no-color 2> /dev/null \
-    | awk '$1 == "?" { print "?" } $1 != "?" { print "!" }' \
-    | sort | uniq | head -c1
-}
-
-hg_in_repo() {
-    [[ `hg branch 2> /dev/null` ]] && echo 'on '
-}
-
-hg_branch() {
-    hg branch 2> /dev/null
-}
diff --git a/plugins/available/javascript.plugins.bash b/plugins/available/javascript.plugin.bash
similarity index 67%
rename from plugins/available/javascript.plugins.bash
rename to plugins/available/javascript.plugin.bash
index 76a7e13..e8037b9 100644
--- a/plugins/available/javascript.plugins.bash
+++ b/plugins/available/javascript.plugin.bash
@@ -1,16 +1,22 @@
-#!/usr/bin/env bash
-#
-# The install directory is hard-coded. TOOD: allow the directory to be specified on the command line.
-#
+# The install directory is hard-coded. TODO: allow the directory to be specified on the command line.
+
+cite about-plugin
+about-plugin 'download jquery files into current project'
 
 [[ -z "$JQUERY_VERSION_NUMBER" ]] && JQUERY_VERSION_NUMBER="1.6.1"
 [[ -z "$JQUERY_UI_VERSION_NUMBER" ]] && JQUERY_UI_VERSION_NUMBER="1.8.13"
 
 function rails_jquery {
+  about 'download rails.js into public/javascripts'
+  group 'javascript'
+
   curl -o public/javascripts/rails.js http://github.com/rails/jquery-ujs/raw/master/src/rails.js
 }
 
 function jquery_install {
+  about 'download jquery.js into public/javascripts'
+  group 'javascript'
+
   if [ -z "$1" ]
   then
       version=$JQUERY_VERSION_NUMBER
@@ -21,6 +27,9 @@
 }
 
 function jquery_ui_install {
+  about 'download jquery_us.js into public/javascripts'
+  group 'javascript'
+
   if [ -z "$1" ]
   then
       version=$JQUERY_UI_VERSION_NUMBER
diff --git a/plugins/available/jekyll.plugins.bash b/plugins/available/jekyll.plugin.bash
similarity index 92%
rename from plugins/available/jekyll.plugins.bash
rename to plugins/available/jekyll.plugin.bash
index 74e3cb1..6254a87 100644
--- a/plugins/available/jekyll.plugins.bash
+++ b/plugins/available/jekyll.plugin.bash
@@ -1,6 +1,11 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'manage your jekyll site'
 
 editpost() {
+  about 'edit a post'
+  param '1: site directory'
+  group 'jekyll'
+
   unset SITE
   if [ -z "$1" ]
   then
@@ -35,11 +40,11 @@
     DATE=`echo $POST | grep -oE "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}"`
     TITLE=`cat $POST | grep -oE "title: (.+)"`
     TITLE=`echo $TITLE | sed 's/title: //'`
-    echo "$COUNTER) 	$DATE	$TITLE" >> "$TMPFILE"	
+    echo "$COUNTER) 	$DATE	$TITLE" >> "$TMPFILE"
     POSTS[$COUNTER]=$POST
     COUNTER=`expr $COUNTER + 1`
   done
-  less $TMPFILE	
+  less $TMPFILE
   read -p "Number of post to edit: " POST_TO_EDIT
   if [ -z "$JEKYLL_EDITOR" ]
   then
@@ -50,6 +55,10 @@
 }
 
 newpost() {
+  about 'create a new post'
+  param '1: site directory'
+  group 'jekyll'
+
   unset SITE
   if [ -z "$1" ]
   then
@@ -93,7 +102,7 @@
   then
     select OPTION in $OPTIONS
     do
-      if [[ $OPTION = "Text" ]] 
+      if [[ $OPTION = "Text" ]]
       then
         POST_TYPE="Text"
         break
@@ -257,6 +266,10 @@
 }
 
 function testsite() {
+  about 'launches local jekyll server'
+  param '1: site directory'
+  group 'jekyll'
+
   unset SITE
   if [ -z "$1" ]
   then
@@ -285,6 +298,10 @@
 }
 
 function buildsite() {
+  about 'builds site'
+  param '1: site directory'
+  group 'jekyll'
+
   unset SITE
   if [ -z "$1" ]
   then
@@ -314,6 +331,10 @@
 }
 
 function deploysite() {
+  about 'rsyncs site to remote host'
+  param '1: site directory'
+  group 'jekyll'
+
   unset SITE
   if [ -z "$1" ]
   then
diff --git a/plugins/available/latex.plugin.bash b/plugins/available/latex.plugin.bash
index c2ce9dd..eefec59 100644
--- a/plugins/available/latex.plugin.bash
+++ b/plugins/available/latex.plugin.bash
@@ -1,4 +1,5 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'use mactex'
 
 # add mactex to the path if its present
 MACTEX_PATH=/usr/local/texlive/2009/bin/universal-darwin
diff --git a/plugins/available/nginx.plugins.bash b/plugins/available/nginx.plugin.bash
similarity index 81%
rename from plugins/available/nginx.plugins.bash
rename to plugins/available/nginx.plugin.bash
index 6dd86dd..660b503 100644
--- a/plugins/available/nginx.plugins.bash
+++ b/plugins/available/nginx.plugin.bash
@@ -1,6 +1,10 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'manage your nginx service'
 
 function nginx_reload() {
+  about 'reload your nginx config'
+  group 'nginx'
+
   FILE="${NGINX_PATH}/logs/nginx.pid"
   if [ -e $FILE ]; then
     echo "Reloading NGINX..."
@@ -13,6 +17,9 @@
 }
 
 function nginx_stop() {
+  about 'stop nginx'
+  group 'nginx'
+
   FILE="${NGINX_PATH}/logs/nginx.pid"
   if [ -e $FILE ]; then
     echo "Stopping NGINX..."
@@ -25,6 +32,9 @@
 }
 
 function nginx_start() {
+  about 'start nginx'
+  group 'nginx'
+
   FILE="${NGINX_PATH}/sbin/nginx"
   if [ -e $FILE ]; then
     echo "Starting NGINX..."
@@ -35,6 +45,9 @@
 }
 
 function nginx_restart() {
+  about 'restart nginx'
+  group 'nginx'
+
   FILE="${NGINX_PATH}/logs/nginx.pid"
   if [ -e $FILE ]; then
     echo "Stopping NGINX..."
diff --git a/plugins/available/nvm.plugin.bash b/plugins/available/nvm.plugin.bash
index 3f489dd..2e607d6 100644
--- a/plugins/available/nvm.plugin.bash
+++ b/plugins/available/nvm.plugin.bash
@@ -5,6 +5,9 @@
 # Implemented by Tim Caswell <tim@creationix.com>
 # with much bash help from Matthew Ranney
 
+cite about-plugin
+about-plugin 'node version manager, as a bash function'
+
 export NVM_DIR=$HOME/.nvm
 
 if [ ! -d "$NVM_DIR" ]; then
@@ -75,6 +78,10 @@
 
 nvm()
 {
+  about 'Node Version Manager'
+  param '1: command, see nvm help'
+  group 'nvm'
+
   if [ $# -lt 1 ]; then
     nvm help
     return
diff --git a/plugins/available/osx.plugin.bash b/plugins/available/osx.plugin.bash
index 7d3d077..fde9c83 100644
--- a/plugins/available/osx.plugin.bash
+++ b/plugins/available/osx.plugin.bash
@@ -1,6 +1,10 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'osx-specific functions'
 
 function tab() {
+  about 'opens a new terminal tab'
+  group 'osx'
+
   osascript 2>/dev/null <<EOF
     tell application "System Events"
       tell process "Terminal" to keystroke "t" using command down
@@ -15,6 +19,10 @@
 # this one switches your os x dock between 2d and 3d
 # thanks to savier.zwetschge.org
 function dock-switch() {
+    about 'switch dock between 2d and 3d'
+    param '1: "2d" or "3d"'
+    example '$ dock-switch 2d'
+    group 'osx'
 
     if [ $(uname) = "Darwin" ]; then
 
@@ -39,6 +47,10 @@
 # Download a file and open it in Preview
 
 function prevcurl() {
+  about 'download a file and open it in Preview'
+  param '1: url'
+  group 'osx'
+
   if [ ! $(uname) = "Darwin" ]
   then
     echo "This function only works with Mac OS X"
diff --git a/plugins/available/python.plugin.bash b/plugins/available/python.plugin.bash
index 6c87f8a..c705d5b 100644
--- a/plugins/available/python.plugin.bash
+++ b/plugins/available/python.plugin.bash
@@ -1,4 +1,5 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'alias "http" to SimpleHTTPServer'
 
 if [ $(uname) = "Linux" ]
 then
diff --git a/plugins/available/rbenv.plugin.bash b/plugins/available/rbenv.plugin.bash
index c45d714..70fe62c 100644
--- a/plugins/available/rbenv.plugin.bash
+++ b/plugins/available/rbenv.plugin.bash
@@ -1,8 +1,10 @@
-#!/usr/bin/env bash
-
 # Load rbebv, if you are using it
+
+cite about-plugin
+about-plugin 'load rbenv, if you are using it'
+
 export PATH="$HOME/.rbenv/bin:$PATH"
 [[ `which rbenv` ]] && eval "$(rbenv init -)"
 
 # Load the auto-completion script if rbenv was loaded.
-[[ -e ~/.rbenv/completions/rbenv.bash ]] && source ~/.rbenv/completions/rbenv.bash
\ No newline at end of file
+[[ -e ~/.rbenv/completions/rbenv.bash ]] && source ~/.rbenv/completions/rbenv.bash
diff --git a/plugins/available/ruby.plugin.bash b/plugins/available/ruby.plugin.bash
index 9ae61a4..f36bb15 100644
--- a/plugins/available/ruby.plugin.bash
+++ b/plugins/available/ruby.plugin.bash
@@ -1,4 +1,10 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'adds "remove_gem" function'
+
 function remove_gem {
+  about 'removes installed gem'
+  param '1: installed gem name'
+  group 'ruby'
+
   gem list | grep $1 | awk '{ print $1; }' | xargs sudo gem uninstall
 }
diff --git a/plugins/available/rvm.plugin.bash b/plugins/available/rvm.plugin.bash
index e0d18ba..6acad07 100644
--- a/plugins/available/rvm.plugin.bash
+++ b/plugins/available/rvm.plugin.bash
@@ -1,6 +1,8 @@
-#!/usr/bin/env bash
-
 # Load RVM, if you are using it
+
+cite about-plugin
+about-plugin 'load rvm, if you are using it'
+
 [[ -s $HOME/.rvm/scripts/rvm ]] && source $HOME/.rvm/scripts/rvm
 
 # Check to make sure that RVM is actually loaded before adding
diff --git a/plugins/available/ssh.plugin.bash b/plugins/available/ssh.plugin.bash
new file mode 100644
index 0000000..4e17206
--- /dev/null
+++ b/plugins/available/ssh.plugin.bash
@@ -0,0 +1,19 @@
+cite about-plugin
+about-plugin 'ssh helper functions'
+
+function add_ssh() {
+  about 'add entry to ssh config'
+  param '1: host'
+  param '2: hostname'
+  param '3: user'
+  group 'ssh'
+
+  echo -en "\n\nHost $1\n  HostName $2\n  User $3\n  ServerAliveInterval 30\n  ServerAliveCountMax 120" >> ~/.ssh/config
+}
+
+function sshlist() {
+  about 'list hosts defined in ssh config'
+  group 'ssh'
+
+  awk '$1 ~ /Host$/ { print $2 }' ~/.ssh/config
+}
diff --git a/plugins/available/ssh.plugins.bash b/plugins/available/ssh.plugins.bash
deleted file mode 100644
index 39718fb..0000000
--- a/plugins/available/ssh.plugins.bash
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env bash
-
-function add_ssh() {
-  echo -en "\n\nHost $1\n  HostName $2\n  User $3\n  ServerAliveInterval 30\n  ServerAliveCountMax 120" >> ~/.ssh/config
-}
-
-function sshlist() {
-  awk '$1 ~ /Host$/ { print $2 }' ~/.ssh/config
-}
diff --git a/plugins/available/subversion.plugin.bash b/plugins/available/subversion.plugin.bash
index a7fe941..bdb3edf 100644
--- a/plugins/available/subversion.plugin.bash
+++ b/plugins/available/subversion.plugin.bash
@@ -1,8 +1,21 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'svn helper functions'
+
 rm_svn(){
+  about 'remove ".svn" files from directory'
+  param '1: directory to search for files'
+  group 'svn'
+
+  if [ -z "$1" ]; then
+      reference rm_svn
+      return
+  fi
   find $1 -name .svn -print0 | xargs -0 rm -rf
 }
 
 svn_add(){
-	svn status | grep '^\?' | sed -e 's/? *//' | sed -e 's/ /\ /g' | xargs svn add
+    about 'add to svn repo'
+    group 'svn'
+
+    svn status | grep '^\?' | sed -e 's/? *//' | sed -e 's/ /\ /g' | xargs svn add
 }
diff --git a/plugins/available/tmux.plugin.bash b/plugins/available/tmux.plugin.bash
index ff35336..f7ee337 100644
--- a/plugins/available/tmux.plugin.bash
+++ b/plugins/available/tmux.plugin.bash
@@ -1,2 +1,6 @@
 # make sure that tmux is launched in 256 color mode
+
+cite about-plugin
+about-plugin 'make sure that tmux is launched in 256 color mode'
+
 alias tmux="TERM=xterm-256color tmux"
diff --git a/plugins/available/tmuxinator.plugin.bash b/plugins/available/tmuxinator.plugin.bash
index cf5500d..a011435 100644
--- a/plugins/available/tmuxinator.plugin.bash
+++ b/plugins/available/tmuxinator.plugin.bash
@@ -1,3 +1,4 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'sources tmuxinator script if available'
 
 [[ -s $HOME/.tmuxinator/scripts/tmuxinator ]] && . $HOME/.tmuxinator/scripts/tmuxinator
diff --git a/plugins/available/vagrant.plugins.bash b/plugins/available/vagrant.plugin.bash
similarity index 94%
rename from plugins/available/vagrant.plugins.bash
rename to plugins/available/vagrant.plugin.bash
index 3131744..aa223e7 100644
--- a/plugins/available/vagrant.plugins.bash
+++ b/plugins/available/vagrant.plugin.bash
@@ -1,4 +1,6 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'set up vagrant autocompletion'
+
 _vagrant()
 {
     cur="${COMP_WORDS[COMP_CWORD]}"
diff --git a/plugins/available/virtualenv.plugin.bash b/plugins/available/virtualenv.plugin.bash
index ba27c76..302e19d 100644
--- a/plugins/available/virtualenv.plugin.bash
+++ b/plugins/available/virtualenv.plugin.bash
@@ -1,19 +1,30 @@
-#!/usr/bin/env bash
-
 # make sure virtualenvwrapper is enabled if available
+
+cite about-plugin
+about-plugin 'virtualenvwrapper helper functions'
+
 [[ `which virtualenvwrapper.sh` ]] && . virtualenvwrapper.sh
 
-# create a new virtualenv for this directory
+
 function mkvenv {
+  about 'create a new virtualenv for this directory'
+  group 'virtualenv'
+
   cwd=`basename \`pwd\``
   mkvirtualenv --no-site-packages --distribute $cwd
 }
 
-# create a new virtualenv for the branch you're currently in
+
 function mkvbranch {
+  about 'create a new virtualenv for the current branch'
+  group 'virtualenv'
+
   mkvirtualenv --no-site-packages --distribute "$(basename `pwd`)@$(git_prompt_info)"
 }
 
 function wovbranch {
+  about 'sets workon branch'
+  group 'virtualenv'
+
   workon "$(basename `pwd`)@$(git_prompt_info)"
 }
diff --git a/plugins/available/z.bash b/plugins/available/z.plugin.bash
similarity index 91%
rename from plugins/available/z.bash
rename to plugins/available/z.plugin.bash
index ef3e3d9..6653575 100644
--- a/plugins/available/z.bash
+++ b/plugins/available/z.plugin.bash
@@ -1,7 +1,7 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'maintains a jump-list of the directories you actually use'
+about-plugin '                              z is DEPRECATED, use fasd instead'
 
-# maintains a jump-list of the directories you actually use
-#
 # INSTALL:
 #   * put something like this in your .bashrc:
 #     . /path/to/z.sh
@@ -15,6 +15,11 @@
 #   * z -t foo  # goes to most recently accessed dir matching foo
 #   * z -l foo  # list all dirs matching foo (by frecency)
 
+if [ -e $BASH_IT/plugins/enabled/fasd.plugin.bash ]; then
+    printf '%s\n' 'sorry, the z plugin is incompatible with the fasd plugin. you may use either, but not both.'
+    return
+fi
+
 z() {
  local datafile="$HOME/.z"
  if [ "$1" = "--add" ]; then
diff --git a/plugins/available/z_autoenv.plugins.bash b/plugins/available/z_autoenv.plugin.bash
similarity index 87%
rename from plugins/available/z_autoenv.plugins.bash
rename to plugins/available/z_autoenv.plugin.bash
index 04efa85..dd1aec1 100644
--- a/plugins/available/z_autoenv.plugins.bash
+++ b/plugins/available/z_autoenv.plugin.bash
@@ -1,4 +1,6 @@
-#!/usr/bin/env bash
+cite about-plugin
+about-plugin 'source into environment when cding to directories'
+
 if [[ -n "${ZSH_VERSION}" ]]
 then __array_offset=0
 else __array_offset=1