about summary refs log tree commit diff
path: root/Functions/TCP/zgprintf
blob: c448b35a21e46c6659bd508b9e0d97b86846c323 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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