This repository has been archived by the owner on Jul 19, 2020. It is now read-only.
/
optar.sh
executable file
·131 lines (113 loc) · 2.84 KB
/
optar.sh
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#/usr/bin/env bash
parse-options() {
#input - $@ or string containing shorts (-s), longs (--longs), and arguments
#returns - arrays with parsed data and opts set as vars
#exports a var for each option. (-s => $s, --foo => $foo, --long-opt => $long_opt)
#"-" are translated i(nto "_"
#"--" signals the end of options
#shorts take no arguments, to give args to an option use a --long=arg
if [[ "$1" == "--debug" ]]; then
printf "\n\e[4;33m$(printf %${COLUMNS}s) $(center DEBUGGING ${FUNCNAME[0]}!)$(printf %${COLUMNS}s)\e[0m\n"
set -x
fi
if [[ "$#" == 0 ]]; then
return
fi
# Opts we may have inherited from a parent function also using parse-options. Unset to void collisions.
if [ "$allOptions" ]; then
for opt in ${allOptions[@]}; do
unset $opt
done
fi
local argn long short noMoreOptions
#echo to split quoted args, repeat until no args left
for arg in $(echo "$@"); do
argn=$(($argn + 1))
# if flag set
if [[ "$noMoreOptions" ]]; then
#end of options seen, just push remaining args
arguments+=($arg)
continue
fi
# if end of options is seen
if [[ "$arg" =~ ^--$ ]]; then
# set flag to stop parsing
noMoreOptions="true"
continue
fi
# if long
if [[ "$arg" =~ ^--[[:alnum:]] ]]; then
#start on char 2, skip leading --
long=${arg:2}
# substitute any - with _
long=${long/-/_}
# if opt has an =, it means it has an arg
if [[ "$arg" =~ ^--[[:alnum:]][[:alnum:]]+= ]]; then
# split opt from arg. Ann=choco makes export ann=choco
export ${long%=*}="${long#*=}"
longsWithArgs+=(${long%=*})
else
#no arg, just push
longs+=($long)
fi
continue
fi
# if short
if [[ "$arg" =~ ^-[[:alnum:]] ]]; then
local i=1 #start on 1, skip leading -
# since shorts can be chained (-gpH), look at one char at a time
while [ $i != ${#arg} ]; do
short=${arg:$i:1}
shorts+=($short)
i=$((i + 1))
done
continue
fi
# not a long or short, push as an arg
arguments+=($arg)
done
# give opts with no arguments value "true"
for short in ${shorts[@]}; do
export $short="true"
done
for long in ${longs[@]}; do
export $long="true"
done
export allOptions="$(get-shorts)$(get-longs)"
}
#part of parse-options
get-shorts() {
if [ "$shorts" ]; then
for short in ${shorts[@]}; do
echo -ne "$short "
done
fi
}
#part of parse-options
get-longs() {
if [ "$longs" ]; then
for long in ${longs[@]}; do
echo -ne "$long "
done
fi
if [ "$longsWithArgs" ]; then
for long in ${longsWithArgs[@]}; do
echo -ne "${long}* "
done
fi
}
#part of parse-options
get-arguments() {
for arg in ${arguments[@]}; do
echo -ne "$arg "
done
}
get-optionsWithArgs() {
for opt in ${shortsWithArgs[@]}; do
echo -ne "${opt}* "
done
for opt in ${longsWithArgs[@]}; do
echo -ne "${opt}* "
done
printf "\n"
}