-
Notifications
You must be signed in to change notification settings - Fork 576
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
feat(cli): add parse()
with descriptive schema
#4362
base: main
Are you sure you want to change the base?
Conversation
This is the 2nd set of API for parsing cli arguments. It feels confusing to have 2 different sets of APIs for the same purpose. I'd recommend you develop this tool as a 3rd party tool. If that tool got popularity and adoption in the ecosystem, we would be able to consider adopting it in std |
I agree, two wouldn't make too much sense, though the one currently implemented is based on minimist and is not capable of some use cases, especially comparing it to other poplar tools like cliffy, nor compatible with such a schema based approach (as pointed out in #4272)
There are plenty of popular 3rd party tools out there (commander, yargs, cliffy, etc.) that have this declarative approach implemented and are far more popular than minimist. So I think publishing another 3rd party tool wouldn't make much sense to prove that point. The declarative approach this implements avoids the function call chains and replaces them with native objects and arrays to make it less framework-ish, but is similar to the named modules. ...
.option("--foo")
.option("--bar") => { ...
options: [
{ name: "foo", },
{ name: "bar", },
]
} |
Deno is fantastic tool for writing scripts and CLIs in general. I've been using it a lot lately and find that I can get a lot of mileage using just Deno + For parsing args, the @std The direction @timreichen is taking here would be much more preferred imo then the existing |
How do you measure the popularity of packages? Also I don't see what
Without being tested as 3rd party library, how can we be convinced that this design is better than minimist? |
Sidenote: What I mean by declarative approachI mean having all declarations in one object structured in a certain way: Option propertiesWhile property->objectName parseArgs(Deno.args, {
boolean: ["color"], // type is declared here
default: { color: true }, // default value is declared here
negatable: ["color"], // negatable is declared here
});
object->properties parse(Deno.args, {
options: [
{ name: "color", type: Boolean, default: true, negatable: true } // all option properties declared in one object
]
}); SubcommandsAs explored here, minimist does not support subcommand parsing and a possible implementation would lead to messy code due to the nature of property->objectName. Named valuesSince there is no option object but a collection of properties declared, it is not possible to have named values for options. This is a problem, when one wants to be able to print help for a cli. property->objectName ??? object->properties parse(Deno.args, {
options: [
{ name: "foo", value: { name: "VALUE" } }
],
});
Yes, but
I was talking about the fact that |
I don't see this argument very well. import { parseArgs } from "jsr:@std/cli/parse-args";
const args = parseArgs(Deno.args, {
boolean: ["help"],
});
// This becomes { _: [], help: true }, { _: [], help: false }, etc.
if (args.help) {
console.log("Usage");
Deno.exit(0);
} Isn't Also I don't see well what
But this suggested API design isn't similar to |
@timreichen BTW what do you think about |
I think it is very bare-bone. But I like how one defines the options as an object with properties. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4362 +/- ##
==========================================
- Coverage 91.44% 91.40% -0.04%
==========================================
Files 480 481 +1
Lines 37318 37527 +209
Branches 5316 5382 +66
==========================================
+ Hits 34126 34303 +177
- Misses 3136 3167 +31
- Partials 56 57 +1 ☔ View full report in Codecov by Sentry. |
ref: #4272
This PR adds
parse()
that takes a descriptive schema for parsing args.This is inspired by rusts
clap
,yargs
andcommanderjs
.This needs more tests for edge cases and some discussions about features like
Option.value.accepted?: T[]
for allowed values as a shortcut for`Option.fn: (value) => { if (!accepted.includes(value)) { throw new Error("...")}
Option.value.min?: number
for a minimum of arguments takenOption.value.max?: number
for a maximum of arguments takenThe type generics also need some rework to imply correct types based on
Option.default
andOption.type
for returnedresult
and insideOption.fn(value: T)
Feedback and suggestions are very welcome. @iuioiua @ngdangtu-vn