summary refs log tree commit diff
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