summaryrefslogtreecommitdiff
path: root/functions/arguments.sh
blob: 2c1266f786cb27d26162d0b41559062be7e2ee6f (plain)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/bin/sh

## live-build(7) - System Build Scripts
## Copyright (C) 2016-2020 The Debian Live team
## Copyright (C) 2006-2015 Daniel Baumann <mail@daniel-baumann.ch>
##
## This program comes with ABSOLUTELY NO WARRANTY; for details see COPYING.
## This is free software, and you are welcome to redistribute it
## under certain conditions; see COPYING for details.


Arguments ()
{
	# This function is used for handling arguments both at the frontend (`lb`)
	# level and at the command level, since both accept almost the same basic
	# argument set, with little difference in response to them.
	#
	# We enlist the help of getopt here which takes care of some of the
	# intricacies of parsing for us. Note that getopt does not itself
	# understand the concept of "command" arguments, and the behaviour of it
	# shuffling non-options (those arguments that are not options or option
	# values) to the end of the argument list would present a difficulty, if it
	# were not for the fact that you can control this behaviour with use of the
	# `POSIXLY_CORRECT` environment variable; setting this variable causes
	# getopt to stop parsing arguments once it encounters the first non-option,
	# treating all remaining arguments as being non-options. Note also that
	# getopt always outputs a `--` separator argument between option (including
	# option value) arguments and non-option arguments.
	#
	# At the frontend we need getopt to only parse options up to the point of
	# a command. A command as far as getopt is concerned is simply a
	# "non-option" argument. Using the above mentioned `POSIXLY_CORRECT`
	# environment variable when parsing for the frontend, we can thus have
	# getopt process options up to the first non-option, if given, which should
	# be our command. We can then pass back any remaining arguments including
	# the command argument, for a second command-stage handling. If no command
	# is given, this is trivial to handle. If an invalid option is used before
	# a command, this is caught by getopt.
	#
	# When a command is run, it is passed all remaining arguments, with most
	# scripts then passing them to this function, with argument parsing then
	# occurring in command-context, which just so happens to use almost the same
	# set of arguments for most scripts (the config command is a notable
	# exception).
	#
	# It is true that many of the common options have no effect in the frontend
	# currently, but some do, such as colour control, and others could do in
	# future or during development.
	#
	# Note, do not worry about options unavailable in frontend mode being
	# handled in the case statement, they will never reach there if used for the
	# frontend (i.e. before a command), they will result in an invalid option
	# error!

	local LONGOPTS="breakpoints,color,debug,help,no-color,quiet,usage,verbose,version"
	local SHORTOPTS="huv"

	local IS_FRONTEND="false"
	if [ "${1}" = "frontend" ]; then
		shift
		IS_FRONTEND="true"
	else
		LONGOPTS="${LONGOPTS},force"
	fi

	local GETOPT_ARGS="--name=${PROGRAM} --shell sh --longoptions $LONGOPTS --options $SHORTOPTS"

	local ARGUMENTS
	local ERR=0
	if [ "${IS_FRONTEND}" = "true" ]; then
		ARGUMENTS="$(export POSIXLY_CORRECT=1; getopt $GETOPT_ARGS -- "${@}")" || ERR=$?
	else
		ARGUMENTS="$(getopt $GETOPT_ARGS -- "${@}")" || ERR=$?
	fi

	if [ $ERR -eq 1 ]; then
		Echo_error "Invalid argument(s)"
		exit 1
	elif [ $ERR -ne 0 ]; then
		Echo_error "getopt failure"
		exit 1
	fi

	# Replace arguments with result of getopt processing (e.g. with non-options shuffled to end)
	# Note that this only affects this function's parameter set, not the calling function's or
	# calling script's argument set.
	eval set -- "${ARGUMENTS}"

	local ARG
	for ARG in "$@"; do
		case "${ARG}" in
			--breakpoints)
				_BREAKPOINTS="true"
				shift
				;;

			--color)
				_COLOR="true"
				_COLOR_OUT="true"
				_COLOR_ERR="true"
				shift
				;;

			--no-color)
				_COLOR="false"
				_COLOR_OUT="false"
				_COLOR_ERR="false"
				shift
				;;

			--debug)
				_DEBUG="true"
				shift
				;;

			--force)
				_FORCE="true"
				shift
				;;

			-h|--help)
				if [ $(which man) ]; then
					if [ "${IS_FRONTEND}" = "true" ]; then
						man ${PROGRAM}
					else
						man ${PROGRAM} $(basename ${0})
					fi
					exit 0
				elif [ "${IS_FRONTEND}" = "true" ]; then
					Usage 0
				fi
				;;

			--quiet)
				_QUIET="true"
				shift
				;;

			-u|--usage)
				Usage 0
				shift
				;;

			--verbose)
				_VERBOSE="true"
				shift
				;;

			-v|--version)
				echo "${VERSION}"
				exit 0
				;;

			--)
				shift
				break
				;;

			*)
				if [ "${IS_FRONTEND}" = "true" ]; then
					# We have handled all frontend options up to what we assume to be a command
					break
				fi
				Echo_error "Internal error, unhandled option: %s" "${ARG}"
				exit 1
				;;
		esac
	done

	# Return remaining args
	# Much more simple than trying to deal with command substitution.
	REMAINING_ARGS="$@"
}