diff options
| author | Chet Ramey <chet.ramey@case.edu> | 2018-05-22 16:51:07 -0400 |
|---|---|---|
| committer | Chet Ramey <chet.ramey@case.edu> | 2018-05-22 16:51:07 -0400 |
| commit | 9a51695bed07d37086c352372ac69d0a30039a6b (patch) | |
| tree | 4d0f57cba0dd1ec7a75aae56e18cfe9997d0b7a7 /examples/functions | |
| parent | 7de27456f6494f5f9c11ea1c19024d0024f31112 (diff) | |
| download | bash-5.0-alpha.tar.gz | |
bash-5.0-alpha releasebash-5.0-alpha
Diffstat (limited to 'examples/functions')
| -rw-r--r-- | examples/functions/arrayops.bash | 146 | ||||
| -rw-r--r-- | examples/functions/autoload | 2 | ||||
| -rw-r--r-- | examples/functions/autoload.v4 | 556 | ||||
| -rw-r--r-- | examples/functions/autoload.v4.t | 184 |
4 files changed, 887 insertions, 1 deletions
diff --git a/examples/functions/arrayops.bash b/examples/functions/arrayops.bash new file mode 100644 index 00000000..d34353ae --- /dev/null +++ b/examples/functions/arrayops.bash @@ -0,0 +1,146 @@ +# arrayops.bash --- hide some of the nasty syntax for manipulating bash arrays +# Author: Noah Friedman <friedman@splode.com> +# Created: 2016-07-08 +# Public domain + +# $Id: arrayops.bash,v 1.3 2016/07/28 15:38:55 friedman Exp $ + +# Commentary: + +# These functions try to tame the syntactic nightmare that is bash array +# syntax, which makes perl's almost look reasonable. +# +# For example the apush function below lets you write: +# +# apush arrayvar newval +# +# instead of +# +# ${arrayvar[${#arrayvar[@]}]}=newval +# +# Because seriously, you've got to be kidding me. + +# These functions avoid the use of local variables as much as possible +# (especially wherever modification occurs) because those variable names +# might shadow the array name passed in. Dynamic scope! + +# Code: + +#:docstring apush: +# Usage: apush arrayname val1 {val2 {...}} +# +# Appends VAL1 and any remaining arguments to the end of the array +# ARRAYNAME as new elements. +#:end docstring: +apush() +{ + eval "$1=(\"\${$1[@]}\" \"\${@:2}\")" +} + +#:docstring apop: +# Usage: apop arrayname {n} +# +# Removes the last element from ARRAYNAME. +# Optional argument N means remove the last N elements. +#:end docstring: +apop() +{ + eval "$1=(\"\${$1[@]:0:\${#$1[@]}-${2-1}}\")" +} + +#:docstring aunshift: +# Usage: aunshift arrayname val1 {val2 {...}} +# +# Prepends VAL1 and any remaining arguments to the beginning of the array +# ARRAYNAME as new elements. The new elements will appear in the same order +# as given to this function, rather than inserting them one at a time. +# +# For example: +# +# foo=(a b c) +# aunshift foo 1 2 3 +# => foo is now (1 2 3 a b c) +# but +# +# foo=(a b c) +# aunshift foo 1 +# aunshift foo 2 +# aunshift foo 3 +# => foo is now (3 2 1 a b c) +# +#:end docstring: +aunshift() +{ + eval "$1=(\"\${@:2}\" \"\${$1[@]}\")" +} + +#:docstring ashift: +# Usage: ashift arrayname {n} +# +# Removes the first element from ARRAYNAME. +# Optional argument N means remove the first N elements. +#:end docstring: +ashift() +{ + eval "$1=(\"\${$1[@]: -\${#$1[@]}+${2-1}}\")" +} + +#:docstring aset: +# Usage: aset arrayname idx newval +# +# Assigns ARRAYNAME[IDX]=NEWVAL +#:end docstring: +aset() +{ + eval "$1[\$2]=${@:3}" +} + +#:docstring aref: +# Usage: aref arrayname idx {idx2 {...}} +# +# Echoes the value of ARRAYNAME at index IDX to stdout. +# If more than one IDX is specified, each one is echoed. +# +# Unfortunately bash functions cannot return arbitrary values in the usual way. +#:end docstring: +aref() +{ + eval local "v=(\"\${$1[@]}\")" + local x + for x in ${@:2} ; do echo "${v[$x]}"; done +} + +#:docstring aref: +# Usage: alen arrayname +# +# Echoes the length of the number of elements in ARRAYNAME. +# +# It also returns number as a numeric value, but return values are limited +# by a maximum of 255 so don't rely on this unless you know your arrays are +# relatively small. +#:end docstring: +alen() +{ + eval echo "\${#$1[@]}" + eval return "\${#$1[@]}" +} + +#:docstring anreverse: +# Usage: anreverse arrayname +# +# Reverse the order of the elements in ARRAYNAME. +# The array variable is altered by this operation. +#:end docstring: +anreverse() +{ + eval set $1 "\"\${$1[@]}\"" + eval unset $1 + while [ $# -gt 1 ]; do + eval "$1=(\"$2\" \"\${$1[@]}\")" + set $1 "${@:3}" + done +} + +#provide arrayops + +# arrayops.bash ends here diff --git a/examples/functions/autoload b/examples/functions/autoload index a563a779..cb3a673e 100644 --- a/examples/functions/autoload +++ b/examples/functions/autoload @@ -22,7 +22,7 @@ # # Declare a function ($1) to be autoloaded from a file ($2) when it is first # called. This defines a `temporary' function that will `.' the file -# containg the real function definition, then execute that new definition with +# containing the real function definition, then execute that new definition with # the arguments given to this `fake' function. The autoload function defined # by the file and the file itself *must* be named identically. # diff --git a/examples/functions/autoload.v4 b/examples/functions/autoload.v4 new file mode 100644 index 00000000..a172e612 --- /dev/null +++ b/examples/functions/autoload.v4 @@ -0,0 +1,556 @@ +## -*- sh -*- + +# The psuedo-ksh autoloader. + +# How to use: +# o One function per file. +# o File and function name match exactly. +# o File is located in a directory that is in FPATH. +# o This script (autoload) must be sourced in as early as possible. This +# implies that any code in this script should NOT rely on any library of local +# or self-defined functions having already been loaded. +# o autoload must be called for each function before the function can be used. If +# autoloads are in directories where there are nothing but autoloads, then +# 'autoload /path/to/files/*' suffices (but see options -a and -f). +# o The call must be made in the current environment, not a subshell. +# o The command line suffices as "current environment". If you have autoload +# calls in a script, that script must be dotted into the process. + +# 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 +# The fourth cut came from Matthew Persico, matthew.persico@gmail.com 2017/August + +autoload_calc_shimsize () +{ + echo $((AUTOLOAD_SHIM_OVERHEAD + 3 * ${#1})) +} + +_autoload_split_fpath () +{ + (IFS=':'; set -- ${FPATH}; echo "$@") +} + +_aload() +{ + local opt OPTIND + local doexport=0 + local doreload=0 + local doverbose=0 + local doevalshim=0 + local loadthese + local optimize=0 + local loaded=0 + local exported=0 + local optimized=0 + local summary=0 + local dofpath=0 + while getopts xrvla:oyf opt; do + case $opt in + x) doexport=1;; + r) doreload=1;; + v) doverbose=1;; + l) doevalshim=1;; + a) loadthese=$(find $OPTARG -maxdepth 1 -type f -printf '%f ');; + o) optimize=1;; + y) summary=1;; + f) loadthese=$(find $(_autoload_split_fpath) -maxdepth 1 -type f -printf '%f ');; + *) echo "_aload: usage: _aload [-xrvlyf] [-a dir] [function ...]" >&2; return;; + esac + done + + shift $(($OPTIND-1)) + + [ -z "$loadthese" ] && loadthese="$@" + + local func + for func in $loadthese; do + local exists_fn + exists_fn=$(declare -F $func) + if [ -n "$exists_fn" ] && ((doreload==0)) && ((doevalshim==0)) + then + if ((doverbose)) + then + echo "autoload: function '$func' already exists" + fi + else + local andevaled='' + local andexported='' + local evalstat=0 + local doshim=1 + local funcfile + funcfile=$(_autoload_resolve $func) + if [[ $funcfile ]] ; then + ## The file was found for $func. Process it. + + if ((optimize)); then + ## For the first function loaded, we will not know + ## AUTOLOAD_SHIM_OVERHEAD. We can only calculate it after + ## we have loaded one function. + if [[ $AUTOLOAD_SHIM_OVERHEAD ]]; then + local size=$(wc -c $funcfile| sed 's/ .*//') + local shimsize=$(autoload_calc_shimsize $func) + if (( size <= shimsize)); then + doshim=0 + andevaled=', optimized' + ((optimized+=1)) + fi + fi + fi + + if ((doevalshim)); then + doshim=0 + andevaled=', evaled' + fi + + ## 'brand' as in branding a cow with a mark. We add a local + ## variable to each function we autoload so that we can tell + ## later on it is an autoloaded function without having to + ## maintain some bash array or hash that cannot be passed to + ## and used by subshells. + local brandtext + brandtext="eval \"\$(type $func | sed -e 1d -e 4ilocal\\ AUTOLOADED=\'$func\')\"" + if ((doshim)); then + ## Don't bother trying to save space by shoving all the + ## eval text below onto one unreadable line; new lines will + ## be added at your semicolons and any indentation below + ## seems to be ignored anyway if you export the function; + ## look at its BASH_FUNCTION representation. + eval $func '() + { + local IS_SHIM="$func" + local file=$(_autoload_resolve '$func') + if [[ $file ]] + then + . $file + '$brandtext' + '$func' "$@" + return $? + else + return 1; + fi + }' + else + . $funcfile + eval "$brandtext" + fi + evalstat=$? + if((evalstat==0)) + then + ((loaded+=1)) + ((doexport)) && export -f $func && andexported=', exported' && ((exported+=1)) + ((doverbose)) && echo "$func autoloaded${andexported}${andevaled}" + if [[ ! $AUTOLOAD_SHIM_OVERHEAD ]] && ((doshim)); then + ## ...we have just loaded the first function shim into + ## memory. Let's calc the AUTOLOAD_SHIM_OVERHEAD size + ## to use going forward. In theory, we could check + ## again here to see if we should optimize and source + ## in this function, now that we now the + ## AUTOLOAD_SHIM_OVERHEAD. In practice, it's not worth + ## duping that code or creating a function to do so for + ## one function. + AUTOLOAD_SHIM_OVERHEAD=$(type $func | grep -v -E "^$1 is a function" | sed "s/$func//g"| wc -c) + export AUTOLOAD_SHIM_OVERHEAD + fi + else + echo "$func failed to load" >&2 + fi + fi + fi + done + ((summary)) && echo "autoload: loaded:$loaded exported:$exported optimized:$optimized overhead:$AUTOLOAD_SHIM_OVERHEAD bytes" +} + +_autoload_dump() +{ + local opt OPTIND + local opt_p='' + local opt_s='' + while getopts ps opt + do + case $opt in + p ) opt_p=1;; + s ) opt_s=1;; + esac + done + + shift $(($OPTIND-1)) + + local exported='' + local executed='' + local func + for func in $(declare | grep -E 'local\\{0,1} AUTOLOADED' | sed -e "s/.*AUTOLOADED=//" -e 's/\\//g' -e 's/[");]//g' -e "s/'//g") + do + if [ -n "$opt_p" ]; then echo -n "autoload "; fi + if [ -n "$opt_s" ] + then + exported=$(declare -F | grep -E "${func}$" | sed 's/declare -f\(x\{0,1\}\).*/\1/') + [ "$exported" = 'x' ] && exported=' exported' || exported=' not exported' + executed=$(type $func | grep 'local IS_SHIM') + [ -z "$executed" ] && executed=' executed' || executed=' not executed' + fi + echo "${func}${exported}${executed}" + done +} + +_autoload_resolve() +{ + if [[ ! "$FPATH" ]]; then + echo "autoload: FPATH not set or null" >&2 + return + fi + + local p # for 'path'. The $() commands in the for loop split the FPATH + # string into its constituents so that each one may be processed. + + for p in $( _autoload_split_fpath ); do + p=${p:-.} + if [ -f $p/$1 ]; then echo $p/$1; return; fi + done + + echo "autoload: $1: function source file not found" >&2 +} + +_autoload_edit() +{ + [ -z "$EDITOR" ] && echo "Error: no EDITOR defined" && return 1 + local toedit + local func + for func in "$@" + do + local file=$(_autoload_resolve $func) + if [[ $file ]] + then + toedit="$toedit $file" + else + echo "$funcname not found in FPATH funcfile. Skipping." + fi + done + + [ -z "$toedit" ] && return 1 + + local timemarker=$(mktemp) + + $EDITOR $toedit + + local i + for i in $toedit + do + if [ $i -nt $timemarker ] + then + local f=$(basename $i) + echo Reloading $f + autoload -r $f + fi + done +} + +_autoload_page() +{ + [ -z "$PAGER" ] && echo "Error: no PAGER defined" && return 1 + local topage + local func + for func in "$@" + do + local file=$(_autoload_resolve $func) + if [[ $file ]] + then + topage="$topage $file" + else + echo "$funcname not found in FPATH funcfile. Skipping." + fi + done + + [ -z "$topage" ] && return 1 + + $PAGER $topage +} + +_autoload_remove() +{ + unset -f "$@" +} + +_autoload_help() +{ + cat <<EOH +NAME + autoload + +SYNOPSIS + autoload [-ps] + autoload [-xuremloyv] [function ...] + autoload -a directory [-oyv] + autoload -f [-oyv] + autoload [-h] + + autoreload [function ...] + +DESCRIPTION + + An implementation of the 'autoload' functionality built into other + shells, of which 'ksh' is the most prominent. It allows for a keeping + the process environment small by loading small 'shim' functions into + memory that will, on first call, load the full text of the given + function and run it. Subsequent calls to the function just run the + function. + + 'autoreload' is a synonym for 'autoload -r'. See below. + +USAGE + + o Each function to be autoloaded should be defined in a single file, + named exactly the same as the function. + + o In order to avoid side effects, do NOT put code other than the + function definition in the file. Unless of course you want to do some + one-time initialization. But beware that if you reload the function + for any reason, you will rerun the initialization code. Make sure + your initialization is re-entrant. Or, better yet, + + *** do NOT put code other than the function definition in the file *** + + o These function definition files should be placed in a directory that + is in the FPATH environment variable. Subdirectories are NOT scanned. + + o The autoload script should be sourced into the current process as + early as possible in process start up. See NOTES below for + suggestions. + + o The calls to the autoload function must be made in the current + process. If your calls are in their own script, that script must be + sourced in. Command line invocations are also sufficient. (But see + '-l' below.) + + o The first time the function is called, the shim function that was + created by the 'autoload' call is what is executed. This function + then goes and finds the appropriate file in FPATH, sources it in and + then calls the actual function with any arguments you just passed in + to the shim function. Subsequent calls just run the function. + +OPTIONS + + -a Autoload (a)ll the functions found in the given directory. + + -f Autoload all the functions found in all the directories on the + FPATH. + + -p Print all the autoloaded functions. + + -s Print all the autoloaded functions and add their export status. + + -x Export the specified functions to the environment for use in + subshells. + + -u Unset the function, so it can be reloaded. + + -r Reload the shims of the specified functions, even if the functions + have been already been executed. This will allow you to modify the + functions' source and have the new version executed next time the + function is called. + + It would be very easy to modify a function's script, run the + function and scratch your head for a long time trying to figure out + why your changes are not being executed. That's why we provide the + '-e' flag described below for modifications. + + Reloads, of course, only apply in the context of the current session + and any future subshell you start from the current session. Existing + sessions will need to have the same 'autoload -r' command run in + them. + + -e Find the scripts in which the specified functions are defined and + start up \$EDITOR on those scripts. Reload the ones that were + modified when you exit \$EDITOR. (Note: If you use 'autoload -e foo' + to edit function 'foo', and then in your editor you separately load + up function 'bar', 'autoload' has no way of knowing that you edited + 'bar' and will NOT reload 'bar' for you.) + + Reloads, of course, only apply in the context of the current session + and any future subshell you start from the current session. Existing + sessions will need to have the same 'autoload -r' command run in + them. + + -m Find the scripts in which the specified functions are defined and + run \$PAGER on them ('m' is for 'more', because 'p' (page) and 'l' + (load) are already used as options in 'autoload'). + + -l When autoloading a function, eval the shim immediately in order to + load the true function code. See "Using '-l'" in the NOTES below for + details. + + -o Optimize. When autoloading, take the time to execute + + 'theCharCount=\$(wc -c \$theFuncFile)' + + for each funcion and + + if \$theCharCount < \$AUTOLOAD_SHIM_OVERHEAD + + don't shim it, just eval directly. + + -y Summar(y). Print the number of loaded, exported and optimized + functions. + + -v Turns up the chattiness. + +NOTES + + o Calling 'autoload' on a function that already exists (either shimmed + or expanded) silently ignores the request to load the shim unless it + has been previously removed (-u) or you force the reload (-r). + + o Changing and reloading a function that has been exported does not + require it be re-exported; the modifications will appear in + subsequent subshells. + + o Using '-1' + + If you are running under set -x and/or set -v, you may see that the + shim does not appear to "work"; instead of seeing the shim first and + the real code subsequently, you may see the shim evaluated multiple + times. + + This may not be an error; review your code. What is most likely + happening is that you are calling the function in subshells via + backticks or $(), or in a script that is not being sourced into the + current environment. If you have not previously called the function + in question at your command line or in a script that was sourced into + the current envirnoment, then the various subshells are going to + encounter the shim and replace with the real code before executing. + + Remember, however, that environment modifications that occur in a + subshell are NOT propagated back to the calling shell or over to any + sibling shells. So, if you call an autoloaded function in a very + tight loop of very many subshells, you may want to make an 'autoload + -l' call before you start your loop. '-l' will instruct 'autoload' to + bypass the shim creation and just source in the function's file + directly. For a few calls, the overhead of repeatedly running the + shim is not expensive, but in a tight loop, it might be. Caveat + Programer. + + o Although the number of functions in the environment does not change + by using 'autoload', the amount of memory they take up can be greatly + reduced, depending on the size of your functions. If you have a lot + of small functions, then it is possible that the shim text will be + larger than your actual functions, rendering the memory savings moot. + + 'small' in this case can be determined by calling the function + 'autoload_calc_shimsize' with the name of the function to determine + its shim size. + + o In order to support the -p and -s options, we need a way to determine + if a function 'func' has been autoloaded or if it was loaded + diredctly. In order to do that, we modify the function's code by + adding the text + + local AUTOLOADED='func'; + + to the shim and to the actual function text, just after the opening + brace. Then supporting -p and -s is just a matter of grepping through + all the function text in memory. Even though grepping through the + environment may not be the most efficient way to support this, it is + the simplest to implement for -p and -s operations that are not + heavily used. + + As a consquence of this (and other reasons), the AUTOLOAD* namespace + is reserved for autoloading. Make sure you check any functions that + you bring under autoload for use of variables or functions that start + with AUTOLOAD and change them. + + o The easiest way to load shims for all functions on the FPATH is to run + + autoload -f -x + + in the profile that gets run for login shells. + + When called in the profile of a login shell where no definitions + exist, -f will load all functions it can find on FPATH and -x will + export all of those functions to be available in subshells when this + is called in a login shell. Using this option will relieve you of the + need to call 'autoload' after Every Single Function Definition, nor + will you need to call it in subshells. + + The only thing left to do is to load up the autoload function itself + and its helper functions. That needs to happen in your profile: + + export FPATH=~/functions # or wherever you stash them + if [ -z $(declare -F autoload) ] + then + . ~/bin/autoload # or wherever you've put it + fi + + The 'if' statement is used to make sure we don't reload autoload + needlessly. Sourcing in the autoload script loads the 'autoload' + function and all of its support functions. Additionally, we export + all of these functions so that they are available in subshells; you + do not have to re-source the autoload file in '.bashrc'. + + o Even with all of these shenanigans, you will find cases where no + matter how hard you try, your autoloaded functions will be + unavailable to you, even if you run 'autoload -x -f'. The typical + condition for this is starting up not a subshell, but a brand new + DIFFERENT shell. And the typical example of this is git extentions. + + At the time of this writing, git extentions work by taking a command + 'git foo' and looking for a file 'git-foo' on the path. 'git' then + executes 'git-foo' in a new shell - it executes your command in + /bin/sh. That's not a subshell of your process. It will not get your + exported shell functions. Ballgame over. + + If you find that you want your functions to be available in such + circumstances, convert them back to plain old scripts, make sure they + are 'sh' compliant and take the read/parse hit every time they are + run. + +EOH +} + +autoload() +{ + if (( $# == 0 )) ; then _autoload_dump; return; fi + + local opt OPTIND OPTARG + local passthru + local dumpopt + while getopts psuema:yxrvlohf opt + do + case $opt in + p|s) dumpopt="$dumpopt -${opt}";; + u) shift $((OPTIND-1)); _autoload_remove "$@"; return;; + e) shift $((OPTIND-1)); _autoload_edit "$@"; return;; + m) shift $((OPTIND-1)); _autoload_page "$@"; return;; + x|r|v|l|y|f|o) passthru="$passthru -$opt";; + a) passthru="$passthru -$opt $OPTARG";; + h) _autoload_help; return;; + *) echo "autoload: usage: autoload [-puUx] [function ...]" >&2; return;; + esac + done + + shift $(($OPTIND-1)) + if [ -n "$dumpopt" ] + then + _autoload_dump $dumpopt + else + _aload $passthru "$@" + fi +} + +autoreload () +{ + autoload -r "$@" +} + +## When we source in autoload, we export (but NOT autoload) the autoload +## functions so that they are available in subshells and you don't have to +## source in the autoload file in subshells. +export -f _aload \ + _autoload_dump \ + _autoload_edit \ + _autoload_help \ + _autoload_page \ + _autoload_resolve \ + _autoload_split_fpath \ + autoload \ + autoload_calc_shimsize \ + autoreload diff --git a/examples/functions/autoload.v4.t b/examples/functions/autoload.v4.t new file mode 100644 index 00000000..6d35d141 --- /dev/null +++ b/examples/functions/autoload.v4.t @@ -0,0 +1,184 @@ +#!/bin/bash + +workdir=$(mktemp -d) + +cp autoload $workdir + +cd $workdir +pwd + +. ./autoload + +funclist='ALTEST_func1 ALTEST_funcexport ALTEST_funcu' +for funcname in $funclist; do + cat <<EOFFUNC > $funcname +$funcname () +{ +echo this is $funcname + +} +EOFFUNC + +done + +export FPATH=$workdir + +autoload ALTEST_func1 ALTEST_funcu +autoload -x ALTEST_funcexport + +ok=0 +failed=0 + +for funcname in $funclist; do + + testname="$funcname loaded" + got=$(type $funcname 2>&1) + if [[ $got =~ "$funcname: not found" ]]; then + echo "## Failed $testname" + ((failed+=1)) + else + echo "ok - $testname" + ((ok+=1)) + + testname="$funcname is a shim" + if [[ ! $got =~ "IS_SHIM" ]]; then + echo "## Failed $testname" + ((failed+=1)) + else + echo "ok - $testname" + ((ok+=1)) + + testname="$funcname shim executed" + $funcname > /dev/null + got=$(type $funcname 2>&1) + if [[ $got =~ "IS_SHIM" ]]; then + echo "## Failed $testname" + ((failed+=1)) + else + echo "ok - $testname" + ((ok+=1)) + fi + fi + fi +done + +funcname=ALTEST_func1 +testname="$funcname shim reloaded" +autoload -r $funcname +got=$(type $funcname 2>&1) +if [[ ! $got =~ "IS_SHIM" ]]; then + echo "## Failed $testname" + ((failed+=1)) +else + echo "ok - $testname" + ((ok+=1)) +fi + +funcname=ALTEST_funcu +testname="$funcname shim unloaded" +autoload -u $funcname +got=$(type $funcname 2>&1) +if [[ ! $got =~ "$funcname: not found" ]]; then + echo "## Failed $testname" + ((failed+=1)) +else + echo "ok - $testname" + ((ok+=1)) +fi + +testname="autoload -p" +got=$(autoload -p | grep ALTEST) +if [[ ! $got =~ "autoload ALTEST_func1" ]] || \ + [[ ! $got =~ "autoload ALTEST_funcexport" ]] ; then +echo "## Failed $testname" + ((failed+=1)) +else + echo "ok - $testname" + ((ok+=1)) +fi + +testname="autoload -s" +echo "Executing $testname, could take a long time..." +got=$(autoload -s | grep ALTEST) +if [[ ! $got =~ "ALTEST_func1 not exported not executed" ]] || \ + [[ ! $got =~ "ALTEST_funcexport exported executed" ]] ; then + echo "## Failed $testname" + echo "## got: $got" + ((failed+=1)) +else + echo "ok - $testname" + ((ok+=1)) +fi + +testname="autoload -r -a $FPATH" +autoload -r -a $FPATH +localfailed=0 +localok=0 +for funcname in $funclist; do + got=$(type $funcname 2>&1) + if [[ $got =~ "$funcname: not found" ]]; then + echo "## Failed $testname - $funcname" + ((localfailed+=1)) + else + ((localok+=1)) + if [[ ! $got =~ "IS_SHIM" ]]; then + ((localfailed+=1)) + else + ((localok+=1)) + fi + fi +done +if ((localfailed==0)); then + echo "ok - $testname" + ((ok+=1)) +else + ((failed+=1)) +fi + +testname="autoload -u $funclist" +autoload -u $funclist +localfailed=0 +localok=0 +for funcname in $funclist; do + got=$(type $funcname 2>&1) + if [[ ! $got =~ "$funcname: not found" ]]; then + echo "## Failed $testname - $funcname" + ((localfailed+=1)) + else + ((localok+=1)) + fi +done +if ((localfailed==0)); then + echo "ok - $testname" + ((ok+=1)) +else + ((failed+=1)) +fi + +testname="autoload -r -f" +autoload -r -f +localfailed=0 +localok=0 +for funcname in $funclist; do + got=$(type $funcname 2>&1) + if [[ $got =~ "$funcname: not found" ]]; then + echo "## Failed $testname - $funcname" + ((localfailed+=1)) + else + ((localok+=1)) + if [[ ! $got =~ "IS_SHIM" ]]; then + ((localfailed+=1)) + else + ((localok+=1)) + fi + fi +done +if ((localfailed==0)); then + echo "ok - $testname" + ((ok+=1)) +else + ((failed+=1)) +fi + +echo $ok passed, $failed failed +exit $failed |
