summaryrefslogtreecommitdiffstats
path: root/examples/functions/autoload.v3
blob: b1e5dfe2a1dd52fd99c6e3b88e2d47911c2c6b0a (plain)
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#From: Mark Kennedy <mark.t.kennedy@gmail.com> (<mtk@ny.ubs.com>)
#Message-ID: <35E2B899.63A02DF5@ny.ubs.com>
#Date: Tue, 25 Aug 1998 09:14:01 -0400
#To: chet@nike.ins.cwru.edu
#Subject: a newer version of the ksh-style 'autoload'

#enclosed you'll find 'autoload.v3',  a version of the autoloader
#that emulates the ksh semantics of delaying the resolution (and loading) of the function
#until its first use.  i took the liberty of simplifying the code a bit although it still uses the
#same functional breakdown.  i recently went through the exercise of converting
#my ksh-based environment to bash (a very, very pleasant experience)
#and this popped out.

# the psuedo-ksh autoloader.

# The first cut of this was by Bill Trost, trost@reed.bitnet.
# The second cut came from Chet Ramey, chet@ins.CWRU.Edu
# The third cut came from Mark Kennedy, mtk@ny.ubs.com.  1998/08/25

unset _AUTOLOADS

_aload()
{
    local func
    for func; do
	eval $func '()
		{
		    local f=$(_autoload_resolve '$func')
		    if [[ $f ]]; then
			. $f
			'$func' "$@"
			return $?
		    else
			return 1
		    fi
		}'
	_autoload_addlist $func
    done
}

_autoload_addlist()
{
	local func

	for func in ${_AUTOLOADS[@]}; do
	    [[ $func = "$1" ]] && return
	done

	_AUTOLOADS[${#_AUTOLOADS[@]}]=$1
}

_autoload_dump()
{
    local func

    for func in ${_AUTOLOADS[@]}; do
	[[ $1 ]] && echo -n "autoload "
	echo $func
    done
}

_autoload_remove_one()
{
    local func
    local -a NEW_AUTOLOADS

    for func in ${_AUTOLOADS[@]}; do
	[[ $func != "$1" ]] && NEW_AUTOLOADS[${#NEW_AUTOLOADS[@]}]=$func
    done

    _AUTOLOADS=( ${NEW_AUTOLOADS[@]} )
}

_autoload_remove()
{
    local victim func

    for victim; do
	for func in ${_AUTOLOADS[@]}; do
	    [[ $victim = "$func" ]] && unset -f $func && continue 2
	done
	echo "autoload: $func: not an autoloaded function" >&2
    done

    for func; do
	    _autoload_remove_one $func
    done
}

_autoload_resolve()
{
    if [[ ! "$FPATH" ]]; then
	    echo "autoload: FPATH not set or null" >&2
	    return
    fi

    local p

    for p in $( (IFS=':'; set -- ${FPATH}; echo "$@") ); do
	p=${p:-.}
	if [ -f $p/$1 ]; then echo $p/$1; return; fi
    done

    echo "autoload: $1: function source file not found" >&2
}

autoload()
{
    if (( $# == 0 )) ; then _autoload_dump; return; fi

    local opt OPTIND

    while getopts pu opt
    do
	case $opt in
	    p) _autoload_dump printable; return;;
	    u) shift $((OPTIND-1)); _autoload_remove "$@"; return;; 
	    *) echo "autoload: usage: autoload [-pu] [function ...]" >&2; return;;
	esac
    done

    shift $(($OPTIND-1))

    _aload "$@"
}