--- /dev/null
+# Add to HOOK the given FUNCTION.
+# HOOK is one of chpwd, precmd, preexec, periodic, zshaddhistory,
+# zshexit (the _functions subscript is not required).
+#
+# With -d, remove the function from the hook instead; delete the hook
+# variable if it is empty.
+#
+# -D behaves like -d, but pattern characters are active in the
+# function name, so any matching function will be deleted from the hook.
+#
+# Without -d, the FUNCTION is marked for autoload; -U is passed down to
+# autoload if that is given, as are -z and -k. (This is harmless if the
+# function is actually defined inline.)
+
+emulate -L zsh
+
+local -a hooktypes
+hooktypes=(chpwd precmd preexec periodic zshaddhistory zshexit)
+
+local opt
+local -a autoopts
+integer del
+
+while getopts "dDUzk" opt; do
+ case $opt in
+ (d)
+ del=1
+ ;;
+
+ (D)
+ del=2
+ ;;
+
+ ([Uzk])
+ autoopts+=(-$opt)
+ ;;
+
+ (*)
+ return 1
+ ;;
+ esac
+done
+shift $(( OPTIND - 1 ))
+
+if (( $# != 2 || ${hooktypes[(I)$1]} == 0 )); then
+ print "Usage: $0 hook function\nValid hooks are:\n $hooktypes"
+ return 1
+fi
+
+local hook="${1}_functions"
+local fn="$2"
+
+if (( del )); then
+ # delete, if hook is set
+ if (( ${(P)+hook} )); then
+ if (( del == 2 )); then
+ set -A $hook ${(P)hook:#${~fn}}
+ else
+ set -A $hook ${(P)hook:#$fn}
+ fi
+ # unset if no remaining entries --- this can give better
+ # performance in some cases
+ if (( ! ${(P)#hook} )); then
+ unset $hook
+ fi
+ fi
+else
+ if (( ${(P)+hook} )); then
+ if (( ${${(P)hook}[(I)$fn]} == 0 )); then
+ set -A $hook ${(P)hook} $fn
+ fi
+ else
+ set -A $hook $fn
+ fi
+ autoload $autoopts -- $fn
+fi
# to caphuso from the Zsh example files for this idea.
autoload ${fpath[1]}/^_*(^/:t)
+# Simulate hooks using _functions arrays for Zsh versions older then 4.3.4. At
+# the moment only precmd() and preexec() are simulated.
+if [[ $ZSH_VERSION != (4.3.<4->|4.<4->*|<5->*) ]]; then
+ # Provide add-zsh-hook which was added in 4.3.4.
+ fpath=($fpath ~/.zsh/functions/compatibility)
+
+ # Run all functions defined in the ${precmd,preexec}_functions arrays.
+ function precmd() {
+ for function in $precmd_functions; do
+ $function $@
+ done
+ }
+ function preexec() {
+ for function in $preexec_functions; do
+ $function $@
+ done
+ }
+fi
+
# Autoload add-zsh-hook to add/remove zsh hook functions easily.
autoload -Uz add-zsh-hook