summaryrefslogtreecommitdiff
path: root/Functions/TCP/zgprintf
diff options
context:
space:
mode:
Diffstat (limited to 'Functions/TCP/zgprintf')
-rw-r--r--Functions/TCP/zgprintf70
1 files changed, 70 insertions, 0 deletions
diff --git a/Functions/TCP/zgprintf b/Functions/TCP/zgprintf
new file mode 100644
index 000000000..c448b35a2
--- /dev/null
+++ b/Functions/TCP/zgprintf
@@ -0,0 +1,70 @@
+# 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