This script exploits bash's weird interpretation of POSIX's requirement that declaration builtins overloaded by functions must not modify the parsing of the arguments. Bash even extends this requirement to nonstandard extensions such as arrays. This typeset wrapper parses options by stealing the (approximately correct) optstring from ksh. It modifies each assignment then prints the effect of the command as a side-effect.
Code:
#!/usr/bin/env bash
shopt -s lastpipe extglob expand_aliases
function unset2 {
\command unset "$@"
}
alias 'typeset=\command typeset'
function typeset {
local -; set +m
typeset -A opts
typeset -i OPTIND=1
typeset REPLY os OPTARG
{
printf :
ksh -c 'typeset --\?\?api' 2>&1
} | awk '/^\.OP . -/ { printf "%s", ($2 ($4 ~ /^flag|[^:]+:optional/ ? "" : ":")) }' |
IFS= read -rd '' os
while getopts "$os" REPLY; do
case $REPLY in
[:?]) return 1 ;;
*) opts+=([$REPLY]=$OPTARG)
esac
unset -v OPTARG
done
shift "$((OPTIND - 1))"
unset2 -v os OPTIND OPTARG
unset -v REPLY
typeset compound scalar IFS=
printf 'typeset %.*s%s -- ' "$((!!${#opts[@]}))" - "${!opts[*]}"
[[ ${!opts[*]} == *!(n|!([Aa]))* ]] && compound= || scalar=
typeset ${compound+\-}${scalar+\+}n REPLY
IFS=' '
for REPLY do
${compound+\:} printf -v "${REPLY%%=*}" %q "${REPLY#*=}"
REPLY=${REPLY%%=*} ${compound+\:}
${compound+\:} command typeset -n REPLY
REPLY+=([${#REPLY[@]}${scalar+ - 1}]+=${scalar+\\ }lol!)
set -- ${compound+"$(printf '[%s]=%q ' "${REPLY[@]@k}")"} ${scalar+"$REPLY"}
${scalar+\:} set -- "${1%%?}"
printf %s "${!REPLY}" =${compound+\(} "${1}${compound+)} "
${compound+\:} command typeset +n REPLY
done
echo
}
unalias typeset
function lol {
typeset -ua lolarray=(moo! blerg!)
typeset -x herp=hello! derp='hi there'
}
# set -x
lol "$@"
# vim: set ft=bash fenc=utf-8 ff=unix ts=4 sw=4 noet :
Script output:
typeset -ua -- lolarray=([0]=MOO\! [1]=BLERG\! [2]=LOL\!)
typeset -x -- herp=hello\!\ lol! derp=hi\ there\ lol!