You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Many of the coreutils share arguments, possibly with some slight variations. Some examples:
head & tail
cksum, sum, b2sum, sha1sum, etc.
base32, base64, basenc
mv, cp
We could copy-paste the Arguments enums for each of these, but I think we can do better.
Essentially, it must be possible to compose multiple Arguments enums. Let's first establish what's currently possible. Given two enums Arg1 and Arg2, we could make a new enum Arg for which the Arg::next_arg calls Arg1::next_arg and Arg2::next_arg in order. That works somewhat but has a problem with abbreviations of long options, because Arg1::next_arg and Arg2::next_arg do not know about each other's long arguments. They also don't know about each other's positional indices.
So we have to break up the trait into multiple methods. One for each of the following operations, which can be composed:
Parse short option.
Get an iterator of long options.
Parse long option.
Get the maximum number of positional arguments.
Parse positional argument.
Get the help text per argument (so we can sort it)
(And parsing free arguments once those are implemented)
The next_arg method can then be provided based on these, possibly only implemented by ArgumentsIter.
That's all the internal plumbing that needs to change, but what does it look like in the API?
One option is to provide a macro that creates an automatic implementation:
This also provides a nice way of grouping options in --help. A variation on this design makes a distinction between an ArgumentGroup and Arguments, where the former can be included into the latter. This makes sense, because Arguments have, for instance, about text and version info, whereas ArgumentGroup doesn't need that. Additionally, we can restrict ArgumentGroup to not include positional arguments, because those get hard to reason about (and hard to implement in proc macros).
Taking this further can lead to some pretty cool stuff, by combining ArgumentGroup with Value. For example, we can do this:
Many of the coreutils share arguments, possibly with some slight variations. Some examples:
We could copy-paste the
Arguments
enums for each of these, but I think we can do better.Essentially, it must be possible to compose multiple
Arguments
enums. Let's first establish what's currently possible. Given two enumsArg1
andArg2
, we could make a new enumArg
for which theArg::next_arg
callsArg1::next_arg
andArg2::next_arg
in order. That works somewhat but has a problem with abbreviations of long options, becauseArg1::next_arg
andArg2::next_arg
do not know about each other's long arguments. They also don't know about each other's positional indices.So we have to break up the trait into multiple methods. One for each of the following operations, which can be composed:
The
next_arg
method can then be provided based on these, possibly only implemented byArgumentsIter
.That's all the internal plumbing that needs to change, but what does it look like in the API?
One option is to provide a macro that creates an automatic implementation:
That works but I think I prefer supporting it via the derive macro instead, which makes it easier how it's structured:
This also provides a nice way of grouping options in
--help
. A variation on this design makes a distinction between anArgumentGroup
andArguments
, where the former can be included into the latter. This makes sense, becauseArguments
have, for instance, about text and version info, whereasArgumentGroup
doesn't need that. Additionally, we can restrictArgumentGroup
to not include positional arguments, because those get hard to reason about (and hard to implement in proc macros).Taking this further can lead to some pretty cool stuff, by combining
ArgumentGroup
withValue
. For example, we can do this:We could also allow the
--format
argument to be defined like this:The text was updated successfully, but these errors were encountered: