Skip to content
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

Basic argument parsing #117

Closed
dsherret opened this issue Mar 13, 2023 · 5 comments
Closed

Basic argument parsing #117

dsherret opened this issue Mar 13, 2023 · 5 comments

Comments

@dsherret
Copy link
Owner

dsherret commented Mar 13, 2023

Generally when writing scripts, you don't need complex argument parsing and want something that can easily be figured out by looking at the code. You also don't need help text. For that reason, I think an approach like the following might be more appropriate than something more featureful like deno_std's argument parser.

$.args.on("prepare", () => {
  console.log("Preparing...");
});

$.args.on("build", () => {
  console.log("Building...");
});
> deno run -A script.ts prepare
Preparing...
> deno run -A script.ts build
Building
> deno run -A script.ts other
Unknown command: other

Possibilities:
  - prepare
  - build

More complex example:

const args = $.args(); // shorthand for `const args = $.args(Deno.args);`

await args.on("build", async (args) => {
  await args.on("data", (args) => {
    console.log(1);
    if (args.hasFlag("force") || args.hasFlag("f") || hasChanged()) {
     await buildData();
     console.log(2);
    }
  });
  
  // can be sync or async
  args.on("info", (args) => {
    console.log(3);
  }); 
});

args.on("version", (args) => {
  console.log(4);
});

// no match here causes a non-zero exit code that shows all the found options
> deno run -A script.ts build data
1
2
> deno run -A script.ts build data
1
> deno run -A script.ts build data --force
1
2
> deno run -A script.ts build data -f
1
2
> deno run -A script.ts build info
3
> deno run -A script.ts build other
Unknown command: build other

Possibilities:
  - build data
  - build info
> deno run -A script.ts version
4
> deno run -A script.ts invalid
Unknown command: invalid

Possibilities:
  - build
  - version
  • People could call a function on args to prevent the "unknown command" error (maybe args.markHandled() or something).
  • $.args.hasFlag("force") for --force and $.args.hasFlag("f") for -f
  • $.args.get("time"): Arg | undefined -- always requires an equals sign
  • $.args.getOrThrow("time"): Arg | undefined
    • $.args.getOrThrow("time").number()
  • $.args.throwUncapturedFlags() - Throw for any flags that haven't been captured (maybe)
@matklad
Copy link
Contributor

matklad commented Sep 6, 2023

People could call a function on args to prevent the "unknown command" error (maybe args.markHandled() or something).

One idea I've been toying with was "immediate mode" argument parser, with the API along the lines of

const force = args.bool("-f/--force", "ignore errors")
const path = args.string("--path", "path to operate on", { required: true })
args.done()

The trick would be that required --path does not return the error immediately -- it returns "" (or maybe even undefined (just blatantly lying to the type system)). The actual error is raised in .done(). The benefit here is that .done() knows the full grammar for the CLI, so it actually can emit a help message.

From the other angle, clap-style derives are actually inconvenient for quick scripts, as they force you to declare a struct type for the CLI args, while, in the script, you often need only local variables.

And I think low-effort option to add help text (or just to print the options themselves, without any human-authored help) is pretty valueable -- a common use-case are internal tools for a team of software engineers, where you don't necessary want to polish everything to be fit for the end-user, but you also don't want to bug your collegue-author in slack to learn how to use the tool.

@joehillen
Copy link

Not going to lie, but this feels outside the scope of dax. cliffy has a really good interface that is really easy to understand and create good CLI interfaces.

@dsherret
Copy link
Owner Author

dsherret commented Feb 7, 2024

I think it's in scope. Dax is meant to be a swiss army knife for automation scripts and being able to understand inputs to that script is important part of that. Both cliffy and deno_std don't really provide the kind of API I'm looking for in this case.

@balupton
Copy link

balupton commented Mar 11, 2024

Also agree out of scope. There is no necessity to couple such functionality, as it can just be composed. You could write your desired functionality as your own module.

If you want something existing, I wrote this arg parser https://github.com/bevry/argument/blob/HEAD/source/example.ts based on the patterns from a decade of writing hundreds of commands in Dorothy https://github.com/bevry/dorothy - which I'm thinking of using dax for as a replacement for bash

@dsherret
Copy link
Owner Author

dsherret commented May 4, 2024

Yeah, I'm going to close this for now (mainly because I don't have the bandwidth atm)

@dsherret dsherret closed this as not planned Won't fix, can't repro, duplicate, stale May 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants