New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use a core flag parser other than stdlib flag
to unlock wider range of arg types
#1583
Comments
(Moving from #833 (comment) to here) |
This is reasonable imo, I haven't seen any use for not starting (non-argument) flags without |
@jtagcat it's a unix-y-centric way of working, imho. For example, in Windows there's strong precedent for |
Ok, fair point. I'd say multiple prefixes at once gets unreasonably complex. Yet everything is possible by swapping out (not adding to) the prefix and/or the non-space delimiter ( For arguments without a key (eg. Performance of multiple parses isn't an issue. First, arguments are only parsed once (on app startup). With modern processors, multiple calls may even be more performant vs a messy monolithic do-all parser. But I'd not touch the topic right now at all. A bad standard is better than 5 standards. In my opinion, the spec I have in FORMAT.md is fairly good, well-known, and used. Even (new) Microsoft CLI utilities use GNU-like arguments. Everone is free to fork (and wrap the library or whole cli binary) for their own niche. I want to make the codebase maintainable (and workable) for as many as possible, including myself. One niche use-case just isn't worth it. I want to keep it as simple as possible. There isn't anything we are removing compared to stdlib flags. Right now, getting v3 released is the priority. |
@jtagcat I appreciate the points you're making. I'd love to see what an integration of harg for the purpose of addressing this issue looks like, if you're up for doing that work. I'm personally interested in exploring this approach, if only to better understand how the urfave/cli layer can change. |
@meatballhat @jtagcat Both of you make good points. I think as software devs we'd like to make software perfect - covers all use cases, very performant, infintely extensible and so on. While a complete new parser is good, we need to see how much we can stretch stdlib flag to the max to cover most of the use cases. We cannot satisfy every user's use cases so its better to list what features beyond what urfave/cli/v2 offers do we want to achieve. |
@dearchap Are you suggesting that this issue is not worth pursuing (yet)? 😅 imho the workarounds in place to support nested commands and compound short flags are indications that we've already gone past the point of stretching stdlib flag to the max. Or do I misunderstand what you mean? ❤️ |
@meatballhat What are the most requested features of this library ?
if we have those two knocked out, rest of the features are icing on the cake no ? |
Update: https://github.com/jtagcat/harg is tested and ready to integrate.
I think I'd like to keep help text, defaults, and bash completion outside the package. I'll dig around this @dearchap @meatballhat requesting review if you have the time. |
@jtagcat imho https://github.com/jtagcat/harg is lovely as heck and I would very much like to see what an integration with urfave/cli/v3 looks like 😁 Is this work you're planning to do soon? |
@meatballhat: Soon, but not soon. I have half a workday today, then maybe next Sunday, then longer periods starting around 18. dec. Honestly, it plays such a major role in the cli package, a complete rewrite (creatively egoistically named What components are there?
It should also include everything in the v3 milestone. Anything I missed? The only parts I expect to get stuck on are shell completions, and yaml. They are not critical for a v3 beta, though. Footnotes
|
@jtagcat do I understand correctly that you are recommending against integrating |
@jtagcat could you provide some examples of how users would use the harg library ? Maybe a definition for a int flag and a float slice . Thanks |
I meant |
Users using harg through cli:One way would be to do as it is now: Define flags (and aliases, etc), and then retrieve by string. Just the underlining library differs. (I would expect a flag to be available for all subcommands unless explicitly marked as local.) I don't know if it is ergonomically possible to type the lookup string, as it is in harg tests:
I probably need some time to think about it. If you meant direct use of |
One thing maybe needing explaining is Value-typing is still available:
This provides completion and validation in the IDE, and ctrl-clicking (jump to definition, or show all uses). |
I have a chicken and egg problem. It originates from boolean flags not consuming the next argument, thus options in general maybe consuming the next argument, what is a problem when determining whether a subcommand is a value for an option, or a subcommand. One could expect all of the following to work (using only long options for sake of simplicity):
I would prefer globals to be explicitly defined. Helptext can be managed with categories (and optionally hiding globals in subcommand helptext). This would mean that globals have to be defined in all subcommands (flag definitions can be reused with variables). Implicit globals would mean that flags have a recursive flag in their definition, and only ever defined once. While parsing, the arguments are parsed against root command's definitions. When a subcommand (choke) is found, everything until the subcommand is parsed again for only recursive definitions. Next, the subcommand arguments are parsed (recursively). Option order would always matter. Right now, implicit globals sound better. This might need more examples. Cobra uses restrictive explicit style, Docker ordered implicit. Kubernetes stuff uses double-defined unordered ordered implicit globals. Meaning that global options are defined on the global level and local level. Local flags before subcommands are disallowed. Double-defined implicit globals could in theory be implemented (generically, consumable simply as a cli library), with the only downside being half-implicitness (flags are defined globally, but their action has to be always remembered and defined in subcommands). This could be solved with linting. tldrI think recursive double-defined implicit ordered globals is actually doable, roadblock solved by writing a letter to a rubber ducky. I need more time. |
Progress at https://github.com/jtagcat/harg/tree/hcli. It's coming together beautifully imo, needs a workweek more (x2 for unused feature creep). If there is interest, I still would like to make it a future version of urfave/cli. |
@jtagcat We have support for persistent flags in v3 right now. So if you mark a flag as persistent it will be available to all subsequent sub commands. if sub command defines same flag it will take precedence over persistent one. |
@jtagcat Right now we have 2 competing arg parsers, yours and @meatballhat 's argh. At some point we have to make a decision which path is preferred. |
Two requested parses:
In my current project I've built an inefficient args parser which moves flags and positional arguments to their correct positions before sending to app.Run(...). Example: Given an App &cli.App{
Commands: []*cli.Command{
{
Name: "function",
ArgsUsage: "<name>",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "command",
},
},
},
},
}
Whenever we release current iteration it will be here: https://github.com/taubyte/tau/tree/main/cli/args |
Above is now released, you can see my tests here: https://github.com/taubyte/tau/blob/main/cli/args/args_test.go |
@skelouse sorry for the long delay! I think your requests are accounted for, but I'll definitely want more feedback once this is closer. I've been occupied with other life adventures since ~January-ish but I've got some vacation time coming up 🤞🏼 |
I have lost focus on this more than once, and IIUC others in threads here have also moved on, so I'd like to propose that this is not a blocker for v3 release. @urfave/cli WDYT? |
I agree. We probably handle most of the use cases for a cli utility. Refitting a new parser is a nice engineering project but adds only incremental value |
tl;dr - By switching away from stdlib
flag
, we will be able to support a wider range of capabilities with significantly less workaround code.Much of the code around here is arguably working around stdlib
flag
, for example:FlagSet.Var
)By building on top of stdlib
flag
, we are limited to two categories of string arguments:-
-
flag
🤷🏼There are many other command line argument parsers available in the Go third-party package ecosystem such as:
flag
argparse
The text was updated successfully, but these errors were encountered: