Hello again, developers. Don't worry, this is the last e-mail I was planning to send :). Currently, PMS doesn't have any convention for option passing. In particular, we have:
a. has_version and best_version having long '--host-root' (no
parameters).
b. dodoc, doheader, doins have short '-r' option. docompress has short
'-x' option.
c. dohtml has whole lot of short options, some taking parameters.
d. doman has -i18n=LANG old-style long option.
(econf, emake, einstall are pass-through so they don't count)
In other words, it's an inconsistent mess. I think we should set up
a few basic rules for functions in PMS, and hopefully spread them into
eclasses as well.
While normally I'd suggest following getopt_long() as close
as possible, I don't think this is the best way here since:
1. I'm not ware of any sane, dep-free, portable way of reusing
getopt_long() from bash.
2. Implementing the whole option parsing would introduce a lot of extra
code for each function.
3. Most of the helpers take no or at most a single option.
4. We can assume that ebuilds are supposed to use canonical command
lines.
That said, I suggest the following basic rules:
1. Options must precede positional parameters on the command-line.
Interspersing options and positional parameters is not allowed.
2. Each short option must be specified as a separate parameter.
Specifying multiple short options in one parameter is not allowed.
3. If a helper supports any options, then the positional parameters may
not resemble options. In particular, passing any positional parameters
beginning with '-' is not allowed.
4. [optionally] If a helper supports any options, '--' option may be
used to terminate option parsing. All parameters following it will be
treated as positional parameters, and rule 3. doesn't apply to
parameters following '--'.
5. Helpers should define both short and long variants for each option
they provide.
6. If the option takes a parameter, it should be passed as
the parameter immediately following it. Concatenating option
and the parameter is not allowed. Interspersing multiple options
and their parameters is not allowed.
Explanation and rationale;
(1) Interspersing options and positional parameters is not that useful
in scripts. It's helpful in interactive shell when you may forget to
pass some option and add it after files but in ebuild you'd rather use
the canonical option order. It would also decrease readability.
Disallowing this allows us to use very simple parsers for single-option
commands, like:
if [[ ${1} == -r ]]; then ...; fi
(2) Specifying multiple options via a single parameter (e.g. '-ab' for
'-a -b') makes parsing quite hard and also decreases readability. I'd
dare say simplicity in using the 'longer' form outweighs the gain of
shortening command lines.
That said, most of our commands take no more than a single option :).
(3) This one is quite understandable but it may become blurry with all
the restrictions given above. In particular, one may assume that
'foo -a bar -b' will treat '-b' as positional parameter. Since this
will be very unreadable and unpredictable, we should ban that use.
Similarly, to keep option parsing simple we may not implement any
specific checks for invalid options. Then, 'foo -a -b' would treat
unsupported '-b' option as a positional parameter, and we don't want to
support that.
The extra 'if a helper supports any options' is mostly supposed to
handle output helpers like elog that may accidentally start a line with
'-'. Since they are not supposed to handle any options, and mostly
resemble the 'echo' built-in (thinking of the POSIX one, not the ugly
bashism), I don't feel like we should require '--' in them.
(4) I don't have a strong opinion about that. It is rather unlikely
that we will ever need to support positional parameters that start with
'-' but supporting this when option parsing is in-place is rather
simple:
if [[ ${1} == -- ]]; then shift; break; fi
As for the functions that are more likely to meet rogue '-', i.e. elog
and friends, I think we oughtn't support option parsing at all. For
these functions, '--' will be treated literally -- that's the reason
for the 'if a helper supports any option' clause.
(5) This is pretty much a open field for dicussion. Implementing more
than one alias for a option is rather straightforward. Either:
[[ ${1} == -r || ${1} == --recursive ]]
or:
-r|--recursive) ...;;
in a case statement.
Most of the developers will prefer the short forms. However, the long
forms are more readable and could be useful in case of the more
confusing options. For example, 'die --respect-nonfatal' is the only
sane way of explaining what the option does I can think of ;).
If developers don't feel like we ought to support both long and short
options, we should probably go for short options only.
(6) Long story short, '-a foo -b bar', not '-afoo -bbar' and definitely
not '-a -b foo bar' :). Because they are confusing and very confusing,
respectively.
Additionally, we may not want to support '--foo=bar' to avoid extra
code in option parsing, e.g.:
--foo) sth=${2}; shift;;
--foo=*) sth=${1#*=};;
However, I don't have a strong opinion on this since it's relatively
simple to achieve.
What are your thoughts?
--
Best regards,
Michał Górny
signature.asc
Description: PGP signature
