Can we use Commands *and* (global) Flags? What about a 'default' command? #1974
Unanswered
GwynethLlewelyn
asked this question in
Q&A
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi there! 👋
I was actually a bit surprised that nobody asked this before...
I'm using the latest version of v2, even though I'm quite eager to "upgrade" to v3... as soon as at least some documentation is finished 😁
So, here is my apparently simple question, which, however, I'm not able to implement in a reasonable way.
I'm trying to do a tool that will perform some operations on images. Because I like the
git
approach, I thought that it would be nice to have some commands (some of which have their own specific flags), as well as some global flags, which all commands can use.So consider the commands
compress
,resize
, andconvert
. All can optionally take up to two arguments, i.e. the filename of an existing image, and the output filename. That's the part that works.Some commands need to have a few extra flags. For instance,
convert
has an additional (optional) flag,-g
, which allows the filetype to be specified (strictly speaking, this might not be needed). That works well, sowork, because
webp
is the default image format to convert to.Similarly, the
resize
option has its own set of flags to set height and width, both of which are fine as well (compress
doesn't have any flags, I think, but it may in the future).So far, so good. I can confirm this on the
Action:
for each command, and check what it got, and it's as expected.Now, the problem starts when the flag is actually at the end!
Uh-oh. What happens now is that the
-g
flag is never 'seen' byconvert
. Instead, the command reports that it has four arguments, not two. And since only the two first are acknowledged by the code, well, this sort of works but... the image will be converted towebp
, since that's the default anyway.This can still be sort-of-fixed by changing the help to say, "flags before filenames" or something to the effect.
But now I have another issue. What about the global flags?
For the moment, I have two crucial global flags defined:
-d
(for the debugging level, multiple-d
increases that), and-k
. The latter is, of course, an API key (which can also be retrieved via the environment). Suppose that we'd tried the previous command with the-g
at the end, and we became confused, because we expected a PNG image, and we got a WebP instead. What's going on? Let's increase the debug level:Ok. So, this will give us zero errors. The image is still a WebP! Weird!
Maybe at some point the user figures out, well, probably the
-d
cannot be at the end. Let's try this:Uh oh — say what?! What is this error?!
"Let me see," the user thinks. "Maybe
-d
is not the right flag, let's look at help..." And they type:Arrrrrrgh! And, in despair:
... which gives a very useful description, sure, but a very wrong one.
All right, I can correct the texts, that's not a problem. But the above example show that this is not how commands and subcommands work on, say,
git
, orgpg
, or evengo
(to an extent...go
also has its quirks).Because the problem comes when you've got tons of global flags to parse — they must all come before the command (which is awkward and not intuitive), except for the flags that are specific to that subcommand — these must come after the command, which, well, is just a recipe for trouble. Trouble when answering support requests, that is.
To make matters even slightly worse... where do I actually place the globals?
Consider the following. Besides having filenames as arguments (which is a 'normal' way of expressing things), sometimes it might be more useful to, say, use them as parameters passed by flags (I use
-i
for the input file and-o
for the output file), such as in the following:Although I dislike having the command at the end of everything, instead of at the start, like a 'normal' git-like CLI is supposed to work, the command above is fine, and works exactly as expected.
Since I set
compress
as default, this also means that omitting the command will, indeed, do thecompress
action.But what if someone mistakenly adds a typo?
I would expect one of the two to happen:
compress
which is set as the default; orInstead, none of the above happens.
What happens was tricky for me to debug. With an invalid command, what gets called instead is the Flags
Action
handler (!). And to be even more devious: the filename is set totest.jpg
(since that comes from the flag level), but theconvret
typo is assumed to be the first argument passed to the command line (which, if you think a bit about it, it makes sense from the perspective of the parser). Since the first argument, by definition, is the input filename, it overrides whatever comes after-i
(thus, exactly the opposite of what one would expect), but instead tries to open theconvret
file instead, which of course doesn't exist and throws a strange error...Eventually, one might argue that this last error will make the user double-check on their command line and find the typo. But it would be nice to catch it much earlier on!
That said...
If I understand things correctly, mixing & matching Flags and Commands is Not A Good Idea™, right?
I believe I'll simply add flags instead of commands, and avoid the mess. Perhaps this is something that will get changed under v3?... it would certainly be nice!
Beta Was this translation helpful? Give feedback.
All reactions