about summary refs log tree commit diff
path: root/Functions/Misc/add-zsh-hook
blob: fa8015a3dfa4e4528ec6d3f424af3a4ae8b74aee (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# Add to HOOK the given FUNCTION.
# HOOK is one of chpwd, precmd, preexec, periodic, zshexit (the
# _functions subscript is not required).
#
# With -d, remove the function from the hook instead; delete the hook
# variable if it is empty.
#
# Without -d, the FUNCTION is marked for autoload; -U is passed down to
# autoload if that is given.  (This is harmless if the function is actually
# defined inline.)

emulate -L zsh

local -a hooktypes
hooktypes=(chpwd precmd preexec periodic zshexit)

local opt
local -a autoopts
integer del

while getopts "d" opt; do
  case $opt in
    (d)
    del=1
    ;;

    (U)
    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
    set -A $hook ${(P)hook:#$fn}
    # unset if no remaining entries --- this can give better
    # performance in some cases
    (( ${(P)#hook} )) || unset $hook
  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