# Generalised printf. # Arguments of the form -%X=... give the output to be used with # the directive %x. # # -P indicates that any unhandled directives are to be # passed to printf. With this option, any %-escapes passed to printf # are assumed to consume exactly one argument from the command line. # Unused command line arguments are ignored. This is only minimally # implemented. # # -R indicates the value is to be put into REPLY rather than printed. # # -r indicates that print formatting (backslash escapes etc.) should # not be replied to the result. When using -R, no print formatting # is applied in any case. emulate -L zsh setopt extendedglob local opt printf fmt usereply match mbegin mend raw c typeset -A chars chars=(% %) while getopts "%:PrR" opt; do case $opt in (%) if [[ $OPTARG != ?=* ]]; then print -r "Bad % option: should be -%${OPTARG[1]}=..." >&2 return 1 fi chars[${OPTARG[1]}]=${OPTARG[3,-1]} ;; (P) printf=1 ;; (r) raw=-r ;; (R) usereply=1 ;; esac done (( OPTIND > 1 )) && shift $(( OPTIND - 1 )) [[ -z $usereply ]] && local REPLY REPLY= if (( $# )); then fmt=$1 shift fi while [[ $fmt = (#b)([^%]#)%([-0-9.*]#?)(*) ]]; do REPLY+=$match[1] c=$match[2] fmt=$match[3] if [[ -n ${chars[$c]} ]]; then REPLY+=${chars[$c]} elif [[ -n $P ]]; then # hmmm, we need sprintf... # TODO: %ld etc. REPLY+=`printf "%$c" $1` (( $? )) && return 1 shift else print -r "Format not handled: %$c" >&2 return 1 fi done REPLY+=$fmt [[ -z $usereply ]] && print -n $raw - $REPLY return 0