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
Naming is confusing for a new user (at least this one) #50
Comments
I didn't pay much attention to those names because users don't need to intact with them directly, but I see your point - documentation aspect is going to be better. Will rename on the next version bump.
Possibly, I tend to think of them as assembling them in terms of natural language: "i want extra spicy, with extra rice to the side, Kou Shui Ji" or whatever. Fits well with some languages, still valid in English. Putting everything into prefix leads to combinatorial explosion: we have switches, flags, required flags, positonals, etc. And some of them can be I'm open to suggestions to how to convey this idea better. Probably better blurb in a tutorial?
https://docs.rs/bpaf/latest/bpaf/struct.Named.html I tried to explain terminology here. Things with a name could be flags, switches or arguments.
Right, this is what it is. I'll update the docs, thank you for the suggestions.
Documentation tries to explain the behavior: It's a flag that only parses when it's actually present which allows composing them with Since there's only a few names in the API I'm not trying to put full meaning into the name itself, rather making so they are easy to type. The alternative name I was thinking of is a
Probably not the best possible name, I agree. We'll see if I can come up with something better.
Hmm... Maybe, but this naming seems more natural in Haskell.
Thank you for your feedback, much appreciated. |
The problem is that there is nothing prefacing
I wasn't thinking you needed factories for every combination. One route is to just use "flag" to refer to the named portion of the argument so you have
Users easily get confused by terminology like this, even if it comes from common precedent. We found this frequently with clap and we've been iterating on it to have less need for there to be something that needs defining. Also "argument" is a very overloaded word. I'm not sure which part of getopts documentation you were looking at but my quick glance at some it sounded like it talking in terms of being an argument muncher. When you separate from that context, "argument" is being used in multiple distinct ways and can be confusing.
Sounds like
"natural in Haskell" should be a red flag :). In my working with CLIs across ecosystems, when I see a "parser" without any qualifiers, my immediate thought is "argument parser" or "the thing I use". This is why I made sure that clap's |
True, but usually context is within 2-3 words - you can have short name, long name, I'm simply trying to keep combinatoric and derive APIs close to each other when possible. Anyway, something to keep in mind.
For the top level functions to create
Hmm.... ❤️ I think I can totally make it work and do the same for positional too. Wasn't possible in pre 0.5.x which explain why there are
To be honest it comes from me reading it a while ago and mostly relying on my memory :) Okay, doing one more pass over terminology is important then. Any reading you can recommend?
They are required, but they also require a value. Flags/switches are optional by default. Present - parses as one value, absent - parses as a different value. req_flag gives you tri-state switches and similar scenarios when you want to get one out of several flags (value-less arguments?) from the user.
Hmm... I think you convinced me. Do you mind if I ping you to review the terminology/naming once I have it? |
Ok, so
Go for it |
A little off topic but I've taken a crack at a new clap/bpaf comparison and would appreciate feedback to improve accuracy and reduce inherent bias. Rather than a blog post or people only finding it when browsing one of our repos, I decided to explore putting it in the argparse-rosetta-rs repo as a more neutral and evergreen place. |
Re method names: I personally found the short names fine, because it's the same way they are in haskell's optparse-applicative. In fact, I still haven't read the docs for bpaf and am still relying on my haskell knowledge. But your point that seeing just |
I'd caution against the bias of "it worked this way in haskell" if the hope is to have a wider reach than Haskell developers as Haskell approaches to problems aren't always intuitive to the wider programming audience. |
Right, I'm keeping this ticket open to collect thoughts from non Haskell users. Also a question - is I have a parser for interactive command line that uses more Haskell-like approach https://github.com/pacak/omnomnomicon/blob/master/src/tutorial.rs - I'll probably end up rewriting it before releasing. |
I'm just learning of
IMHO, yes, the "rules" are looser for the latter in a couple ways:
My first impression is this isn't a deal breaker for using the crate or anything, but |
Here's some thoughts about names and APIs. No particular order:
It would be nice to have some APIs to stop the parsing of child types. Like serde with its I hope it helps! |
Will add something, good point.
Problem with #[derive(Bpaf, Debug, Clone)]
enum Optimization {
#[bpaf(long("optimize"))]
/// optimize
Yes,
#[bpaf(long("no-optimize"))]
/// no optimize
No,
#[bpaf(skip)]
Unspecified
} And even that I'm not sure if it's needed, I'd use dual state + fallback so not to deal with I suspect the idea of making everything
Problem here is that
It helps a lot, will try to update the documentation to address those points. |
Yeah I thought as much for
I believe that would work too! If the default value happens to be The library is amazing: simple and efficient, good documentation and gives very useful features! |
FWIW you can already achieve this result by using |
Browsing the docs, the API feels very abstract and I have a hard figuring out what the different API items are and what they are for
This is a follow up to my reddit comment.
I tend to look first at the types of a crate. In doing so, I see a "Named" and "Positional". I think just adding an
Arg
suffix would be a big help here (NamedArg
,PositionalArg
).Then if I look at an example, I might see something like
long
, without an antecedent feels incomplete. I normally think of "argument" as an element instd::env::args_os
, a positional argument, or--speed SPEED
, not the value being passed in. Personally, I would recommend the example look likeBoth the naming change and the order clarifies what this is and how its used.
EDIT: Oh but the order is required for converting it into a parser. That is unfortunate.
I see in the description for
Named
, a-speed SPEED
is being referred to as an argument. If there is a distinguishing name, normally I would expect it to be "option".I also found the distinction between
switch
andflag
confusing. It sounds likeflag
allows storing any type andswitch
is a specialization of aflag
specifically for bools? One way of clarifying that relationship is by taking the text "Simple boolean flag" and adding a link so itsSimple boolean [flag][Named::flag]
as this makes it clear that "flag" is specifically referring to the same concept as theflag
function.. Speaking of, it seems more intra-doc links could generally exist (I noticedlong
doesn't have them).Some other quick naming thoughts
req_flag
doesto_options
always confuses me, in part because I miss the "s", in part because I think ofOption
since this is Rust, and in part because its a descriptor without the rest of the context. Personally, I would renameParser
toSubParser
andOptionsParser
toParser
(I also always sawParser
and thought that meant top-level).At this point I'm stopping my read through, so can't say whether there are more or if that is the extent of it.
The text was updated successfully, but these errors were encountered: